@idlizer/core 2.1.9-arktscgen-9 → 2.1.10-arktscgen-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/src/LanguageWriters/ArgConvertors.js +5 -3
- package/build/lib/src/LanguageWriters/LanguageWriter.d.ts +7 -5
- package/build/lib/src/LanguageWriters/LanguageWriter.js +3 -1
- package/build/lib/src/LanguageWriters/convertors/CJConvertors.js +2 -1
- package/build/lib/src/LanguageWriters/convertors/InteropConvertors.js +2 -0
- package/build/lib/src/LanguageWriters/convertors/JavaConvertors.js +3 -0
- package/build/lib/src/LanguageWriters/convertors/KotlinConvertors.js +2 -0
- package/build/lib/src/LanguageWriters/convertors/TSConvertors.js +3 -1
- package/build/lib/src/LanguageWriters/writers/CJLanguageWriter.d.ts +2 -5
- package/build/lib/src/LanguageWriters/writers/CJLanguageWriter.js +8 -8
- package/build/lib/src/LanguageWriters/writers/ETSLanguageWriter.d.ts +2 -1
- package/build/lib/src/LanguageWriters/writers/ETSLanguageWriter.js +6 -0
- package/build/lib/src/LanguageWriters/writers/KotlinLanguageWriter.d.ts +2 -5
- package/build/lib/src/LanguageWriters/writers/TsLanguageWriter.d.ts +2 -5
- package/build/lib/src/config.d.ts +66 -0
- package/build/lib/src/config.js +2 -0
- package/build/lib/src/configDescriber.js +1 -1
- package/build/lib/src/diagnosticmessages.d.ts +18 -12
- package/build/lib/src/diagnosticmessages.js +22 -14
- package/build/lib/src/diagnostictypes.d.ts +3 -9
- package/build/lib/src/formatter.d.ts +2 -1
- package/build/lib/src/formatter.js +3 -3
- package/build/lib/src/from-idl/deserialize.js +139 -6
- package/build/lib/src/from-idl/parser.d.ts +99 -0
- package/build/lib/src/from-idl/parser.js +943 -0
- package/build/lib/src/idl.d.ts +13 -1
- package/build/lib/src/idl.js +6 -0
- package/build/lib/src/index.d.ts +1 -0
- package/build/lib/src/index.js +1 -0
- package/build/lib/src/peer-generation/LayoutManager.d.ts +1 -1
- package/build/lib/src/peer-generation/Materialized.d.ts +5 -3
- package/build/lib/src/peer-generation/Materialized.js +10 -7
- package/build/lib/src/peer-generation/PeerClass.d.ts +8 -2
- package/build/lib/src/peer-generation/PeerClass.js +4 -2
- package/build/lib/src/peer-generation/PeerLibrary.d.ts +1 -0
- package/build/lib/src/peer-generation/PeerLibrary.js +6 -0
- package/build/lib/src/peer-generation/PeerMethod.d.ts +9 -2
- package/build/lib/src/peer-generation/PeerMethod.js +23 -4
- package/build/lib/src/peer-generation/getSuperType.d.ts +1 -0
- package/build/lib/src/peer-generation/getSuperType.js +9 -0
- package/package.json +12 -4
|
@@ -0,0 +1,943 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from "fs";
|
|
16
|
+
import * as idl from "../idl";
|
|
17
|
+
import { DiagnosticException } from "../diagnostictypes";
|
|
18
|
+
import { DiagnosticMessageGroup, LoadingFatal, ParsingFatal, InternalFatal } from "../diagnosticmessages";
|
|
19
|
+
const DuplicateModifier = new DiagnosticMessageGroup("error", "DuplicateModifier", "Duplicate modifier", "Duplicate of");
|
|
20
|
+
const NotApplicableModifier = new DiagnosticMessageGroup("error", "NotApplicableModifier", "Not applicable modifier");
|
|
21
|
+
const DuplicatePackageDeclaration = new DiagnosticMessageGroup("error", "DuplicatePackageDeclaration", "Duplicate package declaration", "Duplicate of");
|
|
22
|
+
const DuplicateExtendedAttribute = new DiagnosticMessageGroup("error", "DuplicateExtendedAttribute", "Duplicate extended attribute", "Duplicate of");
|
|
23
|
+
const DuplicateArgumentName = new DiagnosticMessageGroup("error", "DuplicateArgumentName", "Duplicate argument name", "Duplicate of");
|
|
24
|
+
const IncorrectLiteral = new DiagnosticMessageGroup("error", "IncorrectLiteral", "Incorrect literal");
|
|
25
|
+
const IncorrectIdentifier = new DiagnosticMessageGroup("error", "IncorrectIdentifier", "Incorrect identifier");
|
|
26
|
+
const UnexpectedToken = new DiagnosticMessageGroup("error", "UnexpectedToken", "Unexpected token");
|
|
27
|
+
const UnexpectedEndOfFile = new DiagnosticMessageGroup("fatal", "UnexpectedEndOfFile", "Unexpected end of file");
|
|
28
|
+
const UnsupportedSyntax = new DiagnosticMessageGroup("error", "UnsupportedSyntax", "Unsupported syntax");
|
|
29
|
+
const WrongDeclarationPlacement = new DiagnosticMessageGroup("error", "WrongDeclarationPlacement", "Wrong declaration placement");
|
|
30
|
+
const ExpectedPrimitiveType = new DiagnosticMessageGroup("error", "ExpectedPrimitiveType", "Expected primitive type");
|
|
31
|
+
const ExpectedReferenceType = new DiagnosticMessageGroup("error", "ExpectedReferenceType", "Expected reference type");
|
|
32
|
+
const ExpectedGenericArguments = new DiagnosticMessageGroup("error", "ExpectedGenericArguments", "Expected generic arguments");
|
|
33
|
+
const UnexpectedGenericArguments = new DiagnosticMessageGroup("error", "UnexpectedGenericArguments", "Unexpected generic arguments");
|
|
34
|
+
export class FatalParserException extends Error {
|
|
35
|
+
constructor(diagnosticMessages) {
|
|
36
|
+
super();
|
|
37
|
+
this.diagnosticMessages = diagnosticMessages;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
var TokenKind;
|
|
41
|
+
(function (TokenKind) {
|
|
42
|
+
TokenKind[TokenKind["Words"] = 0] = "Words";
|
|
43
|
+
TokenKind[TokenKind["Literal"] = 1] = "Literal";
|
|
44
|
+
TokenKind[TokenKind["Symbol"] = 2] = "Symbol";
|
|
45
|
+
TokenKind[TokenKind["Comment"] = 3] = "Comment";
|
|
46
|
+
TokenKind[TokenKind["Whitespace"] = 4] = "Whitespace";
|
|
47
|
+
TokenKind[TokenKind["End"] = 5] = "End";
|
|
48
|
+
})(TokenKind || (TokenKind = {}));
|
|
49
|
+
const supportedDeclarations = new Set(["attribute", "callback", "const", "constructor", "dictionary",
|
|
50
|
+
"enum", "import", "interface", "namespace", "package", "typedef", "version"]);
|
|
51
|
+
const unsupportedDeclarations = new Set(["deleter", "getter", "includes", "inherit", "iterable", "maplike",
|
|
52
|
+
"mixin", "partial", "required", "setlike", "setter", "stringifier", "unrestricted"]);
|
|
53
|
+
const interfaceContent = new Set([idl.IDLKind.Constructor, idl.IDLKind.Const, idl.IDLKind.Property, idl.IDLKind.Method, idl.IDLKind.Callable]);
|
|
54
|
+
const globalContent = new Set([idl.IDLKind.Namespace, idl.IDLKind.Interface, idl.IDLKind.Enum, idl.IDLKind.Method, idl.IDLKind.Typedef, idl.IDLKind.Callback, idl.IDLKind.Import, idl.IDLKind.Version, idl.IDLKind.Const]);
|
|
55
|
+
const havingBlocks = new Set([idl.IDLKind.Namespace, idl.IDLKind.Interface, idl.IDLKind.Enum]);
|
|
56
|
+
const modifierTokens = new Set(["static", "readonly", "async"]);
|
|
57
|
+
// Uncomment in case of parser debugging
|
|
58
|
+
function trac(s) {
|
|
59
|
+
// console.log(s)
|
|
60
|
+
}
|
|
61
|
+
export class Parser {
|
|
62
|
+
constructor(fileName, content) {
|
|
63
|
+
var _a, _b;
|
|
64
|
+
this._curOffset = 0;
|
|
65
|
+
this._curLine = 0;
|
|
66
|
+
// TypeParameters support
|
|
67
|
+
this._generics = [];
|
|
68
|
+
// TypeArguments parsing support
|
|
69
|
+
this._enableInLiteralParsing = false;
|
|
70
|
+
// symTokens = ["(", ")", "[", "]", "{", "}", ",", "...", ":", ";", "<", "=", ">", "?"]
|
|
71
|
+
this._reDecimal = /-?(?=[0-9]*\.|[0-9]+[eE])(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/y;
|
|
72
|
+
this._reInteger = /-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/y;
|
|
73
|
+
this._reString = /"[^"]*"/y;
|
|
74
|
+
// -something is handled for -Infinity literal parsing, but rejected for identifiers later
|
|
75
|
+
this._reWords = /[-]?[_$A-Za-z][_$0-9A-Za-z]*([.][_$A-Za-z][_$0-9A-Za-z]*)*/y;
|
|
76
|
+
this._reSymbol = /\.\.\.|[()[\]{},:;<=>?]/y;
|
|
77
|
+
this._reWhitespace = /[\t\n\r ]+/y;
|
|
78
|
+
this._reComment = /\/\/.*|\/\*[\s\S]*?\*\//y;
|
|
79
|
+
// Note no sticky behavior.
|
|
80
|
+
this._reIsDocComment = /\/\/\/.*|\/\*\*[\s\S]*?\*\//;
|
|
81
|
+
this.currentModifiers = {};
|
|
82
|
+
trac("constructor");
|
|
83
|
+
this.fileName = fileName;
|
|
84
|
+
if (undefined === content) {
|
|
85
|
+
try {
|
|
86
|
+
content = fs.readFileSync(fileName).toString();
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
content = "";
|
|
90
|
+
throw new FatalParserException([LoadingFatal.reportDiagnosticMessage([{ documentPath: fileName }], (_a = e.message) !== null && _a !== void 0 ? _a : "")]);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
this.content = content;
|
|
94
|
+
const lines = (_b = content.match(/[^\r\n]*(\n|\r\n)?/g)) !== null && _b !== void 0 ? _b : [];
|
|
95
|
+
this.offsets = prepareOffsets(lines);
|
|
96
|
+
this.lines = lines.map((s) => s.replace(/(\n|\r\n)$/, ""));
|
|
97
|
+
}
|
|
98
|
+
parseIDL() {
|
|
99
|
+
var _a;
|
|
100
|
+
trac("parseIDL");
|
|
101
|
+
const previousDiagnosticsCount = DiagnosticMessageGroup.allGroupsEntries.length;
|
|
102
|
+
try {
|
|
103
|
+
this._lexerNext();
|
|
104
|
+
this._prevToken = this._curToken;
|
|
105
|
+
let file = this.parseFile();
|
|
106
|
+
file.text = this.content;
|
|
107
|
+
if (DiagnosticMessageGroup.allGroupsEntries.length != previousDiagnosticsCount) {
|
|
108
|
+
// Empty for now, messages will be added in following `catch`.
|
|
109
|
+
throw new FatalParserException();
|
|
110
|
+
}
|
|
111
|
+
return file;
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
if (!(e instanceof DiagnosticException) && !(e instanceof FatalParserException)) {
|
|
115
|
+
InternalFatal.reportDiagnosticMessage([{ documentPath: this.fileName }], (_a = e.message) !== null && _a !== void 0 ? _a : "");
|
|
116
|
+
}
|
|
117
|
+
throw new FatalParserException(DiagnosticMessageGroup.allGroupsEntries.slice(previousDiagnosticsCount));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
_match(re, kind) {
|
|
121
|
+
re.lastIndex = this._curOffset;
|
|
122
|
+
const res = re.exec(this.content);
|
|
123
|
+
if (!res) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
const value = res[0];
|
|
127
|
+
const startLine = this._curLine + 1;
|
|
128
|
+
const startCharacter = this._curOffset - this.offsets[this._curLine] + 1;
|
|
129
|
+
this._curOffset = re.lastIndex;
|
|
130
|
+
this._curLine += (value.match(/\n/g) || []).length;
|
|
131
|
+
const endLine = this._curLine + 1;
|
|
132
|
+
const endCharacter = this._curOffset - this.offsets[this._curLine];
|
|
133
|
+
const location = { documentPath: this.fileName, lines: this.lines, range: { start: { line: startLine, character: startCharacter }, end: { line: endLine, character: endCharacter } } };
|
|
134
|
+
this._curToken = { kind, value, location };
|
|
135
|
+
return this._curToken;
|
|
136
|
+
}
|
|
137
|
+
_matchComment() {
|
|
138
|
+
const token = this._match(this._reComment, TokenKind.Comment);
|
|
139
|
+
// At any parsing moment `precedingComment` represents possible comment token just before`curToken`.
|
|
140
|
+
// It can be narrowed by `_reIsDocComment` if needed.
|
|
141
|
+
if (token) {
|
|
142
|
+
this.precedingComment = token;
|
|
143
|
+
}
|
|
144
|
+
return token;
|
|
145
|
+
}
|
|
146
|
+
_lexerNext() {
|
|
147
|
+
var _a, _b, _c, _d;
|
|
148
|
+
trac("_advance");
|
|
149
|
+
this._prevToken = this._curToken;
|
|
150
|
+
this._match(this._reWhitespace, TokenKind.Whitespace);
|
|
151
|
+
this.precedingComment = undefined;
|
|
152
|
+
while (this._matchComment()) {
|
|
153
|
+
this._match(this._reWhitespace, TokenKind.Whitespace);
|
|
154
|
+
}
|
|
155
|
+
if (this._curOffset == this.content.length) {
|
|
156
|
+
const pos = { line: this._curLine + 1, character: this._curOffset - this.offsets[this._curLine] + 1 };
|
|
157
|
+
this._curToken = { kind: TokenKind.End, value: "", location: { documentPath: this.fileName, lines: this.lines, range: { start: pos, end: pos } } };
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (this._enableInLiteralParsing && this.content[this._curOffset] == "\"") {
|
|
161
|
+
// TypeArguments parsing support
|
|
162
|
+
const pos = { line: this._curLine + 1, character: this._curOffset - this.offsets[this._curLine] + 1 };
|
|
163
|
+
this._curToken = { kind: TokenKind.Symbol, value: "\"", location: { documentPath: this.fileName, lines: this.lines, range: { start: pos, end: pos } } };
|
|
164
|
+
this._curOffset += 1;
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const token = ((_d = (_c = (_b = (_a = this._match(this._reDecimal, TokenKind.Literal)) !== null && _a !== void 0 ? _a : this._match(this._reInteger, TokenKind.Literal)) !== null && _b !== void 0 ? _b : this._match(this._reString, TokenKind.Literal)) !== null && _c !== void 0 ? _c : this._match(this._reWords, TokenKind.Words)) !== null && _d !== void 0 ? _d : this._match(this._reSymbol, TokenKind.Symbol));
|
|
168
|
+
if (!token) {
|
|
169
|
+
const pos = { line: this._curLine + 1, character: this._curOffset - this.offsets[this._curLine] + 1 };
|
|
170
|
+
ParsingFatal.throwDiagnosticMessage([{ documentPath: this.fileName, lines: this.lines, range: { start: pos, end: pos } }], "Unrecognized symbols");
|
|
171
|
+
}
|
|
172
|
+
// Uncomment in case of parser debugging
|
|
173
|
+
// if (token) {
|
|
174
|
+
// const visTok = {...token, location: {...token.location, lines: undefined, documentPath: undefined}}
|
|
175
|
+
// console.log(`Token: ${JSON.stringify(visTok)}`)
|
|
176
|
+
// }
|
|
177
|
+
}
|
|
178
|
+
get curToken() {
|
|
179
|
+
return this._curToken;
|
|
180
|
+
}
|
|
181
|
+
get curKind() {
|
|
182
|
+
return this._curToken.kind;
|
|
183
|
+
}
|
|
184
|
+
get curValue() {
|
|
185
|
+
return this._curToken.value;
|
|
186
|
+
}
|
|
187
|
+
get curLocation() {
|
|
188
|
+
return this.curToken.location;
|
|
189
|
+
}
|
|
190
|
+
see(tok) {
|
|
191
|
+
return this.curValue == tok;
|
|
192
|
+
}
|
|
193
|
+
seeAndSkip(tok) {
|
|
194
|
+
if (this.curValue == tok) {
|
|
195
|
+
this._lexerNext();
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
seeEof() {
|
|
201
|
+
return this.curToken.kind == TokenKind.End;
|
|
202
|
+
}
|
|
203
|
+
skip(tok) {
|
|
204
|
+
if (this.curValue != tok) {
|
|
205
|
+
if (this.curKind == TokenKind.End) {
|
|
206
|
+
UnexpectedEndOfFile.throwDiagnosticMessage([this.curLocation], `Unexpected end of file, expected "${tok}"`);
|
|
207
|
+
}
|
|
208
|
+
UnexpectedToken.throwDiagnosticMessage([this.curLocation], `Unexpected token, expected "${tok}"`);
|
|
209
|
+
}
|
|
210
|
+
this._lexerNext();
|
|
211
|
+
}
|
|
212
|
+
skipToAfter(tok) {
|
|
213
|
+
trac("skipToAfter");
|
|
214
|
+
while (!this.see(tok) && !this.seeEof()) {
|
|
215
|
+
this._lexerNext();
|
|
216
|
+
}
|
|
217
|
+
if (!this.seeEof()) {
|
|
218
|
+
this._lexerNext();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
trackLocation() {
|
|
222
|
+
trac("trackLocation");
|
|
223
|
+
const start = this.curLocation;
|
|
224
|
+
return () => {
|
|
225
|
+
const end = this._prevToken.location;
|
|
226
|
+
return {
|
|
227
|
+
documentPath: this.fileName,
|
|
228
|
+
range: { start: start.range.start, end: end.range.end },
|
|
229
|
+
lines: this.lines
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
consumeCurrentExtended() {
|
|
234
|
+
const ext = this._internalCurrentExtended;
|
|
235
|
+
this._internalCurrentExtended = undefined;
|
|
236
|
+
return ext;
|
|
237
|
+
}
|
|
238
|
+
assertPossibleModifiers(...mods) {
|
|
239
|
+
for (const k of Object.keys(this.currentModifiers)) {
|
|
240
|
+
if (!mods.includes(k)) {
|
|
241
|
+
NotApplicableModifier.reportDiagnosticMessage([this.currentModifiers[k].location]);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
parseSingleIdentifier() {
|
|
246
|
+
trac("parseSingleIdentifier");
|
|
247
|
+
const token = this.parseFullIdentifier();
|
|
248
|
+
if (token.value.includes(".")) {
|
|
249
|
+
IncorrectIdentifier.throwDiagnosticMessage([this.curLocation]);
|
|
250
|
+
}
|
|
251
|
+
return token;
|
|
252
|
+
}
|
|
253
|
+
parseFullIdentifier() {
|
|
254
|
+
trac("parseFullIdentifier");
|
|
255
|
+
if (this.curKind != TokenKind.Words || literalTypes.has(this.curValue) && this.curValue != "undefined") {
|
|
256
|
+
UnexpectedToken.throwDiagnosticMessage([this.curLocation], "Unexpected token, expected identifier");
|
|
257
|
+
}
|
|
258
|
+
if (this.curValue.startsWith("-")) {
|
|
259
|
+
// Valid for identifiers in WebIDL, but not in Idlize
|
|
260
|
+
IncorrectIdentifier.throwDiagnosticMessage([this.curLocation]);
|
|
261
|
+
}
|
|
262
|
+
const token = this.curToken;
|
|
263
|
+
this._lexerNext();
|
|
264
|
+
return token;
|
|
265
|
+
}
|
|
266
|
+
parseFullIdentifierOrLiteral() {
|
|
267
|
+
trac("parseFullIdentifierOrLiteral");
|
|
268
|
+
if (this.curKind != TokenKind.Words && this.curKind != TokenKind.Literal) {
|
|
269
|
+
UnexpectedToken.throwDiagnosticMessage([this.curLocation], "Unexpected token, expected identifier or literal");
|
|
270
|
+
}
|
|
271
|
+
const token = this.curToken;
|
|
272
|
+
this._lexerNext();
|
|
273
|
+
return token;
|
|
274
|
+
}
|
|
275
|
+
parseLiteral() {
|
|
276
|
+
trac("parseLiteral");
|
|
277
|
+
if (this.curKind != TokenKind.Literal && !literalTypes.has(this.curValue)) {
|
|
278
|
+
UnexpectedToken.throwDiagnosticMessage([this.curLocation], "Unexpected token, expected literal");
|
|
279
|
+
}
|
|
280
|
+
const token = this.curToken;
|
|
281
|
+
this._lexerNext();
|
|
282
|
+
return token;
|
|
283
|
+
}
|
|
284
|
+
parseAndPushGenerics(ext) {
|
|
285
|
+
var _a;
|
|
286
|
+
const gen = (_a = extractTypeParameters(ext)) !== null && _a !== void 0 ? _a : [];
|
|
287
|
+
if (this.seeAndSkip("<")) {
|
|
288
|
+
let next = false;
|
|
289
|
+
while (!this.seeAndSkip(">")) {
|
|
290
|
+
if (next) {
|
|
291
|
+
this.skip(",");
|
|
292
|
+
}
|
|
293
|
+
next = true;
|
|
294
|
+
gen.push(this.parseSingleIdentifier().value);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// To be restored in parseDeclaration
|
|
298
|
+
this._generics.push(gen);
|
|
299
|
+
return gen;
|
|
300
|
+
}
|
|
301
|
+
hasGeneric(name) {
|
|
302
|
+
return this._generics.some(x => x.includes(name));
|
|
303
|
+
}
|
|
304
|
+
parseFile() {
|
|
305
|
+
var _a;
|
|
306
|
+
trac("parseFile");
|
|
307
|
+
const entries = [];
|
|
308
|
+
while (!this.seeEof()) {
|
|
309
|
+
const entry = this.parseDeclaration(idl.IDLKind.File);
|
|
310
|
+
if (entry) {
|
|
311
|
+
entries.push(entry);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return idl.createFile(entries, this.fileName, (_a = this.currentPackage) === null || _a === void 0 ? void 0 : _a.split("."), { nodeLocation: { documentPath: this.fileName, lines: this.lines } });
|
|
315
|
+
}
|
|
316
|
+
parseDeclaration(scopeKind) {
|
|
317
|
+
trac("parseDeclaration");
|
|
318
|
+
const genericsLevel = this._generics.length;
|
|
319
|
+
try {
|
|
320
|
+
const decl = this.parseDeclarationUnsafe(scopeKind);
|
|
321
|
+
if (!decl) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (scopeKind == idl.IDLKind.Interface ? !interfaceContent.has(decl.kind) : !globalContent.has(decl.kind)) {
|
|
325
|
+
// Prefer shorter location ranges for blocks for now
|
|
326
|
+
const location = havingBlocks.has(decl.kind) ? decl.nameLocation : decl.nodeLocation;
|
|
327
|
+
WrongDeclarationPlacement.reportDiagnosticMessage([location], `Wrong declaration placement: ${decl.kind} not allowed in ${scopeKind}`);
|
|
328
|
+
}
|
|
329
|
+
return decl;
|
|
330
|
+
}
|
|
331
|
+
catch (e) {
|
|
332
|
+
if (e instanceof DiagnosticException && e.diagnosticMessage.severity != "fatal") {
|
|
333
|
+
this.skipToAfter(";");
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
throw e;
|
|
337
|
+
}
|
|
338
|
+
finally {
|
|
339
|
+
while (this._generics.length > genericsLevel) {
|
|
340
|
+
this._generics.pop();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
parseDeclarationUnsafe(scopeKind) {
|
|
345
|
+
trac("parseDeclarationUnsafe");
|
|
346
|
+
this._internalCurrentExtended = this.parseExtendedAttributes();
|
|
347
|
+
this.currentModifiers = {};
|
|
348
|
+
while (modifierTokens.has(this.curValue)) {
|
|
349
|
+
if (this.currentModifiers[this.curValue]) {
|
|
350
|
+
DuplicateModifier.reportDiagnosticMessage([this.curLocation]);
|
|
351
|
+
}
|
|
352
|
+
this.currentModifiers[this.curValue] = this.curToken;
|
|
353
|
+
this._lexerNext();
|
|
354
|
+
}
|
|
355
|
+
if (unsupportedDeclarations.has(this.curValue)) {
|
|
356
|
+
UnsupportedSyntax.throwDiagnosticMessage([this.curLocation]);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (supportedDeclarations.has(this.curValue)) {
|
|
360
|
+
if (this.curValue != "attribute") {
|
|
361
|
+
this.assertPossibleModifiers();
|
|
362
|
+
}
|
|
363
|
+
switch (this.curValue) {
|
|
364
|
+
case "attribute":
|
|
365
|
+
this.assertPossibleModifiers("static", "readonly");
|
|
366
|
+
return this.parseAttribute();
|
|
367
|
+
case "callback":
|
|
368
|
+
return this.parseCallback();
|
|
369
|
+
case "const":
|
|
370
|
+
return this.parseConst();
|
|
371
|
+
case "constructor":
|
|
372
|
+
return this.parseConstructor();
|
|
373
|
+
case "dictionary":
|
|
374
|
+
return this.parseDictionary();
|
|
375
|
+
case "enum":
|
|
376
|
+
return this.parseEnum();
|
|
377
|
+
case "import":
|
|
378
|
+
return this.parseImport();
|
|
379
|
+
case "interface":
|
|
380
|
+
return this.parseInterface();
|
|
381
|
+
case "namespace":
|
|
382
|
+
return this.parseNamespace();
|
|
383
|
+
case "package":
|
|
384
|
+
{
|
|
385
|
+
const pack = this.parsePackage();
|
|
386
|
+
if (this.currentPackage) {
|
|
387
|
+
DuplicatePackageDeclaration.reportDiagnosticMessage([pack.location]);
|
|
388
|
+
}
|
|
389
|
+
this.currentPackage = pack.name;
|
|
390
|
+
if (scopeKind != idl.IDLKind.File) {
|
|
391
|
+
WrongDeclarationPlacement.reportDiagnosticMessage([pack.location], `Wrong declaration placement: package is not allowed in ${scopeKind}`);
|
|
392
|
+
}
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
case "typedef":
|
|
396
|
+
return this.parseTypedef();
|
|
397
|
+
case "version":
|
|
398
|
+
return this.parseVersion();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
this.assertPossibleModifiers("static", "async");
|
|
403
|
+
return this.parseOperation();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
parseNamespace() {
|
|
407
|
+
trac("parseNamespace");
|
|
408
|
+
const sloc = this.trackLocation();
|
|
409
|
+
const ext = this.consumeCurrentExtended();
|
|
410
|
+
this.skip("namespace");
|
|
411
|
+
const name = this.parseSingleIdentifier();
|
|
412
|
+
const entries = [];
|
|
413
|
+
this.skip("{");
|
|
414
|
+
while (!this.seeAndSkip("}")) {
|
|
415
|
+
const entry = this.parseDeclaration(idl.IDLKind.Namespace);
|
|
416
|
+
if (entry) {
|
|
417
|
+
entries.push(entry);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
this.skip(";");
|
|
421
|
+
return idl.createNamespace(name.value, entries, { extendedAttributes: ext, nodeLocation: sloc(), nameLocation: name.location });
|
|
422
|
+
}
|
|
423
|
+
parseInterface() {
|
|
424
|
+
trac("parseInterface");
|
|
425
|
+
const sloc = this.trackLocation();
|
|
426
|
+
const ext = this.consumeCurrentExtended();
|
|
427
|
+
this.skip("interface");
|
|
428
|
+
const typeParameters = this.parseAndPushGenerics(ext);
|
|
429
|
+
const name = this.parseSingleIdentifier();
|
|
430
|
+
let bases = [];
|
|
431
|
+
if (this.seeAndSkip(":")) {
|
|
432
|
+
const typeList = this.parseTypeList();
|
|
433
|
+
for (const type of typeList) {
|
|
434
|
+
if (idl.isReferenceType(type)) {
|
|
435
|
+
bases.push(type);
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
ExpectedReferenceType.reportDiagnosticMessage([type.nodeLocation]);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const entries = [];
|
|
443
|
+
this.skip("{");
|
|
444
|
+
while (!this.seeAndSkip("}")) {
|
|
445
|
+
const entry = this.parseDeclaration(idl.IDLKind.Interface);
|
|
446
|
+
if (entry) {
|
|
447
|
+
if (idl.isMethod(entry)) {
|
|
448
|
+
entry.isFree = false;
|
|
449
|
+
}
|
|
450
|
+
entries.push(entry);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
this.skip(";");
|
|
454
|
+
return idl.createInterface(name.value, extractInterfaceSubkind(ext), bases, entries.filter(idl.isConstructor), entries.filter(idl.isConstant), entries.filter(idl.isProperty), entries.filter(idl.isMethod), entries.filter(idl.isCallable), typeParameters, { extendedAttributes: ext, documentation: extractDocumentation(ext), nodeLocation: sloc(), nameLocation: name.location });
|
|
455
|
+
}
|
|
456
|
+
parseExtendedAttributes() {
|
|
457
|
+
trac("parseExtendedAttributes");
|
|
458
|
+
// For future extensions: here is also a good point for doc comments handling
|
|
459
|
+
if (!this.seeAndSkip("[")) {
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
const ext = [];
|
|
463
|
+
const names = new Set();
|
|
464
|
+
const duplicates = new Set();
|
|
465
|
+
let next = false;
|
|
466
|
+
while (!this.seeAndSkip("]")) {
|
|
467
|
+
if (next) {
|
|
468
|
+
this.skip(",");
|
|
469
|
+
}
|
|
470
|
+
next = true;
|
|
471
|
+
const name = this.parseSingleIdentifier();
|
|
472
|
+
if (names.has(name.value)) {
|
|
473
|
+
duplicates.add(name.value);
|
|
474
|
+
}
|
|
475
|
+
names.add(name.value);
|
|
476
|
+
if (name.value == idl.IDLExtendedAttributes.TypeArguments) {
|
|
477
|
+
// TypeArguments parsing support
|
|
478
|
+
try {
|
|
479
|
+
this._enableInLiteralParsing = true;
|
|
480
|
+
this.skip("=");
|
|
481
|
+
const vloc = this.trackLocation();
|
|
482
|
+
const start = this._curOffset; // Already after first quote
|
|
483
|
+
this.skip("\"");
|
|
484
|
+
const types = this.parseTypeList();
|
|
485
|
+
const end = this._curOffset - 1; // Already after second quote
|
|
486
|
+
this._enableInLiteralParsing = false;
|
|
487
|
+
this.skip("\"");
|
|
488
|
+
const stringValue = this.content.slice(start, end);
|
|
489
|
+
ext.push({ name: name.value, value: stringValue, typesValue: types, nameLocation: name.location, valueLocation: vloc() });
|
|
490
|
+
}
|
|
491
|
+
catch (e) {
|
|
492
|
+
this.skipToAfter("\"");
|
|
493
|
+
throw e;
|
|
494
|
+
}
|
|
495
|
+
finally {
|
|
496
|
+
this._enableInLiteralParsing = false;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
let value;
|
|
501
|
+
if (this.seeAndSkip("=")) {
|
|
502
|
+
value = this.parseFullIdentifierOrLiteral();
|
|
503
|
+
}
|
|
504
|
+
const converted = value ? valueFromIdentifierOrLiteral(value) : undefined;
|
|
505
|
+
ext.push({ name: name.value, value: converted, nameLocation: name.location, valueLocation: value === null || value === void 0 ? void 0 : value.location });
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
for (const dup of duplicates) {
|
|
509
|
+
DuplicateExtendedAttribute.reportDiagnosticMessage(ext.filter(x => x.name == dup).map(x => x.nameLocation));
|
|
510
|
+
}
|
|
511
|
+
return ext;
|
|
512
|
+
}
|
|
513
|
+
parseTypeList() {
|
|
514
|
+
trac("parseTypeList");
|
|
515
|
+
const types = [this.parseType()];
|
|
516
|
+
while (this.seeAndSkip(",")) {
|
|
517
|
+
types.push(this.parseType());
|
|
518
|
+
}
|
|
519
|
+
return types;
|
|
520
|
+
}
|
|
521
|
+
parseType(outerExt) {
|
|
522
|
+
var _a;
|
|
523
|
+
// Tuned for IDLize types, no support for legacy combinations like "unsigned short"
|
|
524
|
+
trac("parseType");
|
|
525
|
+
const parsedExt = this.parseExtendedAttributes();
|
|
526
|
+
const ext = parsedExt ? (outerExt ? parsedExt.concat(outerExt) : parsedExt) : (outerExt ? [...outerExt] : undefined);
|
|
527
|
+
const sloc = this.trackLocation();
|
|
528
|
+
if (this.seeAndSkip("(")) {
|
|
529
|
+
let combinedTypes = [];
|
|
530
|
+
let next = false;
|
|
531
|
+
while (!this.seeAndSkip(")")) {
|
|
532
|
+
if (next) {
|
|
533
|
+
this.skip("or");
|
|
534
|
+
}
|
|
535
|
+
next = true;
|
|
536
|
+
combinedTypes.push(this.parseType());
|
|
537
|
+
}
|
|
538
|
+
const isNullable = this.seeAndSkip("?") || combinedTypes.includes(idl.IDLUndefinedType);
|
|
539
|
+
combinedTypes = combinedTypes.filter(x => x !== idl.IDLUndefinedType);
|
|
540
|
+
const distilledType = combinedTypes.length == 1
|
|
541
|
+
? combinedTypes[0]
|
|
542
|
+
: idl.createUnionType(combinedTypes, undefined, { extendedAttributes: ext, nodeLocation: sloc() });
|
|
543
|
+
if (isNullable) {
|
|
544
|
+
return idl.createOptionalType(distilledType, { extendedAttributes: ext, nodeLocation: sloc() });
|
|
545
|
+
}
|
|
546
|
+
return distilledType;
|
|
547
|
+
}
|
|
548
|
+
const name = this.parseFullIdentifier();
|
|
549
|
+
const genArgs = (_a = extractTypeArguments(ext)) !== null && _a !== void 0 ? _a : [];
|
|
550
|
+
if (this.seeAndSkip("<")) {
|
|
551
|
+
let next = false;
|
|
552
|
+
while (!this.seeAndSkip(">")) {
|
|
553
|
+
if (next) {
|
|
554
|
+
this.skip(",");
|
|
555
|
+
}
|
|
556
|
+
next = true;
|
|
557
|
+
genArgs.push(this.parseType());
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
let type;
|
|
561
|
+
if (this.hasGeneric(name.value)) {
|
|
562
|
+
if (genArgs.length > 0) {
|
|
563
|
+
UnexpectedGenericArguments.reportDiagnosticMessage([name.location]);
|
|
564
|
+
}
|
|
565
|
+
type = idl.createTypeParameterReference(name.value, { extendedAttributes: ext, nodeLocation: sloc(), nameLocation: name.location });
|
|
566
|
+
}
|
|
567
|
+
else if (builtinTypes.has(name.value)) {
|
|
568
|
+
if (genArgs.length > 0) {
|
|
569
|
+
UnexpectedGenericArguments.reportDiagnosticMessage([name.location]);
|
|
570
|
+
}
|
|
571
|
+
type = builtinTypes.get(name.value);
|
|
572
|
+
}
|
|
573
|
+
else if (builtinGenericTypeNames.has(name.value)) {
|
|
574
|
+
if (genArgs.length == 0) {
|
|
575
|
+
ExpectedGenericArguments.reportDiagnosticMessage([name.location]);
|
|
576
|
+
}
|
|
577
|
+
type = idl.createContainerType(name.value, genArgs, { extendedAttributes: ext, nodeLocation: sloc(), nameLocation: name.location });
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
type = idl.createReferenceType(name.value, genArgs.length > 0 ? genArgs : undefined, { extendedAttributes: ext, nodeLocation: sloc(), nameLocation: name.location });
|
|
581
|
+
}
|
|
582
|
+
const isNullable = this.seeAndSkip("?");
|
|
583
|
+
if (isNullable) {
|
|
584
|
+
return idl.createOptionalType(type, { extendedAttributes: ext, nodeLocation: sloc() });
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
return type;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
parseReferenceType() {
|
|
591
|
+
trac("parseReferenceType");
|
|
592
|
+
const type = this.parseType();
|
|
593
|
+
if (!idl.isReferenceType(type)) {
|
|
594
|
+
ExpectedReferenceType.reportDiagnosticMessage([type.nodeLocation]);
|
|
595
|
+
}
|
|
596
|
+
return type;
|
|
597
|
+
}
|
|
598
|
+
parsePrimitiveType() {
|
|
599
|
+
trac("parsePrimitiveType");
|
|
600
|
+
const type = this.parseType();
|
|
601
|
+
if (!idl.isPrimitiveType(type)) {
|
|
602
|
+
ExpectedPrimitiveType.reportDiagnosticMessage([type.nodeLocation]);
|
|
603
|
+
}
|
|
604
|
+
return type;
|
|
605
|
+
}
|
|
606
|
+
parseArgTuple() {
|
|
607
|
+
trac("parseArgTuple");
|
|
608
|
+
const args = [];
|
|
609
|
+
const names = new Set();
|
|
610
|
+
const duplicates = new Set();
|
|
611
|
+
this.skip("(");
|
|
612
|
+
let next = false;
|
|
613
|
+
while (!this.seeAndSkip(")")) {
|
|
614
|
+
if (next) {
|
|
615
|
+
this.skip(",");
|
|
616
|
+
}
|
|
617
|
+
next = true;
|
|
618
|
+
const arg = this.parseArg();
|
|
619
|
+
if (names.has(arg.name)) {
|
|
620
|
+
duplicates.add(arg.name);
|
|
621
|
+
}
|
|
622
|
+
names.add(arg.name);
|
|
623
|
+
args.push(arg);
|
|
624
|
+
}
|
|
625
|
+
for (const dup of duplicates) {
|
|
626
|
+
DuplicateArgumentName.reportDiagnosticMessage(args.filter(x => x.name == dup).map(x => x.nameLocation));
|
|
627
|
+
}
|
|
628
|
+
return args;
|
|
629
|
+
}
|
|
630
|
+
parseArg() {
|
|
631
|
+
trac("parseArg");
|
|
632
|
+
const ext = this.parseExtendedAttributes();
|
|
633
|
+
const sloc = this.trackLocation();
|
|
634
|
+
const optional = this.seeAndSkip("optional");
|
|
635
|
+
// Note `extendedAttributes` forwarding
|
|
636
|
+
const type = this.parseType(ext);
|
|
637
|
+
const spread = this.seeAndSkip("...");
|
|
638
|
+
const name = this.parseSingleIdentifier();
|
|
639
|
+
// Note absense of `extendedAttributes`, they are only forwarded to `type`, as it was in the old parsing code
|
|
640
|
+
return idl.createParameter(name.value, type, optional, spread, { nodeLocation: sloc(), nameLocation: name.location });
|
|
641
|
+
}
|
|
642
|
+
parseOperation() {
|
|
643
|
+
trac("parseOperation");
|
|
644
|
+
const sloc = this.trackLocation();
|
|
645
|
+
const ext = this.consumeCurrentExtended();
|
|
646
|
+
const isStatic = !!this.currentModifiers.static;
|
|
647
|
+
const isAsync = !!this.currentModifiers.async;
|
|
648
|
+
const isOptional = extractOptional(ext);
|
|
649
|
+
const isFree = true; // Will be set to false in parseInterface if method is declared within interface
|
|
650
|
+
const typeParameters = this.parseAndPushGenerics(ext);
|
|
651
|
+
// Note `extendedAttributes` forwarding
|
|
652
|
+
const retType = this.parseType(ext);
|
|
653
|
+
const name = this.parseSingleIdentifier();
|
|
654
|
+
const args = this.parseArgTuple();
|
|
655
|
+
this.skip(";");
|
|
656
|
+
if (ext === null || ext === void 0 ? void 0 : ext.some(x => x.name == idl.IDLExtendedAttributes.CallSignature)) {
|
|
657
|
+
return idl.createCallable(name.value, args, retType, { isStatic, isAsync }, { extendedAttributes: ext, documentation: extractDocumentation(ext), nodeLocation: sloc(), nameLocation: name.location }, typeParameters);
|
|
658
|
+
}
|
|
659
|
+
return idl.createMethod(name.value, args, retType, { isStatic, isAsync, isOptional, isFree }, { extendedAttributes: ext, documentation: extractDocumentation(ext), nodeLocation: sloc(), nameLocation: name.location }, typeParameters);
|
|
660
|
+
}
|
|
661
|
+
parseConstructor() {
|
|
662
|
+
trac("parseConstructor");
|
|
663
|
+
const sloc = this.trackLocation();
|
|
664
|
+
const ext = this.consumeCurrentExtended();
|
|
665
|
+
this.skip("constructor");
|
|
666
|
+
const args = this.parseArgTuple();
|
|
667
|
+
this.skip(";");
|
|
668
|
+
return idl.createConstructor(args, undefined, { extendedAttributes: ext, documentation: extractDocumentation(ext), nodeLocation: sloc() });
|
|
669
|
+
}
|
|
670
|
+
parseConst() {
|
|
671
|
+
trac("parseConst");
|
|
672
|
+
const sloc = this.trackLocation();
|
|
673
|
+
const ext = this.consumeCurrentExtended();
|
|
674
|
+
this.skip("const");
|
|
675
|
+
const type = this.parseType();
|
|
676
|
+
const name = this.parseSingleIdentifier();
|
|
677
|
+
this.skip("=");
|
|
678
|
+
const value = this.parseLiteral();
|
|
679
|
+
const extracted = extractLiteral(value);
|
|
680
|
+
this.skip(";");
|
|
681
|
+
return idl.createConstant(name.value, type, extracted.extractedString, { extendedAttributes: ext, nodeLocation: sloc(), nameLocation: name.location, valueLocation: value.location });
|
|
682
|
+
}
|
|
683
|
+
parseAttribute() {
|
|
684
|
+
trac("parseAttribute");
|
|
685
|
+
const sloc = this.trackLocation();
|
|
686
|
+
const ext = this.consumeCurrentExtended();
|
|
687
|
+
const isReadonly = !!this.currentModifiers.readonly;
|
|
688
|
+
const isStatic = !!this.currentModifiers.static;
|
|
689
|
+
const isOptional = extractOptional(ext);
|
|
690
|
+
this.skip("attribute");
|
|
691
|
+
const type = this.parseType();
|
|
692
|
+
const name = this.parseSingleIdentifier();
|
|
693
|
+
this.skip(";");
|
|
694
|
+
return idl.createProperty(name.value, type, isReadonly, isStatic, isOptional, { extendedAttributes: ext, documentation: extractDocumentation(ext), nodeLocation: sloc(), nameLocation: name.location });
|
|
695
|
+
}
|
|
696
|
+
parseTypedef() {
|
|
697
|
+
trac("parseTypedef");
|
|
698
|
+
const sloc = this.trackLocation();
|
|
699
|
+
const ext = this.consumeCurrentExtended();
|
|
700
|
+
this.skip("typedef");
|
|
701
|
+
const typeParameters = this.parseAndPushGenerics(ext);
|
|
702
|
+
const type = this.parseType();
|
|
703
|
+
const name = this.parseSingleIdentifier();
|
|
704
|
+
if (idl.isUnionType(type)) {
|
|
705
|
+
type.name = name.value;
|
|
706
|
+
}
|
|
707
|
+
this.skip(";");
|
|
708
|
+
return idl.createTypedef(name.value, type, typeParameters, { extendedAttributes: ext, documentation: extractDocumentation(ext), nodeLocation: sloc(), nameLocation: name.location });
|
|
709
|
+
}
|
|
710
|
+
parseCallback() {
|
|
711
|
+
trac("parseCallback");
|
|
712
|
+
const sloc = this.trackLocation();
|
|
713
|
+
const ext = this.consumeCurrentExtended();
|
|
714
|
+
this.skip("callback");
|
|
715
|
+
if (this.see("interface")) {
|
|
716
|
+
UnsupportedSyntax.throwDiagnosticMessage([this.curLocation], "Unsupported syntax: callback interface");
|
|
717
|
+
}
|
|
718
|
+
const typeParameters = this.parseAndPushGenerics(ext);
|
|
719
|
+
const name = this.parseSingleIdentifier();
|
|
720
|
+
this.skip("=");
|
|
721
|
+
const retType = this.parseType();
|
|
722
|
+
const args = this.parseArgTuple();
|
|
723
|
+
this.skip(";");
|
|
724
|
+
return idl.createCallback(name.value, args, retType, { extendedAttributes: ext, documentation: extractDocumentation(ext), nodeLocation: sloc(), nameLocation: name.location }, typeParameters);
|
|
725
|
+
}
|
|
726
|
+
parseEnum() {
|
|
727
|
+
trac("parseEnum");
|
|
728
|
+
const sloc = this.trackLocation();
|
|
729
|
+
const ext = this.consumeCurrentExtended();
|
|
730
|
+
this.skip("enum");
|
|
731
|
+
const name = this.parseSingleIdentifier();
|
|
732
|
+
const items = [];
|
|
733
|
+
this.skip("{");
|
|
734
|
+
let next = false;
|
|
735
|
+
while (!this.seeAndSkip("}")) {
|
|
736
|
+
if (next) {
|
|
737
|
+
this.skip(",");
|
|
738
|
+
// Can have trailing comma
|
|
739
|
+
if (this.seeAndSkip("}")) {
|
|
740
|
+
break;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
next = true;
|
|
744
|
+
const ext = this.parseExtendedAttributes();
|
|
745
|
+
const entry = this.parseLiteral();
|
|
746
|
+
const member = idl.createEnumMember(entry.value, undefined, idl.IDLNumberType, undefined, { extendedAttributes: ext, nodeLocation: entry.location, nameLocation: entry.location });
|
|
747
|
+
items.push(member);
|
|
748
|
+
}
|
|
749
|
+
return idl.createEnum(name.value, items, { extendedAttributes: ext, documentation: extractDocumentation(ext), nodeLocation: sloc(), nameLocation: name.location });
|
|
750
|
+
}
|
|
751
|
+
parseDictionary() {
|
|
752
|
+
trac("parseDictionary");
|
|
753
|
+
const sloc = this.trackLocation();
|
|
754
|
+
const ext = this.consumeCurrentExtended();
|
|
755
|
+
this.skip("dictionary");
|
|
756
|
+
const name = this.parseSingleIdentifier();
|
|
757
|
+
const items = [];
|
|
758
|
+
this.skip("{");
|
|
759
|
+
while (!this.seeAndSkip("}")) {
|
|
760
|
+
items.push(this.parseDictionaryEntry());
|
|
761
|
+
}
|
|
762
|
+
this.skip(";");
|
|
763
|
+
return idl.createEnum(name.value, items, { extendedAttributes: ext, documentation: extractDocumentation(ext), nodeLocation: sloc(), nameLocation: name.location });
|
|
764
|
+
}
|
|
765
|
+
parseDictionaryEntry() {
|
|
766
|
+
trac("parseDictionaryEntry");
|
|
767
|
+
const ext = this.parseExtendedAttributes();
|
|
768
|
+
const sloc = this.trackLocation();
|
|
769
|
+
const type = this.parsePrimitiveType();
|
|
770
|
+
const name = this.parseSingleIdentifier();
|
|
771
|
+
this.skip("=");
|
|
772
|
+
const value = this.parseLiteral();
|
|
773
|
+
const extracted = extractLiteral(value);
|
|
774
|
+
this.skip(";");
|
|
775
|
+
return idl.createEnumMember(name.value, undefined, type, extracted.extractedValue, { extendedAttributes: ext, nodeLocation: sloc(), nameLocation: name.location, valueLocation: value.location });
|
|
776
|
+
}
|
|
777
|
+
parsePackage() {
|
|
778
|
+
trac("parsePackage");
|
|
779
|
+
const sloc = this.trackLocation();
|
|
780
|
+
this.skip("package");
|
|
781
|
+
const packagePath = this.parseFullIdentifierOrLiteral();
|
|
782
|
+
this.skip(";");
|
|
783
|
+
return { location: sloc(), name: valueFromIdentifierOrLiteral(packagePath) };
|
|
784
|
+
}
|
|
785
|
+
parseImport() {
|
|
786
|
+
trac("parseImport");
|
|
787
|
+
const sloc = this.trackLocation();
|
|
788
|
+
this.skip("import");
|
|
789
|
+
const importPath = this.parseFullIdentifierOrLiteral();
|
|
790
|
+
let alias;
|
|
791
|
+
if (this.seeAndSkip("as")) {
|
|
792
|
+
alias = this.parseSingleIdentifier();
|
|
793
|
+
}
|
|
794
|
+
this.skip(";");
|
|
795
|
+
return idl.createImport(valueFromIdentifierOrLiteral(importPath).split("."), alias === null || alias === void 0 ? void 0 : alias.value, { nodeLocation: sloc(), nameLocation: alias === null || alias === void 0 ? void 0 : alias.location, valueLocation: importPath.location });
|
|
796
|
+
}
|
|
797
|
+
parseVersion() {
|
|
798
|
+
trac("parseVersion");
|
|
799
|
+
const sloc = this.trackLocation();
|
|
800
|
+
this.skip("version");
|
|
801
|
+
const versionLiteral = this.parseLiteral();
|
|
802
|
+
this.skip(";");
|
|
803
|
+
return idl.createVersion(versionLiteral.value.split("."), { nodeLocation: sloc(), valueLocation: versionLiteral.location });
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
function prepareOffsets(lines) {
|
|
807
|
+
let offsets = [];
|
|
808
|
+
let offset = 0;
|
|
809
|
+
for (let line of lines) {
|
|
810
|
+
let plus = line.length;
|
|
811
|
+
offsets.push(offset);
|
|
812
|
+
offset += plus;
|
|
813
|
+
}
|
|
814
|
+
return offsets;
|
|
815
|
+
}
|
|
816
|
+
function valueFromIdentifierOrLiteral(token) {
|
|
817
|
+
if (token.kind == TokenKind.Words && !literalTypes.has(token.value)) {
|
|
818
|
+
return token.value;
|
|
819
|
+
}
|
|
820
|
+
return extractLiteral(token).extractedString;
|
|
821
|
+
}
|
|
822
|
+
const literalTypes = new Map([
|
|
823
|
+
["true", "boolean"],
|
|
824
|
+
["false", "boolean"],
|
|
825
|
+
["Infinity", "number"],
|
|
826
|
+
["-Infinity", "number"],
|
|
827
|
+
["NaN", "number"],
|
|
828
|
+
["null", "null"],
|
|
829
|
+
["undefined", "undefined"],
|
|
830
|
+
]);
|
|
831
|
+
const extractedUndefined = { type: "undefined", extractedString: "undefined", extractedValue: "undefined" };
|
|
832
|
+
function extractLiteral(token) {
|
|
833
|
+
if (token.kind == TokenKind.Words) {
|
|
834
|
+
if (!literalTypes.has(token.value)) {
|
|
835
|
+
IncorrectLiteral.reportDiagnosticMessage([token.location]);
|
|
836
|
+
return extractedUndefined;
|
|
837
|
+
}
|
|
838
|
+
const type = literalTypes.get(token.value);
|
|
839
|
+
const extractedString = token.value;
|
|
840
|
+
const extractedValue = type == "number" ? parseFloat(extractedString) : extractedString;
|
|
841
|
+
return { type, extractedString, extractedValue };
|
|
842
|
+
}
|
|
843
|
+
if (token.kind != TokenKind.Literal) {
|
|
844
|
+
IncorrectLiteral.reportDiagnosticMessage([token.location]);
|
|
845
|
+
return extractedUndefined;
|
|
846
|
+
}
|
|
847
|
+
if (token.value[0] == "\"") {
|
|
848
|
+
try {
|
|
849
|
+
const extractedString = unescapeString(token.value);
|
|
850
|
+
return { type: "string", extractedString, extractedValue: extractedString };
|
|
851
|
+
}
|
|
852
|
+
catch (e) {
|
|
853
|
+
IncorrectLiteral.reportDiagnosticMessage([token.location], `Incorrect literal: ${e.message}`);
|
|
854
|
+
return extractedUndefined;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
const extractedValue = parseFloat(token.value);
|
|
858
|
+
if (Number.isNaN(extractedValue)) {
|
|
859
|
+
// Real NaNs are handled before that, so report an error
|
|
860
|
+
IncorrectLiteral.reportDiagnosticMessage([token.location]);
|
|
861
|
+
}
|
|
862
|
+
return { type: "number", extractedString: token.value, extractedValue };
|
|
863
|
+
}
|
|
864
|
+
// Taken from deserialize.ts as is
|
|
865
|
+
function unescapeString(value) {
|
|
866
|
+
if (!value.length || value[0] !== '"')
|
|
867
|
+
return value;
|
|
868
|
+
value = value.slice(1, -1);
|
|
869
|
+
value = value.replace(/\\((['"\\bfnrtv])|([0-7]{1-3})|x([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/g, (_, all, c, oct, h2, u4) => {
|
|
870
|
+
if (c !== undefined) {
|
|
871
|
+
switch (c) {
|
|
872
|
+
case "'": return "'";
|
|
873
|
+
case '"': return '"';
|
|
874
|
+
case "\\": return "\\";
|
|
875
|
+
case "b": return "\b";
|
|
876
|
+
case "f": return "\f";
|
|
877
|
+
case "n": return "\n";
|
|
878
|
+
case "r": return "\r";
|
|
879
|
+
case "t": return "\t";
|
|
880
|
+
case "v": return "\v";
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
else if (oct !== undefined) {
|
|
884
|
+
return String.fromCharCode(parseInt(oct, 8));
|
|
885
|
+
}
|
|
886
|
+
else if (h2 !== undefined) {
|
|
887
|
+
return String.fromCharCode(parseInt(h2, 16));
|
|
888
|
+
}
|
|
889
|
+
else if (u4 !== undefined) {
|
|
890
|
+
return String.fromCharCode(parseInt(u4, 16));
|
|
891
|
+
}
|
|
892
|
+
throw new Error(`unknown escape sequence: ${_}`);
|
|
893
|
+
});
|
|
894
|
+
return value;
|
|
895
|
+
}
|
|
896
|
+
function extractInterfaceSubkind(ext) {
|
|
897
|
+
var _a;
|
|
898
|
+
const ent = (_a = ext === null || ext === void 0 ? void 0 : ext.find(x => x.name == "Entity")) === null || _a === void 0 ? void 0 : _a.value;
|
|
899
|
+
switch (ent) {
|
|
900
|
+
case idl.IDLEntity.Class: return idl.IDLInterfaceSubkind.Class;
|
|
901
|
+
case idl.IDLEntity.Literal: return idl.IDLInterfaceSubkind.AnonymousInterface;
|
|
902
|
+
case idl.IDLEntity.Tuple: return idl.IDLInterfaceSubkind.Tuple;
|
|
903
|
+
default: return idl.IDLInterfaceSubkind.Interface;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
function extractDocumentation(ext) {
|
|
907
|
+
var _a;
|
|
908
|
+
return (_a = ext === null || ext === void 0 ? void 0 : ext.find(x => x.name == "Documentation")) === null || _a === void 0 ? void 0 : _a.value;
|
|
909
|
+
}
|
|
910
|
+
function extractOptional(ext) {
|
|
911
|
+
var _a;
|
|
912
|
+
return (_a = ext === null || ext === void 0 ? void 0 : ext.some(x => x.name.toLowerCase() == "optional")) !== null && _a !== void 0 ? _a : false;
|
|
913
|
+
}
|
|
914
|
+
function sanitizeTypeParameter(param) {
|
|
915
|
+
const extendsIdx = param.indexOf('extends');
|
|
916
|
+
if (extendsIdx !== -1) {
|
|
917
|
+
return param.substring(0, extendsIdx).trim();
|
|
918
|
+
}
|
|
919
|
+
const eqIdx = param.indexOf('=');
|
|
920
|
+
if (eqIdx !== -1) {
|
|
921
|
+
return param.substring(0, eqIdx).trim();
|
|
922
|
+
}
|
|
923
|
+
return param;
|
|
924
|
+
}
|
|
925
|
+
function extractTypeParameters(ext) {
|
|
926
|
+
var _a, _b, _c;
|
|
927
|
+
return (_c = (_b = (_a = ext === null || ext === void 0 ? void 0 : ext.find(x => x.name == idl.IDLExtendedAttributes.TypeParameters)) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.split(",")) === null || _c === void 0 ? void 0 : _c.map(sanitizeTypeParameter);
|
|
928
|
+
}
|
|
929
|
+
function extractTypeArguments(ext) {
|
|
930
|
+
var _a;
|
|
931
|
+
return (_a = ext === null || ext === void 0 ? void 0 : ext.find(x => x.name == idl.IDLExtendedAttributes.TypeArguments)) === null || _a === void 0 ? void 0 : _a.typesValue;
|
|
932
|
+
}
|
|
933
|
+
const builtinTypesList = [idl.IDLPointerType, idl.IDLVoidType, idl.IDLBooleanType,
|
|
934
|
+
idl.IDLObjectType, idl.IDLI8Type, idl.IDLU8Type, idl.IDLI16Type, idl.IDLU16Type,
|
|
935
|
+
idl.IDLI32Type, idl.IDLU32Type, idl.IDLI64Type, idl.IDLU64Type, idl.IDLF32Type,
|
|
936
|
+
idl.IDLF64Type, idl.IDLBigintType, idl.IDLNumberType, idl.IDLStringType, idl.IDLAnyType,
|
|
937
|
+
idl.IDLUndefinedType, idl.IDLUnknownType, idl.IDLObjectType, idl.IDLThisType, idl.IDLDate,
|
|
938
|
+
idl.IDLBufferType, idl.IDLSerializerBuffer
|
|
939
|
+
];
|
|
940
|
+
// Better solution will be to make it registry in idl.ts
|
|
941
|
+
const builtinTypes = new Map(builtinTypesList.map(x => [x.name, x]));
|
|
942
|
+
const builtinGenericTypeNames = new Set(["sequence", "record", "Promise"]);
|
|
943
|
+
//# sourceMappingURL=parser.js.map
|