File indexing completed on 2024-05-05 16:41:06

0001 /*
0002     SPDX-FileCopyrightText: 2008 Niko Sams <niko.sams@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef DECLARATIONBUILDER_H
0008 #define DECLARATIONBUILDER_H
0009 
0010 #include "typebuilder.h"
0011 #include "helper.h"
0012 #include <language/duchain/classdeclaration.h>
0013 #include <language/duchain/builders/abstractdeclarationbuilder.h>
0014 
0015 namespace KDvelop
0016 {
0017 class Declaration;
0018 }
0019 namespace Php
0020 {
0021 class ParseSession;
0022 class EditorIntegrator;
0023 class ClassDeclaration;
0024 class FunctionDeclaration;
0025 class NamespaceDeclaration;
0026 
0027 typedef KDevelop::AbstractDeclarationBuilder<AstNode, IdentifierAst, TypeBuilder> DeclarationBuilderBase;
0028 
0029 /**
0030  * The DeclarationBuilder builds declarations, types and contexts for everything in a AST.
0031  *
0032  * \note Since PHP allows the usage of functions, classes and interfaces before definition,
0033  *       a \see PreDeclarationBuilder is used to get the declarations _and_ types for those.
0034  *       Thus type- and declaratoinbuilding for these is skipped in this class.
0035  */
0036 class KDEVPHPDUCHAIN_EXPORT DeclarationBuilder : public DeclarationBuilderBase
0037 {
0038 public:
0039     DeclarationBuilder(EditorIntegrator* editor)
0040         : m_currentModifers(0)
0041     {
0042         m_editor = editor;
0043         m_findVariable.find = false;
0044         m_useNamespaceType = ClassDeclarationType;
0045     }
0046     KDevelop::ReferencedTopDUContext build(const KDevelop::IndexedString& url, AstNode* node,
0047             const KDevelop::ReferencedTopDUContext& updateContext
0048             = KDevelop::ReferencedTopDUContext()) override;
0049 
0050     void startVisiting(AstNode* node) override;
0051 
0052 protected:
0053     void visitClassDeclarationStatement(ClassDeclarationStatementAst *node) override;
0054     void visitInterfaceDeclarationStatement(InterfaceDeclarationStatementAst *node) override;
0055     void visitTraitDeclarationStatement(TraitDeclarationStatementAst *node) override;
0056     void visitClassStatement(ClassStatementAst *node) override;
0057     virtual void importTraitMethods(ClassStatementAst *node);
0058     void visitClassExtends(ClassExtendsAst *node) override;
0059     void visitClassImplements(ClassImplementsAst *node) override;
0060     void visitParameterList(ParameterListAst *node) override;
0061     void visitParameter(ParameterAst *node) override;
0062     void visitFunctionDeclarationStatement(FunctionDeclarationStatementAst *node) override;
0063     void visitGenericTypeHint(GenericTypeHintAst *node) override;
0064     void visitClassVariable(ClassVariableAst *node) override;
0065     void visitConstantDeclaration(ConstantDeclarationAst *node) override;
0066     void visitClassConstantDeclaration(ClassConstantDeclarationAst *node) override;
0067     void visitTraitAliasStatement(TraitAliasStatementAst *node) override;
0068     virtual void createTraitAliasDeclarations(TraitAliasStatementAst *node, KDevelop::DeclarationPointer dec);
0069     void visitOuterTopStatement(OuterTopStatementAst* node) override;
0070     void visitAssignmentExpression(AssignmentExpressionAst* node) override;
0071     void visitAssignmentExpressionEqual(AssignmentExpressionEqualAst *node) override;
0072     void visitVariable(VariableAst* node) override;
0073     void visitFunctionCall(FunctionCallAst* node) override;
0074     void visitFunctionCallParameterList(FunctionCallParameterListAst* node) override;
0075     void visitFunctionCallParameterListElement(FunctionCallParameterListElementAst* node) override;
0076     void visitStatement(StatementAst* node) override;
0077     void visitStaticVar(StaticVarAst* node) override;
0078     void visitGlobalVar(GlobalVarAst* node) override;
0079     void visitCatchItem(CatchItemAst *node) override;
0080     void visitUnaryExpression( UnaryExpressionAst* node ) override;
0081     void visitAssignmentListElement(AssignmentListElementAst* node) override;
0082     void openNamespace(NamespaceDeclarationStatementAst* parent, IdentifierAst* node, const IdentifierPair& identifier, const KDevelop::RangeInRevision& range) override;
0083     void closeNamespace(NamespaceDeclarationStatementAst* parent, IdentifierAst* node, const IdentifierPair& identifier) override;
0084     void visitUseStatement(UseStatementAst* node) override;
0085     void visitUseNamespaceOrUseGroupedNamespace(UseNamespaceOrUseGroupedNamespaceAst* node) override;
0086     void visitNonGroupedUseNamespace(UseNamespaceOrUseGroupedNamespaceAst* node);
0087     void visitClosure(ClosureAst* node) override;
0088     void visitLexicalVar(LexicalVarAst* node) override;
0089     void visitVarExpression(VarExpressionAst* node) override;
0090 
0091     /// checks whether the body is empty (i.e. equals ";" instead of "{...}")
0092     bool isEmptyMethodBody(const MethodBodyAst* body) const {
0093         return !body || !body->statements;
0094     }
0095 
0096     void closeDeclaration() override;
0097     void classContextOpened(KDevelop::DUContext* context) override;
0098 
0099     void supportBuild(AstNode* node, KDevelop::DUContext* context = nullptr) override;
0100     void closeContext() override;
0101 
0102     /// don't forget to closeDeclaration() afterwards
0103     /// set m_currentModifers to your likings and reset it afterwards
0104     void openClassMemberDeclaration(AstNode* node, const KDevelop::QualifiedIdentifier& name);
0105 
0106     void updateCurrentType() override;
0107 
0108 private:
0109     /// because the predeclarationbuilder runs before us,
0110     /// we always "think" that we are recompiling, while this is not necessarily true
0111     bool m_actuallyRecompiling;
0112 
0113     struct FindVariableResults {
0114         /// Set this to true if you want to catch any variable in the lower AST tree
0115         bool find;
0116         /// If the found variable is accessed as an array ($var[...]) this is set to true.
0117         /// @see m_findVariable
0118         bool isArray;
0119         /// The identifier for the found variable.
0120         /// @see m_findVariable
0121         KDevelop::QualifiedIdentifier identifier;
0122         /// The identifier for the parent of the found variable. Empty if
0123         /// the found variable is not a class member.
0124         /// @see m_findVariable
0125         KDevelop::QualifiedIdentifier parentIdentifier;
0126         /// The AstNode of the found variable. Use this for declarations.
0127         /// @see m_findVariable
0128         AstNode* node;
0129 
0130         FindVariableResults();
0131     };
0132     FindVariableResults m_findVariable;
0133 
0134     /// The position of the current argument, will only be set inside function calls.
0135     int m_functionCallParameterPos;
0136     /// Type of the current function, will only be set inside function calls.
0137     KDevelop::FunctionType::Ptr m_currentFunctionType;
0138     /// The AstNode of the previous function declaration argument
0139     ParameterAst *m_functionDeclarationPreviousArgument = nullptr;
0140     /// The AstNode of the previous function call argument
0141     FunctionCallParameterListElementAst *m_functionCallPreviousArgument = nullptr;
0142     /// Type of use
0143     DeclarationType m_useNamespaceType;
0144 
0145     unsigned int m_currentModifers;
0146     QString m_lastTopStatementComment;
0147 
0148     QHash<qint64, ClassDeclaration*> m_types;
0149     QHash<qint64, FunctionDeclaration*> m_functions;
0150     QHash<qint64, NamespaceDeclaration*> m_namespaces;
0151     QVector<KDevelop::QualifiedIdentifier> m_upcomingClassVariables;
0152 
0153     /// handles common stuff for both interfaces and classes
0154     ClassDeclaration* openTypeDeclaration(IdentifierAst *name, KDevelop::ClassDeclarationData::ClassType type);
0155 
0156     /// check if this declaration is already declared
0157     bool isGlobalRedeclaration(const KDevelop::QualifiedIdentifier &identifier, AstNode *node,
0158                                DeclarationType type);
0159     /// check if a non-abstract method declaration tries to overwrite a final base method
0160     /// or whether a abstract method is redeclared
0161     /// @param ids      The identifier for the current method
0162     /// @param curClass the current class we are in
0163     /// @param node     the node we are processing, used to access modifiers and for error reporting
0164     bool isBaseMethodRedeclaration(const IdentifierPair &ids, ClassDeclaration *curClass,
0165                                    ClassStatementAst *node);
0166     /// reports a redeclaration error for the given node
0167     /// @param declaration the old declaration
0168     /// @param node        the AstNode which resembles the redeclaration
0169     void reportRedeclarationError(KDevelop::Declaration* declaration, AstNode *node);
0170 
0171     /**
0172      * Get the interesting identifiers out of a VariableAst node:
0173      * $var yields @p id = 'var', @p parent = ''
0174      * $var->asdf yields @p id = 'asdf', @p parent = 'asdf'
0175      * $var->...->foo->bar yields @p id = 'bar', @p parent => 'foo'
0176      *
0177      * @note If the parent or the identifier itself end on an array access, e.g. $var[0] or
0178      *       $var->...->parent[0]->bar, @p arrayAccess will be set to true.
0179      *
0180      * @param id the last identifier
0181      * @param parent the parent of the last identifier
0182      * @param targetNode the node of the last identifier
0183      * @param arrayAccess the node actually ends on an array access, like $node->var->..->asdf[0]
0184      */
0185     void getVariableIdentifier(VariableAst *node,
0186                                     KDevelop::QualifiedIdentifier &id,
0187                                     KDevelop::QualifiedIdentifier &parent,
0188                                     AstNode* &targetNode,
0189                                     bool &arrayAccess);
0190 
0191     /**
0192      * Declare a class member in @p parentCtx. Validates whether the current context allows
0193      * redeclaration of private/protected members.
0194      *
0195      * @param parentCtx  The class context you want to add the member to.
0196      * @param type       The type of the member.
0197      * @param identifier The identifier of the member.
0198      * @param node       The node of the member.
0199      */
0200     void declareClassMember(KDevelop::DUContext *parentCtx, KDevelop::AbstractType::Ptr type,
0201                             const KDevelop::QualifiedIdentifier& identifier, AstNode* node );
0202 
0203     /**
0204      * Declare a variable in @p parentCtx. If the variable is already defined in the
0205      * context and it's last type equals @p type, don't do anything.
0206      *
0207      * @param parentCtx  The context you want to declare the variable in.
0208      * @param type       The type of the variable
0209      * @param identifier The identifier for the variable.
0210      * @param node       The node for the variable.
0211      */
0212     void declareVariable(KDevelop::DUContext *parentCtx, KDevelop::AbstractType::Ptr type,
0213                             const KDevelop::QualifiedIdentifier& identifier, AstNode* node );
0214 
0215     /**
0216      * Wrapper that operates declares the found variable. It will declare it
0217      * either as a class member or as a variable, depending whether a parent was found.
0218      *
0219      * It will also check whether that var also exists and if so, won't do anything.
0220      *
0221      * @param type When the var gets declared, this will be it's type.
0222      *
0223      * @see m_findVariable
0224      * @see declareClassMeember
0225      * @see declareVariable
0226      */
0227     void declareFoundVariable(KDevelop::AbstractType::Ptr type);
0228 
0229     /**
0230      * Sets encountered and updates the comment when we are recompiling.
0231      */
0232     void encounter(KDevelop::Declaration* dec);
0233 
0234     bool isReservedClassName(QString className);
0235 };
0236 
0237 }
0238 
0239 #endif // DECLARATIONBUILDER_H
0240