File indexing completed on 2024-05-19 04:42:00
0001 /* 0002 SPDX-FileCopyrightText: 2012 Aleix Pol <aleixpol@kde.org> 0003 SPDX-FileCopyrightText: 2012 Milian Wolff <mail@milianw.de> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #ifndef DECLARATIONBUILDER_H 0009 #define DECLARATIONBUILDER_H 0010 0011 #include <language/duchain/builders/abstractdeclarationbuilder.h> 0012 #include <language/duchain/builders/abstracttypebuilder.h> 0013 0014 #include "contextbuilder.h" 0015 0016 #include <util/stack.h> 0017 0018 namespace KDevelop 0019 { 0020 class ClassDeclaration; 0021 } 0022 0023 namespace QmlJS 0024 { 0025 class NodeJS; 0026 } 0027 0028 using TypeBuilder = KDevelop::AbstractTypeBuilder<QmlJS::AST::Node, QmlJS::AST::IdentifierPropertyName, ContextBuilder>; 0029 using DeclarationBuilderBase = KDevelop::AbstractDeclarationBuilder<QmlJS::AST::Node, QmlJS::AST::IdentifierPropertyName, TypeBuilder>; 0030 0031 class KDEVQMLJSDUCHAIN_EXPORT DeclarationBuilder : public DeclarationBuilderBase 0032 { 0033 friend class QmlJS::NodeJS; 0034 0035 public: 0036 explicit DeclarationBuilder(ParseSession* session); 0037 0038 KDevelop::ReferencedTopDUContext build(const KDevelop::IndexedString& url, 0039 QmlJS::AST::Node* node, 0040 const KDevelop::ReferencedTopDUContext& updateContext = KDevelop::ReferencedTopDUContext()) override; 0041 void startVisiting(QmlJS::AST::Node* node) override; 0042 0043 protected: 0044 using Visitor::visit; 0045 using Visitor::endVisit; 0046 0047 using ExportLiteralsAndNames = QList<QPair<QmlJS::AST::StringLiteral*, QString>>; 0048 0049 // Functions 0050 template<typename Decl> 0051 void declareFunction(QmlJS::AST::Node* node, 0052 bool newPrototypeContext, 0053 const KDevelop::Identifier& name, 0054 const KDevelop::RangeInRevision& nameRange, 0055 QmlJS::AST::Node* parameters, 0056 const KDevelop::RangeInRevision& parametersRange, 0057 QmlJS::AST::Node* body, 0058 const KDevelop::RangeInRevision& bodyRange); 0059 template<typename Node> 0060 void declareParameters(Node* node, QmlJS::AST::UiQualifiedId* Node::*typeFunc); 0061 void endVisitFunction(); // Set the return type of the function to void if no return statement has been encountered 0062 0063 bool visit(QmlJS::AST::FunctionDeclaration* node) override; 0064 bool visit(QmlJS::AST::FunctionExpression* node) override; 0065 bool visit(QmlJS::AST::FormalParameterList* node) override; 0066 bool visit(QmlJS::AST::UiParameterList* node) override; 0067 bool visit(QmlJS::AST::ReturnStatement* node) override; 0068 void endVisit(QmlJS::AST::FunctionDeclaration* node) override; 0069 void endVisit(QmlJS::AST::FunctionExpression* node) override; 0070 0071 // Variables 0072 /// NOTE: this visits the @p base node and its children 0073 void inferArgumentsFromCall(QmlJS::AST::Node* base, 0074 QmlJS::AST::ArgumentList* arguments); 0075 bool visit(QmlJS::AST::VariableDeclaration* node) override; 0076 void endVisit(QmlJS::AST::VariableDeclaration* node) override; 0077 bool visit(QmlJS::AST::BinaryExpression* node) override; 0078 bool visit(QmlJS::AST::CallExpression* node) override; 0079 bool visit(QmlJS::AST::NewMemberExpression* node) override; 0080 0081 // Arrays 0082 void declareFieldMember(const KDevelop::DeclarationPointer& declaration, 0083 const QString& member, 0084 QmlJS::AST::Node* node, 0085 const QmlJS::AST::SourceLocation& location); 0086 bool visit(QmlJS::AST::FieldMemberExpression* node) override; 0087 bool visit(QmlJS::AST::ArrayMemberExpression* node) override; 0088 0089 bool visit(QmlJS::AST::ObjectLiteral* node) override; 0090 bool visit(QmlJS::AST::PropertyNameAndValue* node) override; 0091 void endVisit(QmlJS::AST::PropertyNameAndValue* node) override; 0092 void endVisit(QmlJS::AST::ObjectLiteral* node) override; 0093 0094 // plugin.qmltypes 0095 void declareComponent(QmlJS::AST::UiObjectInitializer* node, 0096 const KDevelop::RangeInRevision &range, 0097 const KDevelop::Identifier &name); 0098 void declareMethod(QmlJS::AST::UiObjectInitializer* node, 0099 const KDevelop::RangeInRevision &range, 0100 const KDevelop::Identifier &name, 0101 bool isSlot, 0102 bool isSignal); 0103 void declareProperty(QmlJS::AST::UiObjectInitializer* node, 0104 const KDevelop::RangeInRevision &range, 0105 const KDevelop::Identifier &name); 0106 void declareParameter(QmlJS::AST::UiObjectInitializer* node, 0107 const KDevelop::RangeInRevision &range, 0108 const KDevelop::Identifier &name); 0109 void declareEnum(const KDevelop::RangeInRevision &range, 0110 const KDevelop::Identifier &name); 0111 void declareComponentSubclass(QmlJS::AST::UiObjectInitializer* node, 0112 const KDevelop::RangeInRevision& range, 0113 const QString& baseclass, 0114 QmlJS::AST::UiQualifiedId* qualifiedId); 0115 void declareComponentInstance(QmlJS::AST::ExpressionStatement *expression); 0116 ExportLiteralsAndNames exportedNames(QmlJS::AST::ExpressionStatement *exports); 0117 void declareExports(const ExportLiteralsAndNames& exports, 0118 KDevelop::ClassDeclaration* classdecl); 0119 0120 // UI 0121 void importDirectory(const QString& directory, QmlJS::AST::UiImport* node); 0122 void importModule(QmlJS::AST::UiImport* node); 0123 bool visit(QmlJS::AST::UiImport* node) override; 0124 0125 bool visit(QmlJS::AST::UiObjectDefinition* node) override; 0126 void endVisit(QmlJS::AST::UiObjectDefinition* node) override; 0127 0128 bool visit(QmlJS::AST::UiScriptBinding* node) override; 0129 void endVisit(QmlJS::AST::UiScriptBinding* node) override; 0130 bool visit(QmlJS::AST::UiObjectBinding* node) override; 0131 void endVisit(QmlJS::AST::UiObjectBinding* node) override; 0132 0133 bool visit(QmlJS::AST::UiPublicMember* node) override; 0134 void endVisit(QmlJS::AST::UiPublicMember* node) override; 0135 0136 protected: 0137 template<class DeclarationT> 0138 DeclarationT* openDeclaration(const KDevelop::Identifier& id, 0139 const KDevelop::RangeInRevision& newRange, 0140 DeclarationFlags flags = NoFlags) 0141 { 0142 auto* res = DeclarationBuilderBase::openDeclaration<DeclarationT>(id, newRange, flags); 0143 res->setAlwaysForceDirect(true); 0144 return res; 0145 } 0146 0147 private: 0148 void closeAndAssignType(); 0149 void registerBaseClasses(); /*!< @brief Enumerates the base classes of the current class and import their inner contexts */ 0150 void addBaseClass(KDevelop::ClassDeclaration* classDecl, const QString &name); /*!< @brief Add a base class to a class declaration */ 0151 void addBaseClass(KDevelop::ClassDeclaration* classDecl, const KDevelop::IndexedType& type); 0152 KDevelop::AbstractType::Ptr typeFromName(const QString& name); /*!< @brief Type from a general name (int, string, or a class name) */ 0153 KDevelop::AbstractType::Ptr typeFromClassName(const QString& name); /*!< @brief Type from a class name, built-in types are not supported here */ 0154 bool areTypesEqual(const KDevelop::AbstractType::Ptr& a, 0155 const KDevelop::AbstractType::Ptr& b); 0156 0157 using DeclarationBuilderBase::setComment; 0158 void setComment(QmlJS::AST::Node* node); 0159 0160 private: 0161 bool m_prebuilding; 0162 KDevelop::Stack<bool> m_skipEndVisit; 0163 }; 0164 0165 #endif // DECLARATIONBUILDER_H