[Qt-creator] Issue parsing QStringLiteral() in SpellChecker Plugin
Nikolai Kosjar
nikolai.kosjar at theqtcompany.com
Tue Jul 28 11:24:55 CEST 2015
Hiya!
On 07/25/2015 10:30 PM, Carel Combrink wrote:
> Due to the expansion of the macro, I am finding it rather hard to get the position of the words as the user sees it, not my plugin. For example if I have a mistake on "line: 8, Col: 63" (reported by QtC), my parser sees 2 instances of the word at (10:65) and (10:232).
I don't know how you get the line and column information, but you should use
the get* functions of CPlusPlus::TranslationUnit for this.
Consider to what QStringLiteral("hello there") might expand to:
auto s = ([]() -> QString { enum { Size = sizeof(u"" "hello there")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { (-1) } }, Size, 0, 0, sizeof(QStringData) }, u"" "hello there" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }());
The following code will report 4 string literals (note the u""), assuming that
document comes from CppTools::CppModelManager::documentUpdated():
if (TranslationUnit *translationUnit = document->translationUnit()) {
for (unsigned i = 0; i < translationUnit->tokenCount(); ++i) {
const Token t = translationUnit->tokenAt(i);
if (t.isStringLiteral() && t.expanded()) {
unsigned line, column;
translationUnit->getTokenStartPosition(i, &line, &column);
qDebug() << "String:" << t.spell() << "at line:" << line << "column:" << column;
}
}
}
output:
23 String: at line: 9 column: 41
24 String: hello there at line: 7 column: 29
63 String: at line: 9 column: 177
64 String: hello there at line: 7 column: 29
That's OK. You just have to ignore the duplicates. And note that u"" is a token
consisting of 3 utf16chars and you probably also want to ignore this one.
> I have started searching and looked a bit at the WrapStringLiteral class (part of CppQuickfixes) and it seems like the WrapStringLiteral::analyze() function can do what I need. I am not sure how to use this, or implement something similar.
Note that the quickfixes do operate on a slightly different document than the
one that is emitted via CppModelManager::documentUpdated(). So you can't use
that code.
> PS: I will also be very grateful if this solution can be used to also know which strings are translatable strings (enclosed in tr()).
The fast/simple solution that will work most of the time in Qt projects: Check
for the "tr" and "(" tokens before the string literal token. Note that it will
already fail for e.g.: MyClass tr("lala");
The slower/correct solution involves:
1. Finding the CallAST for tr(). Choose one of:
1.a Use an ASTVisitor for this and override visit(CallAST *ast)
See CheckSymbols::visit(CallAST *ast) for an example.
1.b Use ASTPath - see how it's used in cppquickfixes.cpp
See how ASTPath is used in cppquickfixes.cpp ("interface.path()").
2. Making a lookup on the "tr" to ensure it's the right one.
Remove the optimization line in src/libs/cplusplus/cplusplus.pro and rebuild
for a better debugging experience.
Nikolai
More information about the Qt-creator
mailing list