File indexing completed on 2024-05-19 04:42:00

0001 /*
0002     SPDX-FileCopyrightText: 2013 Andrea Scarpino <scarpino@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef EXPRESSIONVISITOR_H
0008 #define EXPRESSIONVISITOR_H
0009 
0010 #include <util/stack.h>
0011 
0012 #include <language/duchain/builders/dynamiclanguageexpressionvisitor.h>
0013 #include <language/duchain/types/integraltype.h>
0014 #include <language/duchain/ducontext.h>
0015 
0016 #include <util/path.h>
0017 
0018 #include <qmljs/parser/qmljsast_p.h>
0019 
0020 #include "duchainexport.h"
0021 
0022 class KDEVQMLJSDUCHAIN_EXPORT ExpressionVisitor : public KDevelop::DynamicLanguageExpressionVisitor, public QmlJS::AST::Visitor
0023 {
0024 public:
0025     explicit ExpressionVisitor(KDevelop::DUContext* context);
0026 
0027     /**
0028      * Return whether the expression ends with a prototype member.
0029      *
0030      * Example of such expressions are:
0031      *
0032      * @code
0033      * Class.prototype
0034      * Module.Class.prototype
0035      * object.__proto__
0036      * @endcode
0037      *
0038      * These expressions don't point to a prototype:
0039      *
0040      * @code
0041      * Class.prototype.method
0042      * object.__proto__.member
0043      * @endcode
0044      */
0045     bool isPrototype() const;
0046 
0047     using Visitor::visit;
0048     using Visitor::endVisit;
0049 
0050 protected:
0051     bool visit(QmlJS::AST::NumericLiteral* node) override;
0052     bool visit(QmlJS::AST::StringLiteral* node) override;
0053     bool visit(QmlJS::AST::RegExpLiteral* node) override;
0054     bool visit(QmlJS::AST::TrueLiteral* node) override;
0055     bool visit(QmlJS::AST::FalseLiteral* node) override;
0056 
0057     bool visit(QmlJS::AST::ArrayLiteral* node) override;
0058     bool visit(QmlJS::AST::ObjectLiteral* node) override;
0059     bool visit(QmlJS::AST::ArrayMemberExpression* node) override;
0060     bool visit(QmlJS::AST::FieldMemberExpression* node) override;
0061 
0062     bool visit(QmlJS::AST::BinaryExpression* node) override;
0063     bool visit(QmlJS::AST::IdentifierExpression* node) override;
0064     bool visit(QmlJS::AST::UiQualifiedId* node) override;
0065     bool visit(QmlJS::AST::ThisExpression* node) override;
0066 
0067     bool visit(QmlJS::AST::FunctionExpression* node) override;
0068     bool visit(QmlJS::AST::CallExpression* node) override;
0069     bool visit(QmlJS::AST::NewMemberExpression* node) override;
0070 
0071     void postVisit(QmlJS::AST::Node* node) override;
0072 
0073 private:
0074     using KDevelop::DynamicLanguageExpressionVisitor::encounter;
0075 
0076     void encounterNothing();
0077     void encounter(KDevelop::IntegralType::CommonIntegralTypes type);
0078 
0079     void encounter(const QString &declaration, KDevelop::DUContext* context = nullptr);
0080     bool encounterParent(const QString& declaration);       // "parent" QML identifier
0081     bool encounterDeclarationInContext(const KDevelop::QualifiedIdentifier& id,
0082                                        KDevelop::DUContext* context);
0083     bool encounterDeclarationInNodeModule(const KDevelop::QualifiedIdentifier& id,
0084                                           const QString& module);
0085     bool encounterGlobalDeclaration(const KDevelop::QualifiedIdentifier& id);
0086 
0087     void encounterFieldMember(const QString &name);
0088     void encounterObjectAtLocation(const QmlJS::AST::SourceLocation &location);
0089     void instantiateCurrentDeclaration();   /*!< @brief Encounter a StructureType whose declaration is currentDeclaration() */
0090 
0091 private:
0092     int m_prototypeDepth;   // 2 = the current node is "prototype" or "__proto__". 1 = we have just closed this node. <= 0 : "__proto__" is not the last node (as in "foo.prototype.bar")
0093     KDevelop::Path m_currentDir;
0094 };
0095 
0096 #endif // EXPRESSIONVISITOR_H