[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