File indexing completed on 2024-05-19 04:42:01
0001 /* 0002 SPDX-FileCopyrightText: 2013 Andrea Scarpino <scarpino@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "usebuilder.h" 0008 #include "expressionvisitor.h" 0009 0010 #include "helper.h" 0011 #include "parsesession.h" 0012 0013 using namespace KDevelop; 0014 0015 UseBuilder::UseBuilder(ParseSession* session) 0016 : UseBuilderBase() 0017 { 0018 m_session = session; 0019 m_nodesThatOpenedContexts.push(nullptr); // One push here, a thousand isEmpty() calls avoided later 0020 } 0021 0022 bool UseBuilder::preVisit(QmlJS::AST::Node* node) 0023 { 0024 DUContext* ctx = contextFromNode(node); 0025 0026 if (ctx && currentContext() != ctx) { 0027 openContext(ctx); 0028 m_nodesThatOpenedContexts.push(node); 0029 } 0030 0031 return true; 0032 } 0033 0034 void UseBuilder::postVisit(QmlJS::AST::Node* node) 0035 { 0036 if (m_nodesThatOpenedContexts.top() == node) { 0037 closeContext(); 0038 m_nodesThatOpenedContexts.pop(); 0039 } 0040 } 0041 0042 bool UseBuilder::visit(QmlJS::AST::FieldMemberExpression* node) 0043 { 0044 useForExpression(node, m_session->locationToRange(node->identifierToken)); 0045 return UseBuilderBase::visit(node); 0046 } 0047 0048 bool UseBuilder::visit(QmlJS::AST::IdentifierExpression* node) 0049 { 0050 useForExpression(node); 0051 return UseBuilderBase::visit(node); 0052 } 0053 0054 bool UseBuilder::visit(QmlJS::AST::UiQualifiedId* node) 0055 { 0056 useForExpression(node); 0057 return false; 0058 } 0059 0060 bool UseBuilder::visit(QmlJS::AST::UiImport* node) 0061 { 0062 Q_UNUSED(node); 0063 return false; // Don't highlight the identifiers that appear in import statements 0064 } 0065 0066 bool UseBuilder::visit(QmlJS::AST::UiScriptBinding* node) 0067 { 0068 QString propertyName = node->qualifiedId->name.toString(); 0069 0070 if (propertyName == QLatin1String("name") || 0071 propertyName == QLatin1String("type") || 0072 propertyName == QLatin1String("exports") || 0073 propertyName == QLatin1String("prototype")) { 0074 // Ignore plugin.qmltypes-specific property names. They appear a huge 0075 // number of time and are never declared anywhere. 0076 return false; 0077 } 0078 0079 return true; 0080 } 0081 0082 bool UseBuilder::visit(QmlJS::AST::UiPublicMember* node) 0083 { 0084 // node->memberType can contain a type name (if node is a property), use it 0085 DeclarationPointer decl = QmlJS::getDeclaration( 0086 QualifiedIdentifier(node->memberTypeName().toString()), 0087 currentContext() 0088 ); 0089 0090 newUse( 0091 m_session->locationToRange(node->typeToken), 0092 decl 0093 ); 0094 0095 return true; 0096 } 0097 0098 void UseBuilder::useForExpression(QmlJS::AST::Node* node, const KDevelop::RangeInRevision &range) 0099 { 0100 // ExpressionVisitor can find the type and corresponding declaration of many 0101 // kinds of expressions (identifiers, field members, special identifiers like 0102 // this or parent, etc). 0103 ExpressionVisitor visitor(currentContext()); 0104 0105 node->accept(&visitor); 0106 0107 if (visitor.lastDeclaration()) { 0108 newUse( 0109 range.isValid() ? range : m_session->locationsToRange( 0110 node->firstSourceLocation(), 0111 node->lastSourceLocation() 0112 ), 0113 visitor.lastDeclaration() 0114 ); 0115 } 0116 }