【问题标题】:QtCreator intellisense missing when importing js files with Qt.include(...)使用 Qt.include(...) 导入 js 文件时缺少 QtCreator 智能感知
【发布时间】:2014-06-04 09:07:49
【问题描述】:

Qt Creator 是一个很好的编辑器,但有时它很令人沮丧。事实上,智能感知并不总是能正常工作。

示例项目如下所示:

//Test1.js file
function test1() {
   console.log('hi from test1');
}

//Test2.js file
Qt.include('Test1.js');
function test2() {
   console.log('hi from test2');
   test1();  
}

//Test.qml file
import QtQuick 1.1
import "Test2.js" as Test2

QtObject {
    Component.onCompleted: {
         Test2.test1(); //<--- intellisense missing here
         Test2.test2();
    }
}

麻烦:

智能感知编辑器错过了导入的Test2.js 中包含的test1 函数。 Qt.include 很简单——只要说 qml 编译器——嘿,把这个 js 文件内容复制粘贴到这里。

问题是

  1. 有什么方法可以修复这个 QtCreator 行为吗?
  2. QtCreator 插件模型是否允许将此行为添加到现有的智能感知代码中?或者这应该通过修补 QtCreator 代码库来解决?

【问题讨论】:

    标签: javascript qt qt-creator qml


    【解决方案1】:

    快速而肮脏的补丁。

    需要修补 2 个文件 source\qt-creator\src\libs\qmljs\qmljsdocument.h 和 qmljsdocument.cpp。 但是如果文件有 Qt.include,则“跟随光标下的符号”功能可能无法正常工作

    @@ -104,9 +104,13 @@ public:
    
     private:
         bool parse_helper(int kind);
    +    void parseQtInclude(QString dir, QString fileName, QString& result);
    +
    +    QList<QString> _parsedFileNames;
    
     private:
         QmlJS::Engine *_engine;
    +    QmlJS::Engine *_codeCompleteEngine;
         AST::Node *_ast;
         Bind *_bind;
         QList<QmlJS::DiagnosticMessage> _diagnosticMessages;
    
    
    @@ -168,6 +168,7 @@ QList<Language::Enum> Document::companionLanguages(Language::Enum language)
    
     Document::Document(const QString &fileName, Language::Enum language)
         : _engine(0)
    +    , _codeCompleteEngine(0)
         , _ast(0)
         , _bind(0)
         , _fileName(QDir::cleanPath(fileName))
    @@ -197,6 +198,9 @@ Document::~Document()
    
         if (_engine)
             delete _engine;
    +
    +    if (_codeCompleteEngine)
    +        delete _codeCompleteEngine;
     }
    
     Document::MutablePtr Document::create(const QString &fileName, Language::Enum language)
    @@ -337,9 +341,54 @@ public:
    
     } // anonymous namespace
    
    +void Document::parseQtInclude(QString dir, QString fileName, QString& result)
    +{
    +
    +    QFile file(dir + QDir::separator() + fileName);
    +
    +    if (_parsedFileNames.contains(file.fileName()) || !file.open(QIODevice::ReadOnly | QIODevice::Text)) {
    +        return;
    +    }
    +
    +    _parsedFileNames.append(file.fileName());
    +
    +    QFileInfo fileInfo(file);
    +    QTextStream in(&file);
    +    QString source = QString();
    +
    +    while(!in.atEnd()) {
    +        source += in.read(2048);
    +    }
    +
    +    file.close();
    +    source.remove(QLatin1String(".pragma library"));
    +
    +    int endPos = 0;
    +    int pos = source.indexOf(QLatin1String("Qt.include("), endPos);
    +
    +    while (pos >= 0 && pos + 11 < source.length()) {
    +        QChar comma = source.at(pos + 11);
    +        endPos = source.indexOf(comma + QLatin1String(")"), pos);
    +        if (endPos == -1)
    +            return;
    +
    +        QString fullStaterment = QString(source.begin() + pos, endPos - pos + 2);
    +        QString importName = QString(source.begin() + pos + 12, endPos - pos - 12);
    +
    +        parseQtInclude(fileInfo.absolutePath(), importName, result);
    +
    +        source.replace(fullStaterment, QString());
    +
    +        pos = source.indexOf(QLatin1String("Qt.include("));
    +    }
    +
    +    result += source;
    +}
    +
     bool Document::parse_helper(int startToken)
     {
         Q_ASSERT(! _engine);
    +    Q_ASSERT(! _codeCompleteEngine);
         Q_ASSERT(! _ast);
         Q_ASSERT(! _bind);
    
    @@ -349,6 +398,31 @@ bool Document::parse_helper(int startToken)
         Parser parser(_engine);
    
         QString source = _source;
    +    QString fullSource = _source;
    +
    +    int endPos = 0;
    +    int pos = fullSource.indexOf(QLatin1String("Qt.include("), endPos);
    +
    +    while (pos >= 0 && pos + 11 < fullSource.length()) {
    +        QChar comma = fullSource.at(pos + 11);
    +        endPos = fullSource.indexOf(comma + QLatin1String(")"), pos);
    +        if (endPos == -1)
    +            break;
    +
    +        QString fullStaterment = QString(fullSource.begin() + pos, endPos - pos + 2);
    +        QString importName = QString(fullSource.begin() + pos + 12, endPos - pos - 12);
    +        QString result = QString();
    +
    +        parseQtInclude(this->path(), importName, result);
    +
    +        fullSource.replace(fullStaterment, result);
    +
    +        pos = fullSource.indexOf(QLatin1String("Qt.include("));
    +        if (pos == -1 || pos + 11 == source.length())
    +            break;
    +        comma = fullSource.at(pos + 11);
    +    }
    +
         lexer.setCode(source, /*line = */ 1, /*qmlMode = */isQmlLikeLanguage(_language));
    
         CollectDirectives collectDirectives(path());
    @@ -369,9 +443,37 @@ bool Document::parse_helper(int startToken)
         }
    
         _ast = parser.rootNode();
    +    AST::Node *savedAst = _ast;
         _diagnosticMessages = parser.diagnosticMessages();
    
    +    if (endPos > 0) {
    +        _codeCompleteEngine = new Engine();
    +        Lexer lexerCodeComplete(_codeCompleteEngine);
    +        Parser parserCodeComplete(_codeCompleteEngine);
    +
    +        bool _parsed;
    +
    +        lexerCodeComplete.setCode(fullSource, /*line = */ 1, /*qmlMode = */isQmlLikeLanguage(_language));
    +        switch (startToken) {
    +        case QmlJSGrammar::T_FEED_UI_PROGRAM:
    +            _parsed = parserCodeComplete.parse();
    +            break;
    +        case QmlJSGrammar::T_FEED_JS_PROGRAM:
    +            _parsed = parserCodeComplete.parseProgram();
    +            break;
    +        case QmlJSGrammar::T_FEED_JS_EXPRESSION:
    +            _parsed = parserCodeComplete.parseExpression();
    +            break;
    +        default:
    +            Q_ASSERT(0);
    +        }
    +
    +        if (_parsed)
    +            _ast = parserCodeComplete.rootNode();
    +    }
    +
         _bind = new Bind(this, &_diagnosticMessages, collectDirectives.isLibrary, collectDirectives.imports);
    +    _ast = savedAst;
    
         return _parsedCorrectly;
     }
    

    【讨论】:

      猜你喜欢
      • 2022-08-02
      • 2012-02-09
      • 1970-01-01
      • 2016-10-16
      • 1970-01-01
      • 2012-03-06
      • 1970-01-01
      • 1970-01-01
      • 2015-01-05
      相关资源
      最近更新 更多