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

0001 /*
0002     SPDX-FileCopyrightText: 2012 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef PARSESESSION_H
0008 #define PARSESESSION_H
0009 
0010 #include <qmljs/qmljsdocument.h>
0011 #include <qmljs/qmljsdialect.h>
0012 
0013 #include <serialization/indexedstring.h>
0014 #include <language/duchain/problem.h>
0015 #include <language/duchain/topducontext.h>
0016 
0017 #include "duchainexport.h"
0018 
0019 namespace KDevelop
0020 {
0021 class SimpleRange;
0022 class RangeInRevision;
0023 }
0024 
0025 using SimpleUse = QPair<KDevelop::DUContextPointer, KDevelop::RangeInRevision>;
0026 
0027 /**
0028  * This class wraps the qmljs parser and offers some helper functions
0029  * that make it simpler to use the parser in KDevelop.
0030  */
0031 class KDEVQMLJSDUCHAIN_EXPORT ParseSession
0032 {
0033 public:
0034     /**
0035      * @return a unique identifier for QML/JS documents.
0036      */
0037     static KDevelop::IndexedString languageString();
0038 
0039     /**
0040      * @return the QML/JS language corresponding to a file suffix
0041      */
0042     static QmlJS::Dialect guessLanguageFromSuffix(const QString& path);
0043 
0044     /**
0045      * Parse the given @p contents.
0046      *
0047      * @param url The url for the document you want to parse.
0048      * @param contents The contents of the document you want to parse.
0049      */
0050     ParseSession(const KDevelop::IndexedString& url, const QString& contents, int priority);
0051 
0052     /**
0053      * @return the URL of this session
0054      */
0055     KDevelop::IndexedString url() const;
0056 
0057     /**
0058      * @return The module name of this file ("/foo/QtQuick.qml" yields "QtQuick")
0059      */
0060     QString moduleName() const;
0061 
0062     /**
0063      * @return true if the document was properly parsed, false otherwise.
0064      */
0065     bool isParsedCorrectly() const;
0066 
0067     /**
0068      * @return the root AST node or null if it failed to parse.
0069      */
0070     QmlJS::AST::Node* ast() const;
0071 
0072     /**
0073      * Add a problem concerning the given range
0074      */
0075     void addProblem(QmlJS::AST::Node* node,
0076                     const QString& message,
0077                     KDevelop::IProblem::Severity severity = KDevelop::IProblem::Warning);
0078 
0079     /**
0080      * @return the problems encountered during parsing.
0081      */
0082     QList<KDevelop::ProblemPointer> problems() const;
0083 
0084     /**
0085      * @return the string representation of @p location.
0086      */
0087     QString symbolAt(const QmlJS::AST::SourceLocation& location) const;
0088 
0089     /**
0090      * @return the language of the parsed document.
0091      */
0092     QmlJS::Dialect language() const;
0093 
0094     /**
0095      * @return the comment related to the given source location or an empty string
0096      */
0097     QString commentForLocation(const QmlJS::AST::SourceLocation& location) const;
0098 
0099     /**
0100      * Convert @p location to a KDevelop::RangeInRevision and return that.
0101      */
0102     KDevelop::RangeInRevision locationToRange(const QmlJS::AST::SourceLocation& location) const;
0103 
0104     /**
0105      * Convert @p locationFrom and @p locationTo to a KDevelop::RangeInRevision and return that.
0106      */
0107     KDevelop::RangeInRevision locationsToRange(const QmlJS::AST::SourceLocation& locationFrom,
0108                                                const QmlJS::AST::SourceLocation& locationTo) const;
0109 
0110     /**
0111      * Range that starts at the end of the first token, and ends at the beginning of the second token
0112      */
0113     KDevelop::RangeInRevision locationsToInnerRange(const QmlJS::AST::SourceLocation& locationFrom,
0114                                                     const QmlJS::AST::SourceLocation& locationTo) const;
0115 
0116     /**
0117      * @return a range that spans @p fromNode and @p toNode.
0118      */
0119     KDevelop::RangeInRevision editorFindRange(QmlJS::AST::Node* fromNode, QmlJS::AST::Node* toNode) const;
0120 
0121     void setContextOnNode(QmlJS::AST::Node* node, KDevelop::DUContext* context);
0122     KDevelop::DUContext* contextFromNode(QmlJS::AST::Node* node) const;
0123 
0124     /**
0125      * Return whether all the files included by this file were already present in
0126      * the DUChain.
0127      */
0128     bool allDependenciesSatisfied() const;
0129 
0130     /**
0131      * Return the context of a given QML file, NULL if this file is not yet known
0132      * to the DUChain.
0133      *
0134      * When a file that exists is passed to this method and the file hasn't yet
0135      * been parsed, it is queued for parsing, and the current file will also be
0136      * re-parsed after it.
0137      */
0138     KDevelop::ReferencedTopDUContext contextOfFile(const QString &fileName);
0139 
0140     /**
0141      * Static version of contextOfFile. The @p url parameter is used to trigger
0142      * a reparse of @p url if @p fileName was not yet in the DUChain
0143      */
0144     static KDevelop::ReferencedTopDUContext contextOfFile(const QString& fileName,
0145                                                           const KDevelop::IndexedString& url,
0146                                                           int ownPriority);
0147 
0148     /**
0149      * Schedule for update all the files that depend on this file
0150      */
0151     void reparseImporters();
0152 
0153     /**
0154      * Schedule a document for update using the default flags of QML/JS
0155      */
0156     static void scheduleForParsing(const KDevelop::IndexedString& url, int priority);
0157 
0158     /**
0159      * Dump AST tree to stdout.
0160      */
0161     void dumpNode(QmlJS::AST::Node* node) const;
0162 
0163 private:
0164     KDevelop::IndexedString m_url;
0165     QString m_baseName;
0166     QmlJS::Document::MutablePtr m_doc;
0167     int m_ownPriority;
0168     bool m_allDependenciesSatisfied;
0169 
0170     QList<KDevelop::ProblemPointer> m_problems;
0171     using NodeToContextHash = QHash<QmlJS::AST::Node*, KDevelop::DUContextPointer>;
0172     NodeToContextHash m_astToContext;
0173 };
0174 
0175 #endif // PARSESESSION_H