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