Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmljssourcelocation_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
5#ifndef QQMLJSSOURCELOCATION_P_H
6#define QQMLJSSOURCELOCATION_P_H
7
8#include <QtCore/private/qglobal_p.h>
9#include <QtCore/qhashfunctions.h>
10
11//
12// W A R N I N G
13// -------------
14//
15// This file is not part of the Qt API. It exists purely as an
16// implementation detail. This header file may change from version to
17// version without notice, or even be removed.
18//
19// We mean it.
20//
21
22QT_BEGIN_NAMESPACE
23
24namespace QQmlJS {
25
27{
28 // see also Lexer::illegalFileLengthError() and its enforcement in qqmljs.g
29 static constexpr bool qSizeTypeCanHoldQuint32()
30 {
31 return sizeof(qsizetype) > sizeof(quint32);
32 }
33public:
34 explicit constexpr SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0)
37 {
38 if constexpr (!qSizeTypeCanHoldQuint32()) {
39 constexpr quint32 maxLength = quint32(std::numeric_limits<qsizetype>::max());
40
41 // note: no overflow when adding offset and length because:
42 // offset + length <= (maxLength - 1) + (maxLength - 1) = std::numeric_limits<quint32>::max()
43 Q_ASSERT_X(length < maxLength && offset < maxLength && offset + length < maxLength,
44 "QQmlJS::SourceLocation", "File size is limited to 2GB!");
45 Q_ASSERT_X(line < maxLength, "QQmlJS::SourceLocation",
46 "Line exceeded maxLength of 2^31 - 1");
47 Q_ASSERT_X(column < maxLength, "QQmlJS::SourceLocation",
48 "Column exceeded maxLength of 2^31 - 1");
49 }
50 }
51
52 static SourceLocation fromQSizeType(qsizetype offset, qsizetype length = 0, qsizetype line = 0,
53 qsizetype column = 0)
54 {
55 if constexpr (qSizeTypeCanHoldQuint32()) {
56 constexpr qsizetype maxLength = qsizetype(std::numeric_limits<quint32>::max());
57
58 Q_ASSERT_X(offset + length < maxLength, "QQmlJS::SourceLocation",
59 "File size is limited to 4GB!");
60 Q_ASSERT_X(line < maxLength, "QQmlJS::SourceLocation",
61 "Line exceeded maxLength of 2^32 - 1");
62 Q_ASSERT_X(column < maxLength, "QQmlJS::SourceLocation",
63 "Column exceeded maxLength of 2^32 - 1");
64 }
65 return SourceLocation(quint32(offset), quint32(length), quint32(line), quint32(column));
66 }
67
68private:
69 struct LocationInfo
70 {
71 quint32 offset;
72 quint32 startLine;
73 quint32 startColumn;
74 };
75
76 template <typename Predicate>
77 static LocationInfo findLocationIf(QStringView text, Predicate &&predicate,
78 const SourceLocation &startHint = SourceLocation{})
79 {
80 quint32 i = startHint.isValid() ? startHint.offset : 0;
81 quint32 endLine = startHint.isValid() ? startHint.startLine : 1;
82 quint32 endColumn = startHint.isValid() ? startHint.startColumn : 1;
83 const quint32 end = quint32(text.size());
84
85 for (; i < end; ++i) {
86 if (predicate(i, endLine, endColumn))
87 return LocationInfo{ i, endLine, endColumn };
88
89 const QChar currentChar = text.at(i);
90 const bool isLineFeed = currentChar == u'\n';
91 const bool isCarriageReturn = currentChar == u'\r';
92 // note: process the newline on the "\n" part of "\r\n", and treat "\r" as normal
93 // character
94 const bool isHalfANewline =
95 isCarriageReturn && (i + 1 < end && text.at(i + 1) == u'\n');
96
97 if (isHalfANewline || (!isCarriageReturn && !isLineFeed)) {
98 ++endColumn;
99 continue;
100 }
101
102 // catch positions after the end of the line
103 if (predicate(i, endLine, std::numeric_limits<quint32>::max()))
104 return LocationInfo{ i, endLine, endColumn };
105
106 // catch positions after the end of the file and return the last character of the last
107 // line
108 if (i == end - 1) {
109 if (predicate(i, std::numeric_limits<quint32>::max(),
110 std::numeric_limits<quint32>::max())) {
111 return LocationInfo{ i, endLine, endColumn };
112 }
113 }
114
115 ++endLine;
116 endColumn = 1;
117 }
118
119 // not found, return last position
120 return LocationInfo{ i, endLine, endColumn };
121 }
122
123public:
124 static quint32 offsetFrom(QStringView text, quint32 line, quint32 column,
125 const SourceLocation &startHint = SourceLocation{})
126 {
127 // sanity check that hint can actually be used
128 const SourceLocation hint =
129 (startHint.startLine < line
130 || (startHint.startLine == line && startHint.startColumn <= column))
131 ? startHint
132 : SourceLocation{};
133
134 const auto result = findLocationIf(
135 text,
136 [line, column](quint32, quint32 currentLine, quint32 currentColumn) {
137 return line <= currentLine && column <= currentColumn;
138 },
139 hint);
140 return result.offset;
141 }
142 static std::pair<quint32, quint32>
143 rowAndColumnFrom(QStringView text, quint32 offset,
144 const SourceLocation &startHint = SourceLocation{})
145 {
146 // sanity check that hint can actually be used
147 const SourceLocation hint = startHint.offset <= offset ? startHint : SourceLocation{};
148
149 const auto result = findLocationIf(
150 text,
151 [offset](quint32 currentOffset, quint32, quint32) {
152 return offset == currentOffset;
153 },
154 hint);
155 return std::make_pair(result.startLine, result.startColumn);
156 }
157
158 bool isValid() const { return *this != SourceLocation(); }
159
160 qsizetype begin() const { return qsizetype(offset); }
161 qsizetype end() const { return qsizetype(offset) + length; }
162
163 // Returns a zero length location at the start of the current one.
165 {
166 return SourceLocation(offset, 0, startLine, startColumn);
167 }
168 // Returns a zero length location at the end of the current one.
169 SourceLocation endZeroLengthLocation(QStringView text) const
170 {
171 auto [row, column] = rowAndColumnFrom(text, offset + length, *this);
172 return SourceLocation{ offset + length, 0, row, column };
173 }
174
175// attributes
176 // ### encode
177
178 // Those quint32 can be casted to qsizetype because the Parser aborts on files with size >=
179 // std::min(std::numeric_limits<quint32>::max(), std::numeric_limits<qsizetype>::max()).
184
185 friend size_t qHash(const SourceLocation &location, size_t seed = 0)
186 {
187 return qHashMulti(seed, location.offset, location.length,
188 location.startLine, location.startColumn);
189 }
190
191 friend bool operator==(const SourceLocation &a, const SourceLocation &b)
192 {
193 return a.offset == b.offset && a.length == b.length
194 && a.startLine == b.startLine && a.startColumn == b.startColumn;
195 }
196
197 friend bool operator!=(const SourceLocation &a, const SourceLocation &b) { return !(a == b); }
198
199 // Returns a source location starting at the beginning of l1, l2 and ending at the end of them.
200 // Ignores invalid source locations.
202 quint32 e = qMax(l1.end(), l2.end());
203 SourceLocation res;
204 if (l1.offset <= l2.offset)
205 res = (l1.isValid() ? l1 : l2);
206 else
207 res = (l2.isValid() ? l2 : l1);
208 res.length = e - res.offset;
209 return res;
210 }
211};
212
213inline static constexpr SourceLocation s_documentOrigin(0, 0, 1, 1);
214
215} // namespace QQmlJS
216
217QT_END_NAMESPACE
218
219#endif
friend size_t qHash(const SourceLocation &location, size_t seed=0)
SourceLocation startZeroLengthLocation() const
constexpr SourceLocation(quint32 offset=0, quint32 length=0, quint32 line=0, quint32 column=0)
friend bool operator!=(const SourceLocation &a, const SourceLocation &b)
static quint32 offsetFrom(QStringView text, quint32 line, quint32 column, const SourceLocation &startHint=SourceLocation{})
friend SourceLocation combine(const SourceLocation &l1, const SourceLocation &l2)
static SourceLocation fromQSizeType(qsizetype offset, qsizetype length=0, qsizetype line=0, qsizetype column=0)
SourceLocation endZeroLengthLocation(QStringView text) const
friend bool operator==(const SourceLocation &a, const SourceLocation &b)
static std::pair< quint32, quint32 > rowAndColumnFrom(QStringView text, quint32 offset, const SourceLocation &startHint=SourceLocation{})
FunctionExpression * asAnonymousFunctionDefinition(Node *n)
Definition qqmljsast.cpp:20
ClassExpression * asAnonymousClassDefinition(Node *n)
Definition qqmljsast.cpp:30
static constexpr SourceLocation s_documentOrigin(0, 0, 1, 1)