File indexing completed on 2024-04-28 08:26:55
0001 /* This file is part of KDevelop 0002 * 0003 * Copyright 2010 Niko Sams <niko.sams@gmail.com> 0004 * Copyright 2010 Alexander Dymo <adymo@kdevelop.org> 0005 * Copyright (C) 2011-2015 Miquel Sabaté Solà <mikisabate@gmail.com> 0006 * 0007 * This program is free software; you can redistribute it and/or modify 0008 * it under the terms of the GNU Library General Public License as 0009 * published by the Free Software Foundation; either version 2 of the 0010 * License, or (at your option) any later version. 0011 * 0012 * This program is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU General Public 0018 * License along with this program; if not, write to the 0019 * Free Software Foundation, Inc., 0020 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #ifndef RUBY_DECLARATION_BUILDER_H 0024 #define RUBY_DECLARATION_BUILDER_H 0025 0026 #include <language/duchain/builders/abstractdeclarationbuilder.h> 0027 0028 #include <duchain/builders/typebuilder.h> 0029 #include <duchain/helpers.h> 0030 #include <util/stack.h> 0031 0032 namespace ruby { 0033 0034 class ModuleDeclaration; 0035 class MethodDeclaration; 0036 0037 using DeclarationBuilderBase = 0038 KDevelop::AbstractDeclarationBuilder<Ast, NameAst, TypeBuilder>; 0039 0040 /** 0041 * @class DeclarationBuilder 0042 * 0043 * The DeclarationBuilder iterates a Ast to build declarations. 0044 */ 0045 class KDEVRUBYDUCHAIN_EXPORT DeclarationBuilder : public DeclarationBuilderBase 0046 { 0047 public: 0048 explicit DeclarationBuilder(EditorIntegrator *editor); 0049 ~DeclarationBuilder() override; 0050 0051 protected: 0052 /// Re-implemented from KDevelop::AbstractDeclarationBuilder. 0053 void closeDeclaration() override; 0054 void closeContext() override; 0055 0056 /// Re-implemented from the ContextBuilder. 0057 void startVisiting(Ast *node) override; 0058 0059 /// Methods re-implemented from AstVisitor. 0060 0061 bool declaredInContext(const QByteArray &name) const override; 0062 0063 void visitClassStatement(Ast *node) override; 0064 void visitSingletonClass(Ast *node) override; 0065 void visitModuleStatement(Ast *node) override; 0066 void visitMethodStatement(Ast *node) override; 0067 void visitParameter(Ast *node) override; 0068 void visitBlock(Ast *node) override; 0069 void visitBlockVariables(Ast *node) override; 0070 void visitReturnStatement(Ast *node) override; 0071 void visitAssignmentStatement(Ast *node) override; 0072 void visitAliasStatement(Ast *node) override; 0073 void visitMethodCall(Ast *node) override; 0074 void visitMixin(Ast *node, bool include) override; 0075 void visitForStatement(Ast *node) override; 0076 void visitAccessSpecifier(const access_t policy) override; 0077 void visitYieldStatement(Ast *node) override; 0078 void visitRescueArg(Ast *node) override; 0079 0080 private: 0081 /// @returns the range of the name of the given @p node. 0082 const KDevelop::RangeInRevision getNameRange(const Ast *node) const; 0083 0084 /** 0085 * Open a context for a class/module declaration. It will also open the 0086 * context for the eigen class. 0087 * 0088 * @param decl The declaration itself. 0089 * @param node The node where the declaration resides. 0090 */ 0091 void openContextForClassDefinition(ModuleDeclaration *decl, Ast *node); 0092 0093 /** 0094 * Open or re-open if already exists a declaration in the current context. 0095 * 0096 * @param id The qualified identifier for the declaration. 0097 * @param range The range in which the declaration is contained. 0098 * @param context The context in which the declaration is being performed. 0099 * @returns an opened declaration. It returns nullptr if something 0100 * went wrong. 0101 */ 0102 template<typename T> T * reopenDeclaration(const KDevelop::QualifiedIdentifier &id, 0103 const KDevelop::RangeInRevision &range, 0104 KDevelop::DUContext *context, 0105 DeclarationKind kind = DeclarationKind::Unknown); 0106 0107 /** 0108 * Open or re-open a method declaration in the current context. This is, 0109 * indeed, an specialization of the reopenDeclaration method. 0110 * 0111 * @param id The qualified identifier for the declaration. 0112 * @param range The range in which the declaration is contained. 0113 * @param classMethod Set to true of this is a class method, otherwise set 0114 * false if this is an instance method. 0115 * @returns an opened method declaration. It returns nullptr if something 0116 * went wrong. 0117 */ 0118 MethodDeclaration * reopenDeclaration(const KDevelop::QualifiedIdentifier &id, 0119 const KDevelop::RangeInRevision &range, 0120 bool classMethod); 0121 0122 /** 0123 * Declare a variable in the current context. 0124 * 0125 * @param id The qualified identifier of the new variable declaration. 0126 * @param type The type of the new variable declaration. 0127 * @param node The node that contains this variable declaration. 0128 */ 0129 void declareVariable(const KDevelop::QualifiedIdentifier &id, 0130 const KDevelop::AbstractType::Ptr &type, 0131 Ast *node, 0132 KDevelop::DUContext::SearchFlag flags = KDevelop::DUContext::NoSearchFlags); 0133 0134 /** 0135 * Alias a method declaration. 0136 * 0137 * @param id The id of the new method. 0138 * @param range The range of the new method. 0139 * @param decl The MethodDeclaration that it's being aliased. 0140 * @note the DUChain *must* be locked before calling this method. 0141 */ 0142 void aliasMethodDeclaration(const KDevelop::QualifiedIdentifier &id, 0143 const KDevelop::RangeInRevision &range, 0144 const MethodDeclaration *decl); 0145 0146 /// @returns the current access policy. 0147 inline KDevelop::Declaration::AccessPolicy currentAccessPolicy() const 0148 { 0149 if (m_accessPolicy.isEmpty()) { 0150 return KDevelop::Declaration::Public; 0151 } 0152 return m_accessPolicy.top(); 0153 } 0154 0155 /// Sets the current access policy to the given @p policy. 0156 inline void setAccessPolicy(KDevelop::Declaration::AccessPolicy policy) 0157 { 0158 m_accessPolicy.top() = policy; 0159 } 0160 0161 /// Module mixins helper methods. 0162 0163 /** 0164 * Get the module declaration that is being mixed-in. 0165 * 0166 * @param module The include/extend AST. 0167 * @returns the ModuleDeclaration that is being mixed-in, or nullptr if this 0168 * module doesn't actually exist. 0169 */ 0170 ModuleDeclaration * getModuleDeclaration(Ast *module) const; 0171 0172 /** 0173 * @returns the declared methods inside the given declaration @p decl, 0174 * which is a class or a module. 0175 */ 0176 QList<MethodDeclaration *> getDeclaredMethods(const KDevelop::Declaration *decl); 0177 0178 /// other stuff. 0179 0180 /** 0181 * Check whether the given declaration can be redeclared or not. 0182 * 0183 * @param decl The declaration to be redeclared. 0184 * @param id The id of the declaration. 0185 * @param range The range of the declaration. 0186 * @param kind The kind that the declaration has to have. 0187 * @returns true if it's a valid re-declaration, and false otherwise. 0188 */ 0189 bool validReDeclaration(KDevelop::Declaration *decl, 0190 const KDevelop::QualifiedIdentifier &id, 0191 const KDevelop::RangeInRevision &range, 0192 DeclarationKind kind); 0193 0194 /** 0195 * Get the context that contains the name of the class/module being 0196 * declared. If the container of the name does not exist, then the 0197 * current context is returned. For example, for the following declaration: 0198 * 0199 * class; A::B; end 0200 * 0201 * The returned context will be the internal context of A. In this same 0202 * example, if A does not exist, then the current context would've been 0203 * returned. 0204 * @param node The node of the class/module declaration. 0205 */ 0206 KDevelop::DUContext * getContainedNameContext(Ast *node); 0207 0208 /** 0209 * This is a helper method that iterates over the call args of a method 0210 * call in order to update the type of each parameter accordingly. 0211 * @param mc A list of call args. 0212 * @param lastMethod The last encountered method call. 0213 */ 0214 void visitMethodCallArgs(const Ast *mc, 0215 const KDevelop::DeclarationPointer &lastMethod); 0216 0217 /// @returns true if we're inside a class/module, false otherwise. 0218 inline bool insideClassModule() const 0219 { 0220 return m_classDeclarations.size() > 0; 0221 } 0222 0223 /// @returns the last class/module. 0224 inline KDevelop::Declaration * lastClassModule() const 0225 { 0226 return m_classDeclarations.top().data(); 0227 } 0228 0229 private: 0230 EditorIntegrator *m_editor; 0231 KDevelop::Stack<KDevelop::Declaration::AccessPolicy> m_accessPolicy; 0232 KDevelop::Stack<KDevelop::DeclarationPointer> m_classDeclarations; 0233 bool m_injected; 0234 bool m_instance; 0235 KDevelop::Declaration *m_lastMethodCall; 0236 }; 0237 0238 } 0239 0240 #endif // RUBY_DECLARATION_BUILDER_H