diff options
Diffstat (limited to 'tools/qmllint/findunqualified.cpp')
-rw-r--r-- | tools/qmllint/findunqualified.cpp | 159 |
1 files changed, 35 insertions, 124 deletions
diff --git a/tools/qmllint/findunqualified.cpp b/tools/qmllint/findunqualified.cpp index ea28884f7b..359510f5f7 100644 --- a/tools/qmllint/findunqualified.cpp +++ b/tools/qmllint/findunqualified.cpp @@ -27,6 +27,7 @@ ****************************************************************************/ #include "findunqualified.h" +#include "importedmembersvisitor.h" #include "scopetree.h" #include "typedescriptionreader.h" @@ -99,121 +100,21 @@ void FindUnqualifiedIDVisitor::parseHeaders(QQmlJS::AST::UiHeaderItemList *heade } } -void FindUnqualifiedIDVisitor::parseMembers(QQmlJS::AST::UiObjectMemberList *member, - ScopeTree *scope) -{ - using namespace QQmlJS::AST; - - // member should be the sole element - Q_ASSERT(!member->next); - Q_ASSERT(member && member->member->kind == UiObjectMember::Kind_UiObjectDefinition); - auto definition = cast<UiObjectDefinition *>(member->member); - auto qualifiedId = definition->qualifiedTypeNameId; - while (qualifiedId && qualifiedId->next) { - qualifiedId = qualifiedId->next; - } - scope->setSuperclassName(qualifiedId->name.toString()); - UiObjectMemberList *initMembers = definition->initializer->members; - while (initMembers) { - switch (initMembers->member->kind) { - case UiObjectMember::Kind_UiArrayBinding: { - // nothing to do - break; - } - case UiObjectMember::Kind_UiEnumDeclaration: { - // nothing to do - break; - } - case UiObjectMember::Kind_UiObjectBinding: { - // nothing to do - break; - } - case UiObjectMember::Kind_UiObjectDefinition: { - // creates nothing accessible - break; - } - case UiObjectMember::Kind_UiPublicMember: { - auto publicMember = cast<UiPublicMember *>(initMembers->member); - switch (publicMember->type) { - case UiPublicMember::Signal: { - UiParameterList *param = publicMember->parameters; - MetaMethod method; - method.setMethodType(MetaMethod::Signal); - method.setMethodName(publicMember->name.toString()); - while (param) { - method.addParameter(param->name.toString(), param->type->name.toString()); - param = param->next; - } - scope->addMethod(method); - break; - } - case UiPublicMember::Property: { - MetaProperty prop { - publicMember->name.toString(), - publicMember->memberType->name.toString(), - false, - false, - false, - 0 - }; - scope->addProperty(prop); - break; - } - } - break; - } - case UiObjectMember::Kind_UiScriptBinding: { - // does not create anything new, ignore - break; - } - case UiObjectMember::Kind_UiSourceElement: { - auto sourceElement = cast<UiSourceElement *>(initMembers->member); - if (FunctionExpression *fexpr = sourceElement->sourceElement->asFunctionDefinition()) { - MetaMethod method; - method.setMethodName(fexpr->name.toString()); - method.setMethodType(MetaMethod::Method); - FormalParameterList *parameters = fexpr->formals; - while (parameters) { - method.addParameter(parameters->element->bindingIdentifier.toString(), ""); - parameters = parameters->next; - } - scope->addMethod(method); - } else if (ClassExpression *clexpr = - sourceElement->sourceElement->asClassDefinition()) { - const MetaProperty prop { clexpr->name.toString(), "", false, false, false, 1 }; - scope->addProperty(prop); - } else if (cast<VariableStatement *>(sourceElement->sourceElement)) { - // nothing to do - } else { - const auto loc = sourceElement->firstSourceLocation(); - m_colorOut.writeUncolored( - "unsupportedd sourceElement at " - + QString::fromLatin1("%1:%2: ").arg(loc.startLine).arg(loc.startColumn) - + QString::number(sourceElement->sourceElement->kind)); - } - break; - } - default: { - m_colorOut.writeUncolored("unsupported element of kind " - + QString::number(initMembers->member->kind)); - } - } - initMembers = initMembers->next; - } -} - -void FindUnqualifiedIDVisitor::parseProgram(QQmlJS::AST::Program *program, ScopeTree *scope) +ScopeTree *FindUnqualifiedIDVisitor::parseProgram(QQmlJS::AST::Program *program, + const QString &name) { using namespace QQmlJS::AST; + ScopeTree *result = new ScopeTree(ScopeType::JSLexicalScope, name); for (auto *statement = program->statements; statement; statement = statement->next) { if (auto *function = cast<FunctionDeclaration *>(statement->statement)) { MetaMethod method(function->name.toString()); method.setMethodType(MetaMethod::Method); for (auto *parameters = function->formals; parameters; parameters = parameters->next) method.addParameter(parameters->element->bindingIdentifier.toString(), ""); - scope->addMethod(method); + result->addMethod(method); } } + return result; } enum ImportVersion { FullyVersioned, PartiallyVersioned, Unversioned, BasePath }; @@ -401,42 +302,47 @@ void FindUnqualifiedIDVisitor::importHelper(const QString &module, const QString ScopeTree *FindUnqualifiedIDVisitor::localFile2ScopeTree(const QString &filePath) { using namespace QQmlJS::AST; - auto scope = new ScopeTree(ScopeType::QMLScope); const QFileInfo info { filePath }; QString baseName = info.baseName(); - scope->setClassName(baseName.endsWith(".ui") ? baseName.chopped(3) : baseName); - QFile file(filePath); - if (!file.open(QFile::ReadOnly)) - return scope; - - QString code = file.readAll(); - file.close(); + const QString scopeName = baseName.endsWith(".ui") ? baseName.chopped(3) : baseName; QQmlJS::Engine engine; QQmlJS::Lexer lexer(&engine); const QString lowerSuffix = info.suffix().toLower(); - const bool isJavaScript = (lowerSuffix == QLatin1String("js") || lowerSuffix == QLatin1String("mjs")); const bool isESModule = lowerSuffix == QLatin1String("mjs"); + const bool isJavaScript = isESModule || lowerSuffix == QLatin1String("js"); + + QFile file(filePath); + if (!file.open(QFile::ReadOnly)) { + return new ScopeTree(isJavaScript ? ScopeType::JSLexicalScope : ScopeType::QMLScope, + scopeName); + } + + QString code = file.readAll(); + file.close(); + lexer.setCode(code, /*line = */ 1, /*qmlMode=*/ !isJavaScript); QQmlJS::Parser parser(&engine); const bool success = isJavaScript ? (isESModule ? parser.parseModule() : parser.parseProgram()) : parser.parse(); - if (!success) - return scope; + if (!success) { + return new ScopeTree(isJavaScript ? ScopeType::JSLexicalScope : ScopeType::QMLScope, + scopeName); + } if (!isJavaScript) { QQmlJS::AST::UiProgram *program = parser.ast(); parseHeaders(program->headers); - parseMembers(program->members, scope); - } else { - // TODO: Anything special to do with ES modules here? - parseProgram(QQmlJS::AST::cast<QQmlJS::AST::Program *>(parser.rootNode()), scope); + ImportedMembersVisitor membersVisitor(&m_colorOut); + program->members->accept(&membersVisitor); + return membersVisitor.result(scopeName); } - return scope; + // TODO: Anything special to do with ES modules here? + return parseProgram(QQmlJS::AST::cast<QQmlJS::AST::Program *>(parser.rootNode()), scopeName); } void FindUnqualifiedIDVisitor::importFileOrDirectory(const QString &fileOrDirectory, @@ -705,7 +611,9 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiPublicMember *uipm) uipm->memberType ? uipm->memberType->name.toString() : QString(), uipm->typeModifier == QLatin1String("list"), !uipm->isReadonlyMember, - false, 0); + false, + uipm->memberType ? (uipm->memberType->name == QLatin1String("alias")) : false, + 0); property.setType(m_exportedName2Scope.value(property.typeName()).get()); m_currentScope->insertPropertyIdentifier(property); return true; @@ -882,7 +790,8 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiObjectBinding *uiob) } name.chop(1); - MetaProperty prop(uiob->qualifiedId->name.toString(), name, false, true, true, 0); + MetaProperty prop(uiob->qualifiedId->name.toString(), name, false, true, true, + name == QLatin1String("alias"), 0); prop.setType(m_exportedName2Scope.value(uiob->qualifiedTypeNameId->name.toString()).get()); m_currentScope->addProperty(prop); @@ -897,7 +806,9 @@ void FindUnqualifiedIDVisitor::endVisit(QQmlJS::AST::UiObjectBinding *uiob) leaveEnvironment(); MetaProperty property(uiob->qualifiedId->name.toString(), uiob->qualifiedTypeNameId->name.toString(), - false, true, true, 0); + false, true, true, + uiob->qualifiedTypeNameId->name == QLatin1String("alias"), + 0); property.setType(childScope); m_currentScope->addProperty(property); } |