1/****************************************************************************
2**
3** Copyright (C) 2019 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#ifndef COMMENTASTVISITOR_H
30#define COMMENTASTVISITOR_H
31
32#include <QtQml/private/qqmljsastvisitor_p.h>
33#include <QtQml/private/qqmljsast_p.h>
34#include <QtQml/private/qqmljsengine_p.h>
35
36#include <QHash>
37#include <QString>
38#include <QVector>
39
40using namespace QQmlJS::AST;
41using namespace QQmlJS;
42
43struct Comment
44{
45 enum Location : int
46 {
47 Front = 1,
48 Front_Inline = Front << 1,
49 Back = Front_Inline << 1,
50 Back_Inline = Back << 1,
51 DefaultLocations = Front | Back_Inline,
52 AllLocations = Front | Back | Front_Inline | Back_Inline
53 } m_location = Front;
54
55 Comment() = default;
56 Comment(const QQmlJS::Engine *engine, Location location, QList<SourceLocation> srcLocations)
57 : m_location(location), m_srcLocations(srcLocations) {
58 for (const auto& srcLoc : srcLocations) {
59 m_text += engine->code().mid(position: static_cast<int>(srcLoc.begin()),
60 n: static_cast<int>(srcLoc.end() - srcLoc.begin())) + "\n";
61 }
62
63 m_text.chop(n: 1);
64 }
65
66 QList<SourceLocation> m_srcLocations;
67
68 bool isValid() const { return !m_srcLocations.isEmpty(); }
69 bool isMultiline() const { return m_text.contains(s: "\n"); }
70 bool isSyntheticMultiline() const { return m_srcLocations.size() > 1; }
71
72 bool contains(const SourceLocation& location) const {
73 for (const SourceLocation& srcLoc : m_srcLocations) {
74 if (srcLoc.begin() == location.begin() && srcLoc.end() == location.end())
75 return true;
76 }
77
78 return false;
79 }
80
81 quint32 endLine() const
82 {
83 if (isSyntheticMultiline() || !isValid())
84 return 0;
85
86 return m_srcLocations[0].startLine + m_text.count(c: QLatin1Char('\n'));
87 }
88
89 QString m_text;
90};
91
92class CommentAstVisitor : protected Visitor
93{
94public:
95 CommentAstVisitor(QQmlJS::Engine *engine, Node *rootNode);
96
97 void throwRecursionDepthError() override {}
98
99 const QHash<Node *, Comment> attachedComments() const { return m_attachedComments; }
100 const QHash<quint32, Comment> listComments() const { return m_listItemComments; }
101 const QHash<Node *, QVector<Comment>> orphanComments() const { return m_orphanComments; }
102
103 bool visit(UiScriptBinding *node) override;
104 bool visit(UiObjectBinding *node) override;
105
106 bool visit(UiArrayBinding *node) override;
107 void endVisit(UiArrayBinding *node) override;
108
109 bool visit(UiObjectDefinition *node) override;
110 void endVisit(UiObjectDefinition *) override;
111
112 bool visit(UiEnumDeclaration *node) override;
113 void endVisit(UiEnumDeclaration *node) override;
114
115 bool visit(UiEnumMemberList *node) override;
116
117 bool visit(StatementList *node) override;
118 void endVisit(StatementList *node) override;
119
120 bool visit(UiImport *node) override;
121 bool visit(UiPragma *node) override;
122 bool visit(UiPublicMember *node) override;
123 bool visit(FunctionDeclaration *node) override;
124private:
125 bool isCommentAttached(const SourceLocation& location) const;
126
127 QList<SourceLocation> findCommentsInLine(quint32 line, bool includePrevious = false) const;
128
129 Comment findComment(SourceLocation first, SourceLocation last,
130 int locations = Comment::DefaultLocations) const;
131
132 Comment findComment(Node *node, int locations = Comment::DefaultLocations) const;
133 QVector<Comment> findOrphanComments(Node *node) const;
134 void attachComment(Node *node, int locations = Comment::DefaultLocations);
135
136 QQmlJS::Engine *m_engine;
137 QHash<Node *, Comment> m_attachedComments;
138 QHash<quint32, Comment> m_listItemComments;
139 QHash<Node *, QVector<Comment>> m_orphanComments;
140};
141
142#endif // COMMENTASTVISITOR_H
143

source code of qtdeclarative/tools/qmlformat/commentastvisitor.h