semantifold 0.1.0

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.
Files changed (111) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +71 -0
  3. package/build/index.d.ts +54 -0
  4. package/build/index.d.ts.map +1 -0
  5. package/build/index.js +45 -0
  6. package/build/src/backends/identifiers.d.ts +19 -0
  7. package/build/src/backends/identifiers.d.ts.map +1 -0
  8. package/build/src/backends/identifiers.js +93 -0
  9. package/build/src/backends/index.d.ts +35 -0
  10. package/build/src/backends/index.d.ts.map +1 -0
  11. package/build/src/backends/index.js +149 -0
  12. package/build/src/backends/java.d.ts +8 -0
  13. package/build/src/backends/java.d.ts.map +1 -0
  14. package/build/src/backends/java.js +172 -0
  15. package/build/src/backends/javascript.d.ts +8 -0
  16. package/build/src/backends/javascript.d.ts.map +1 -0
  17. package/build/src/backends/javascript.js +173 -0
  18. package/build/src/backends/php.d.ts +8 -0
  19. package/build/src/backends/php.d.ts.map +1 -0
  20. package/build/src/backends/php.js +175 -0
  21. package/build/src/backends/ruby.d.ts +8 -0
  22. package/build/src/backends/ruby.d.ts.map +1 -0
  23. package/build/src/backends/ruby.js +155 -0
  24. package/build/src/backends/scalars.d.ts +15 -0
  25. package/build/src/backends/scalars.d.ts.map +1 -0
  26. package/build/src/backends/scalars.js +138 -0
  27. package/build/src/backends/shared.d.ts +26 -0
  28. package/build/src/backends/shared.d.ts.map +1 -0
  29. package/build/src/backends/shared.js +424 -0
  30. package/build/src/backends/typescript.d.ts +8 -0
  31. package/build/src/backends/typescript.d.ts.map +1 -0
  32. package/build/src/backends/typescript.js +160 -0
  33. package/build/src/backends/writer.d.ts +87 -0
  34. package/build/src/backends/writer.d.ts.map +1 -0
  35. package/build/src/backends/writer.js +207 -0
  36. package/build/src/diagnostic.d.ts +67 -0
  37. package/build/src/diagnostic.d.ts.map +1 -0
  38. package/build/src/diagnostic.js +96 -0
  39. package/build/src/frontends/index.d.ts +14 -0
  40. package/build/src/frontends/index.d.ts.map +1 -0
  41. package/build/src/frontends/index.js +36 -0
  42. package/build/src/frontends/java.d.ts +12 -0
  43. package/build/src/frontends/java.d.ts.map +1 -0
  44. package/build/src/frontends/java.js +630 -0
  45. package/build/src/frontends/javascript-typescript.d.ts +19 -0
  46. package/build/src/frontends/javascript-typescript.d.ts.map +1 -0
  47. package/build/src/frontends/javascript-typescript.js +633 -0
  48. package/build/src/frontends/php.d.ts +12 -0
  49. package/build/src/frontends/php.d.ts.map +1 -0
  50. package/build/src/frontends/php.js +523 -0
  51. package/build/src/frontends/ruby.d.ts +12 -0
  52. package/build/src/frontends/ruby.d.ts.map +1 -0
  53. package/build/src/frontends/ruby.js +515 -0
  54. package/build/src/frontends/scalars.d.ts +19 -0
  55. package/build/src/frontends/scalars.d.ts.map +1 -0
  56. package/build/src/frontends/scalars.js +71 -0
  57. package/build/src/mapping.d.ts +160 -0
  58. package/build/src/mapping.d.ts.map +1 -0
  59. package/build/src/mapping.js +1120 -0
  60. package/build/src/semantic/location.d.ts +61 -0
  61. package/build/src/semantic/location.d.ts.map +1 -0
  62. package/build/src/semantic/location.js +142 -0
  63. package/build/src/semantic/operators.d.ts +16 -0
  64. package/build/src/semantic/operators.d.ts.map +1 -0
  65. package/build/src/semantic/operators.js +24 -0
  66. package/build/src/semantic/provenance.d.ts +74 -0
  67. package/build/src/semantic/provenance.d.ts.map +1 -0
  68. package/build/src/semantic/provenance.js +577 -0
  69. package/build/src/semantic/scalars.d.ts +19 -0
  70. package/build/src/semantic/scalars.d.ts.map +1 -0
  71. package/build/src/semantic/scalars.js +40 -0
  72. package/build/src/semantic/types.d.ts +1003 -0
  73. package/build/src/semantic/types.d.ts.map +1 -0
  74. package/build/src/semantic/types.js +279 -0
  75. package/build/src/semantic/validate.d.ts +60 -0
  76. package/build/src/semantic/validate.d.ts.map +1 -0
  77. package/build/src/semantic/validate.js +472 -0
  78. package/docs/architecture.md +39 -0
  79. package/docs/coding-standards.md +7 -0
  80. package/docs/goals.md +7 -0
  81. package/docs/language-support.md +69 -0
  82. package/docs/plans/2026-09-02-initial-toolchain.md +54 -0
  83. package/docs/source-maps.md +134 -0
  84. package/docs/testing.md +25 -0
  85. package/index.js +63 -0
  86. package/package.json +69 -0
  87. package/src/backends/identifiers.js +101 -0
  88. package/src/backends/index.js +159 -0
  89. package/src/backends/java.js +182 -0
  90. package/src/backends/javascript.js +184 -0
  91. package/src/backends/php.js +184 -0
  92. package/src/backends/ruby.js +163 -0
  93. package/src/backends/scalars.js +120 -0
  94. package/src/backends/shared.js +456 -0
  95. package/src/backends/typescript.js +168 -0
  96. package/src/backends/writer.js +224 -0
  97. package/src/diagnostic.js +103 -0
  98. package/src/frontends/index.js +36 -0
  99. package/src/frontends/java.js +735 -0
  100. package/src/frontends/javascript-typescript.js +718 -0
  101. package/src/frontends/php.js +593 -0
  102. package/src/frontends/ruby.js +622 -0
  103. package/src/frontends/scalars.js +77 -0
  104. package/src/mapping.js +1260 -0
  105. package/src/semantic/location.js +154 -0
  106. package/src/semantic/operators.js +28 -0
  107. package/src/semantic/provenance.js +629 -0
  108. package/src/semantic/scalars.js +44 -0
  109. package/src/semantic/types.js +319 -0
  110. package/src/semantic/validate.js +529 -0
  111. package/tsconfig.json +16 -0
@@ -0,0 +1,515 @@
1
+ // @ts-check
2
+ import { AndNode, CallNode, DefNode, ElseNode, FalseNode, IfNode, IntegerNode, InterpolatedStringNode, LocalVariableReadNode, LocalVariableWriteNode, OrNode, ParenthesesNode, ProgramNode, RequiredParameterNode, ReturnNode, StatementsNode, StringNode, TrueNode, loadPrism } from "@ruby/prism";
3
+ import { missingType, SemantifoldDiagnostic, unsupportedSyntax } from "../diagnostic.js";
4
+ import { locationFromOffsets, moduleLocation, utf8ByteOffsetToUtf16Offset } from "../semantic/location.js";
5
+ import { withAdaptedOperation } from "../semantic/operators.js";
6
+ import { withParserRanges } from "../semantic/provenance.js";
7
+ import { hasOnlyUnicodeScalars } from "../semantic/scalars.js";
8
+ import { requireSourceScalarType } from "./scalars.js";
9
+ const parsePrism = await loadPrism();
10
+ const rubyBinaryOperations = new Map([
11
+ ["+", "Add"],
12
+ ["-", "Subtract"],
13
+ ["*", "Multiply"],
14
+ ["==", "Equal"],
15
+ ["!=", "NotEqual"],
16
+ ["<", "LessThan"],
17
+ ["<=", "LessThanOrEqual"],
18
+ [">", "GreaterThan"],
19
+ [">=", "GreaterThanOrEqual"]
20
+ ]);
21
+ /**
22
+ * Returns a normalized Prism node location.
23
+ * @param {{location: import("@ruby/prism").Location}} node - Prism node.
24
+ * @param {string} filename - Source filename.
25
+ * @param {string} source - Complete source.
26
+ * @returns {import("../semantic/types.js").SourceLocation} Source location.
27
+ */
28
+ function nodeLocation(node, filename, source) {
29
+ return prismLocation(node.location, filename, source);
30
+ }
31
+ /**
32
+ * Converts a Prism location into a normalized source location.
33
+ * @param {import("@ruby/prism").Location} location - Prism location.
34
+ * @param {string} filename - Source filename.
35
+ * @param {string} source - Complete source.
36
+ * @returns {import("../semantic/types.js").SourceLocation} Source location.
37
+ */
38
+ function prismLocation(location, filename, source) {
39
+ return locationFromOffsets(filename, source, utf8ByteOffsetToUtf16Offset(source, location.startOffset), utf8ByteOffsetToUtf16Offset(source, location.startOffset + location.length));
40
+ }
41
+ /**
42
+ * Slices JavaScript source using Prism's UTF-8 byte offsets.
43
+ * @param {string} source - Complete source.
44
+ * @param {number} startOffset - Inclusive Prism byte offset.
45
+ * @param {number} endOffset - Exclusive Prism byte offset.
46
+ * @returns {string} Source text in the byte range.
47
+ */
48
+ function slicePrismSource(source, startOffset, endOffset) {
49
+ return source.slice(utf8ByteOffsetToUtf16Offset(source, startOffset), utf8ByteOffsetToUtf16Offset(source, endOffset));
50
+ }
51
+ /**
52
+ * Converts a supported Prism expression.
53
+ * @param {import("@ruby/prism").Node} node - Prism node.
54
+ * @param {string} filename - Source filename.
55
+ * @param {string} source - Complete source.
56
+ * @returns {import("../semantic/types.js").Expression} Semantic expression.
57
+ */
58
+ function convertExpression(node, filename, source) {
59
+ const location = nodeLocation(node, filename, source);
60
+ if (node instanceof ParenthesesNode && node.body instanceof StatementsNode && node.body.body.length == 1) {
61
+ return convertExpression(node.body.body[0], filename, source);
62
+ }
63
+ if (node instanceof LocalVariableReadNode) {
64
+ return withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location, name: node.name }, { name: location });
65
+ }
66
+ if (node instanceof IntegerNode) {
67
+ if (!Number.isSafeInteger(node.value))
68
+ return unsupportedSyntax("ruby", "non-safe integer literal", location);
69
+ return withParserRanges({ kind: /** @type {const} */ ("IntegerLiteral"), location, value: node.value }, { literal: location });
70
+ }
71
+ if (node instanceof TrueNode || node instanceof FalseNode) {
72
+ return withParserRanges({ kind: /** @type {const} */ ("BooleanLiteral"), location, value: node instanceof TrueNode }, { literal: location });
73
+ }
74
+ if (node instanceof StringNode) {
75
+ const decoded = node.unescaped;
76
+ if (!decoded.validEncoding || decoded.encoding != "utf-8" || node.isForcedBinaryEncoding() ||
77
+ !hasOnlyUnicodeScalars(decoded.value)) {
78
+ return unsupportedSyntax("ruby", "invalid Unicode string literal", location);
79
+ }
80
+ return withParserRanges({ kind: /** @type {const} */ ("StringLiteral"), location, value: decoded.value }, { literal: location });
81
+ }
82
+ if (node instanceof InterpolatedStringNode)
83
+ return unsupportedSyntax("ruby", "interpolated string", location);
84
+ if (node instanceof CallNode && node.receiver && node.name == "!") {
85
+ const operatorLocation = prismLocation(node.messageLoc ?? node.location, filename, source);
86
+ if (node.callOperatorLoc)
87
+ return unsupportedSyntax("ruby", "qualified boolean not", operatorLocation);
88
+ if (node.messageLoc?.length != 1) {
89
+ return unsupportedSyntax("ruby", "precedence-sensitive boolean not", operatorLocation);
90
+ }
91
+ if (node.arguments_)
92
+ return unsupportedSyntax("ruby", "boolean not argument list", operatorLocation);
93
+ const semantic = withAdaptedOperation(withParserRanges({
94
+ kind: "UnaryExpression",
95
+ location,
96
+ operand: convertExpression(node.receiver, filename, source)
97
+ }, { operator: operatorLocation }), "Not");
98
+ return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
99
+ }
100
+ if (node instanceof CallNode && node.receiver && node.name == "-@") {
101
+ const operatorLocation = prismLocation(node.messageLoc ?? node.location, filename, source);
102
+ if (node.callOperatorLoc)
103
+ return unsupportedSyntax("ruby", "qualified integer negation", operatorLocation);
104
+ if (node.arguments_)
105
+ return unsupportedSyntax("ruby", "integer negation argument list", operatorLocation);
106
+ const semantic = withAdaptedOperation(withParserRanges({
107
+ kind: "UnaryExpression",
108
+ location,
109
+ operand: convertExpression(node.receiver, filename, source)
110
+ }, { operator: operatorLocation }), "Negate");
111
+ return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
112
+ }
113
+ if (node instanceof AndNode || node instanceof OrNode) {
114
+ const operatorLocation = prismLocation(node.operatorLoc, filename, source);
115
+ const sourceOperator = source.slice(operatorLocation.start.offset, operatorLocation.end.offset);
116
+ if (sourceOperator != "&&" && sourceOperator != "||") {
117
+ return unsupportedSyntax("ruby", `precedence-sensitive boolean ${sourceOperator}`, location);
118
+ }
119
+ const semantic = withAdaptedOperation(withParserRanges({
120
+ kind: "BinaryExpression",
121
+ left: convertExpression(node.left, filename, source),
122
+ location,
123
+ right: convertExpression(node.right, filename, source)
124
+ }, { operator: operatorLocation }), node instanceof AndNode ? "And" : "Or");
125
+ return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
126
+ }
127
+ if (node instanceof CallNode && node.receiver && rubyBinaryOperations.has(node.name) && node.callOperatorLoc &&
128
+ node.arguments_?.arguments_.length == 1) {
129
+ return unsupportedSyntax("ruby", `qualified binary operator ${node.name}`, prismLocation(node.messageLoc ?? node.location, filename, source));
130
+ }
131
+ if (node instanceof CallNode && node.receiver && rubyBinaryOperations.has(node.name) && node.arguments_?.arguments_.length == 1) {
132
+ const semantic = withAdaptedOperation(withParserRanges({
133
+ kind: "BinaryExpression",
134
+ left: convertExpression(node.receiver, filename, source),
135
+ location,
136
+ right: convertExpression(node.arguments_.arguments_[0], filename, source)
137
+ }, { operator: prismLocation(node.messageLoc ?? node.location, filename, source) }), /** @type {import("../semantic/operators.js").AdaptedOperation} */ (rubyBinaryOperations.get(node.name)));
138
+ return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
139
+ }
140
+ if (node instanceof CallNode && !node.receiver) {
141
+ return withParserRanges({
142
+ arguments: (node.arguments_?.arguments_ ?? []).map((argument) => convertExpression(argument, filename, source)),
143
+ callee: node.name,
144
+ kind: "CallExpression",
145
+ location
146
+ }, { callee: prismLocation(node.messageLoc ?? node.location, filename, source) });
147
+ }
148
+ return unsupportedSyntax("ruby", node.constructor.name, location);
149
+ }
150
+ /**
151
+ * Converts one explicit Ruby return.
152
+ * @param {import("@ruby/prism").Node} node - Prism node.
153
+ * @param {string} filename - Source filename.
154
+ * @param {string} source - Complete source.
155
+ * @returns {import("../semantic/types.js").ReturnStatement} Semantic return.
156
+ */
157
+ function convertReturn(node, filename, source) {
158
+ const location = nodeLocation(node, filename, source);
159
+ if (!(node instanceof ReturnNode) || node.arguments_?.arguments_.length != 1) {
160
+ return unsupportedSyntax("ruby", node.constructor.name, location);
161
+ }
162
+ return {
163
+ expression: convertExpression(node.arguments_.arguments_[0], filename, source),
164
+ kind: "ReturnStatement",
165
+ location
166
+ };
167
+ }
168
+ /**
169
+ * Reads Prism-owned RBS-style type comments directly preceding a definition.
170
+ * @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
171
+ * @param {{location: import("@ruby/prism").Location}} node - Comment owner.
172
+ * @param {string} filename - Source filename.
173
+ * @param {string} source - Complete source.
174
+ * @returns {{parameters: Map<string, {location: import("../semantic/types.js").SourceLocation, sourceType: string}>, returnType: {location: import("../semantic/types.js").SourceLocation, sourceType: string} | undefined}} Declared types.
175
+ */
176
+ function typeComments(comments, node, filename, source) {
177
+ const preceding = associatedComments(comments, node, source);
178
+ const parameterTypes = new Map();
179
+ /** @type {{location: import("../semantic/types.js").SourceLocation, sourceType: string} | undefined} */
180
+ let returnType;
181
+ for (const comment of preceding) {
182
+ const words = commentTokens(comment, filename, source);
183
+ if (words[0]?.text == "@param" && words.length == 3) {
184
+ parameterTypes.set(words[1].text, { location: words[2].location, sourceType: words[2].text });
185
+ }
186
+ if (words[0]?.text == "@return" && words.length == 2) {
187
+ returnType = { location: words[1].location, sourceType: words[1].text };
188
+ }
189
+ }
190
+ return { parameters: parameterTypes, returnType };
191
+ }
192
+ /**
193
+ * Lexes whitespace-separated metadata tokens inside a Prism-owned Ruby comment.
194
+ * @param {import("@ruby/prism/src/deserialize.js").Comment} comment - Prism comment token.
195
+ * @param {string} filename - Source filename.
196
+ * @param {string} source - Complete source.
197
+ * @returns {{location: import("../semantic/types.js").SourceLocation, text: string}[]} Metadata tokens.
198
+ */
199
+ function commentTokens(comment, filename, source) {
200
+ const start = utf8ByteOffsetToUtf16Offset(source, comment.location.startOffset);
201
+ const end = utf8ByteOffsetToUtf16Offset(source, comment.location.startOffset + comment.location.length);
202
+ const tokens = [];
203
+ let offset = start + 1;
204
+ while (offset < end) {
205
+ while (offset < end && isRubyMetadataWhitespace(source[offset]))
206
+ offset++;
207
+ const tokenStart = offset;
208
+ while (offset < end && !isRubyMetadataWhitespace(source[offset]))
209
+ offset++;
210
+ if (tokenStart < offset) {
211
+ tokens.push({ location: locationFromOffsets(filename, source, tokenStart, offset), text: source.slice(tokenStart, offset) });
212
+ }
213
+ }
214
+ return tokens;
215
+ }
216
+ /**
217
+ * Checks one Ruby metadata separator.
218
+ * @param {string} character - Source character.
219
+ * @returns {boolean} Whether it separates metadata tokens.
220
+ */
221
+ function isRubyMetadataWhitespace(character) {
222
+ return character == " " || character == "\t" || character == "\r" || character == "\n";
223
+ }
224
+ /**
225
+ * Selects only the contiguous comment block immediately before a definition.
226
+ * @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
227
+ * @param {{location: import("@ruby/prism").Location}} node - Comment owner.
228
+ * @param {string} source - Complete source.
229
+ * @returns {import("@ruby/prism/src/deserialize.js").Comment[]} Associated comments.
230
+ */
231
+ function associatedComments(comments, node, source) {
232
+ const preceding = comments.filter((comment) => comment.location.startOffset < node.location.startOffset)
233
+ .sort((left, right) => left.location.startOffset - right.location.startOffset);
234
+ const associated = [];
235
+ let boundary = node.location.startOffset;
236
+ for (let index = preceding.length - 1; index >= 0; index--) {
237
+ const comment = preceding[index];
238
+ const endOffset = comment.location.startOffset + comment.location.length;
239
+ const gap = slicePrismSource(source, endOffset, boundary);
240
+ if (!isImmediateCommentGap(gap))
241
+ break;
242
+ associated.unshift(comment);
243
+ boundary = comment.location.startOffset;
244
+ }
245
+ return associated;
246
+ }
247
+ /**
248
+ * Reads one exact Ruby local type carrier and immutability marker.
249
+ * @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
250
+ * @param {LocalVariableWriteNode} node - Local write.
251
+ * @param {string} filename - Source filename.
252
+ * @param {string} source - Complete source.
253
+ * @returns {{immutable: boolean, type: import("../semantic/types.js").TypeReference} | undefined} Metadata when present.
254
+ */
255
+ function localMetadata(comments, node, filename, source) {
256
+ const associated = associatedComments(comments, node, source);
257
+ const metadata = associated.map((comment) => commentTokens(comment, filename, source));
258
+ const typeMetadata = metadata.filter(([token]) => token?.text == "@type");
259
+ const immutableMetadata = metadata.filter(([token]) => token?.text == "@semantifold-immutable");
260
+ const profileMetadata = metadata.filter(([token]) => {
261
+ return token?.text.startsWith("@type") || token?.text.startsWith("@semantifold-immutable");
262
+ });
263
+ if (profileMetadata.length == 0)
264
+ return undefined;
265
+ const location = nodeLocation(node, filename, source);
266
+ if (typeMetadata.length != 1 || typeMetadata[0].length != 2 ||
267
+ immutableMetadata.length > 1 || immutableMetadata.some((tokens) => tokens.length != 1) ||
268
+ profileMetadata.length != typeMetadata.length + immutableMetadata.length) {
269
+ return unsupportedSyntax("ruby", "malformed local type metadata", location);
270
+ }
271
+ return {
272
+ immutable: immutableMetadata.length == 1,
273
+ type: convertType(typeMetadata[0][1].text, `Local '${node.name}'`, location, typeMetadata[0][1].location)
274
+ };
275
+ }
276
+ /**
277
+ * Converts one Ruby local declaration or assignment.
278
+ * @param {import("@ruby/prism").Node} node - Prism node.
279
+ * @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
280
+ * @param {Set<string>} visible - Names visible during adaptation.
281
+ * @param {string} filename - Source filename.
282
+ * @param {string} source - Complete source.
283
+ * @returns {import("../semantic/types.js").LocalStatement} Semantic local statement.
284
+ */
285
+ function convertLocalStatement(node, comments, visible, filename, source) {
286
+ const location = nodeLocation(node, filename, source);
287
+ if (!(node instanceof LocalVariableWriteNode))
288
+ return unsupportedSyntax("ruby", node.constructor.name, location);
289
+ const metadata = localMetadata(comments, node, filename, source);
290
+ if (metadata) {
291
+ visible.add(node.name);
292
+ return withParserRanges({
293
+ initializer: convertExpression(node.value, filename, source),
294
+ kind: "LocalDeclaration",
295
+ location,
296
+ mutable: !metadata.immutable,
297
+ name: node.name,
298
+ type: metadata.type
299
+ }, { name: prismLocation(node.nameLoc, filename, source), operator: prismLocation(node.operatorLoc, filename, source) });
300
+ }
301
+ if (!visible.has(node.name))
302
+ return missingType("ruby", `Local '${node.name}'`, location);
303
+ const targetLocation = prismLocation(node.nameLoc, filename, source);
304
+ const target = withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location: targetLocation, name: node.name }, {
305
+ name: targetLocation
306
+ });
307
+ return withParserRanges({
308
+ expression: convertExpression(node.value, filename, source),
309
+ kind: "AssignmentStatement",
310
+ location,
311
+ target
312
+ }, { operator: prismLocation(node.operatorLoc, filename, source) });
313
+ }
314
+ /**
315
+ * Converts one exhaustive Prism statement.
316
+ * @param {import("@ruby/prism").Node} node - Prism statement.
317
+ * @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
318
+ * @param {Set<string>} visible - Names visible during adaptation.
319
+ * @param {string} filename - Source filename.
320
+ * @param {string} source - Complete source.
321
+ * @returns {import("../semantic/types.js").Statement} Semantic statement.
322
+ */
323
+ function convertStatement(node, comments, visible, filename, source) {
324
+ if (node instanceof ReturnNode)
325
+ return convertReturn(node, filename, source);
326
+ if (node instanceof IfNode)
327
+ return convertIf(node, comments, visible, filename, source);
328
+ if (node instanceof LocalVariableWriteNode)
329
+ return convertLocalStatement(node, comments, visible, filename, source);
330
+ if (node instanceof CallNode)
331
+ return convertPrint(node, filename, source);
332
+ return unsupportedSyntax("ruby", node.constructor.name, nodeLocation(node, filename, source));
333
+ }
334
+ /**
335
+ * Converts one ordered Prism statement list.
336
+ * @param {StatementsNode | null} node - Prism statements, or an empty source block.
337
+ * @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
338
+ * @param {Set<string>} visible - Names visible on block entry.
339
+ * @param {string} filename - Source filename.
340
+ * @param {string} source - Complete source.
341
+ * @param {import("../semantic/types.js").SourceLocation} fallbackLocation - Empty block location.
342
+ * @returns {import("../semantic/types.js").Block} Semantic block.
343
+ */
344
+ function convertBlock(node, comments, visible, filename, source, fallbackLocation) {
345
+ return {
346
+ kind: "Block",
347
+ location: node ? nodeLocation(node, filename, source) : fallbackLocation,
348
+ statements: node ? node.body.map((statement) => convertStatement(statement, comments, visible, filename, source)) : []
349
+ };
350
+ }
351
+ /**
352
+ * Checks that a comment and its owner are separated by at most one newline.
353
+ * @param {string} gap - Source between the comment and following item.
354
+ * @returns {boolean} Whether the gap is immediate whitespace.
355
+ */
356
+ function isImmediateCommentGap(gap) {
357
+ let newlines = 0;
358
+ for (const character of gap) {
359
+ if (character == "\n") {
360
+ newlines++;
361
+ }
362
+ else if (character != " " && character != "\t" && character != "\r") {
363
+ return false;
364
+ }
365
+ }
366
+ return newlines <= 1;
367
+ }
368
+ /**
369
+ * Requires an exact supported Ruby scalar spelling.
370
+ * @param {string | undefined} sourceType - Ruby type comment value.
371
+ * @param {string} subject - Typed subject.
372
+ * @param {import("../semantic/types.js").SourceLocation} location - Source location.
373
+ * @param {import("../semantic/types.js").SourceLocation} [typeLocation] - Exact type comment token location.
374
+ * @returns {import("../semantic/types.js").TypeReference} Semantic type.
375
+ */
376
+ function convertType(sourceType, subject, location, typeLocation = location) {
377
+ return requireSourceScalarType("ruby", sourceType, subject, location, typeLocation);
378
+ }
379
+ /**
380
+ * Converts a Ruby definition.
381
+ * @param {DefNode} node - Prism definition.
382
+ * @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
383
+ * @param {string} filename - Source filename.
384
+ * @param {string} source - Complete source.
385
+ * @returns {import("../semantic/types.js").FunctionDeclaration} Semantic function.
386
+ */
387
+ function convertFunction(node, comments, filename, source) {
388
+ const location = nodeLocation(node, filename, source);
389
+ if (!node.parameters || node.parameters.optionals.length > 0 || node.parameters.rest || node.parameters.posts.length > 0 ||
390
+ node.parameters.keywords.length > 0 || node.parameters.keywordRest || node.parameters.block ||
391
+ node.parameters.requireds.some((parameter) => !(parameter instanceof RequiredParameterNode))) {
392
+ return unsupportedSyntax("ruby", "parameters", location);
393
+ }
394
+ const declaredTypes = typeComments(comments, node, filename, source);
395
+ const parameters = node.parameters.requireds.map((parameter) => {
396
+ if (!(parameter instanceof RequiredParameterNode))
397
+ return unsupportedSyntax("ruby", parameter.constructor.name, location);
398
+ const parameterLocation = nodeLocation(parameter, filename, source);
399
+ const declaredType = declaredTypes.parameters.get(parameter.name);
400
+ return withParserRanges({
401
+ kind: /** @type {const} */ ("Parameter"),
402
+ location: parameterLocation,
403
+ name: parameter.name,
404
+ type: convertType(declaredType?.sourceType, `Parameter '${parameter.name}'`, parameterLocation, declaredType?.location)
405
+ }, { name: parameterLocation });
406
+ });
407
+ const visible = new Set(parameters.map((parameter) => parameter.name));
408
+ const body = convertBlock(node.body instanceof StatementsNode ? node.body : null, comments, visible, filename, source, location);
409
+ return withParserRanges({
410
+ body,
411
+ kind: "FunctionDeclaration",
412
+ location,
413
+ name: node.name,
414
+ parameters,
415
+ returnType: convertType(declaredTypes.returnType?.sourceType, `Function '${node.name}' return`, location, declaredTypes.returnType?.location)
416
+ }, { name: prismLocation(node.nameLoc, filename, source) });
417
+ }
418
+ /**
419
+ * Converts the existing Ruby if/else terminal with restricted branch prefixes.
420
+ * @param {IfNode} node - Prism if node.
421
+ * @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
422
+ * @param {Set<string>} visible - Enclosing visible names.
423
+ * @param {string} filename - Source filename.
424
+ * @param {string} source - Complete source.
425
+ * @returns {import("../semantic/types.js").IfStatement} Semantic branch.
426
+ */
427
+ function convertIf(node, comments, visible, filename, source) {
428
+ const location = nodeLocation(node, filename, source);
429
+ if (!node.ifKeywordLoc || node.ifKeywordLoc.startOffset != node.location.startOffset) {
430
+ return unsupportedSyntax("ruby", "modifier conditional", node.ifKeywordLoc
431
+ ? prismLocation(node.ifKeywordLoc, filename, source)
432
+ : location);
433
+ }
434
+ const consequentVisible = new Set(visible);
435
+ let alternate;
436
+ if (node.subsequent) {
437
+ const alternateVisible = new Set(visible);
438
+ if (node.subsequent instanceof ElseNode) {
439
+ alternate = convertBlock(node.subsequent.statements, comments, alternateVisible, filename, source, nodeLocation(node.subsequent, filename, source));
440
+ }
441
+ else if (node.subsequent instanceof IfNode) {
442
+ alternate = {
443
+ kind: /** @type {const} */ ("Block"),
444
+ location: nodeLocation(node.subsequent, filename, source),
445
+ statements: [convertIf(node.subsequent, comments, alternateVisible, filename, source)]
446
+ };
447
+ }
448
+ else
449
+ return unsupportedSyntax("ruby", node.subsequent.constructor.name, nodeLocation(node.subsequent, filename, source));
450
+ }
451
+ return {
452
+ ...(alternate ? { alternate } : {}),
453
+ condition: convertExpression(node.predicate, filename, source),
454
+ consequent: convertBlock(node.statements, comments, consequentVisible, filename, source, location),
455
+ kind: "IfStatement",
456
+ location
457
+ };
458
+ }
459
+ /**
460
+ * Converts the supported Ruby puts entry point.
461
+ * @param {import("@ruby/prism").Node} node - Prism node.
462
+ * @param {string} filename - Source filename.
463
+ * @param {string} source - Complete source.
464
+ * @returns {import("../semantic/types.js").PrintStatement} Print statement.
465
+ */
466
+ function convertPrint(node, filename, source) {
467
+ const location = nodeLocation(node, filename, source);
468
+ if (!(node instanceof CallNode) || node.receiver || node.name != "puts" || node.arguments_?.arguments_.length != 1) {
469
+ return unsupportedSyntax("ruby", node.constructor.name, location);
470
+ }
471
+ return { expression: convertExpression(node.arguments_.arguments_[0], filename, source), kind: "PrintStatement", location };
472
+ }
473
+ /**
474
+ * Parses Ruby into the shared semantic module.
475
+ * @param {object} input - Parser input.
476
+ * @param {string} input.filename - Source filename.
477
+ * @param {string} input.source - Source text.
478
+ * @returns {import("../semantic/types.js").SemanticModule} Semantic module.
479
+ */
480
+ export function parseRuby({ filename, source }) {
481
+ const result = parsePrism(source, { filepath: filename });
482
+ if (result.errors.length > 0) {
483
+ const error = result.errors[0];
484
+ const location = locationFromOffsets(filename, source, error.location.startOffset, error.location.startOffset + error.location.length);
485
+ throw new SemantifoldDiagnostic({ code: "PARSE_ERROR", language: "ruby", location, message: error.message });
486
+ }
487
+ if (!(result.value instanceof ProgramNode))
488
+ throw new Error("Prism returned a non-program root.");
489
+ const body = result.value.statements.body;
490
+ const functions = body.filter((node) => node instanceof DefNode)
491
+ .map((node) => convertFunction(node, result.comments, filename, source));
492
+ const entryNodes = body.filter((node) => !(node instanceof DefNode));
493
+ const location = moduleLocation(filename, source);
494
+ if (functions.length == 0)
495
+ return unsupportedSyntax("ruby", "module without a function", location);
496
+ const firstEntry = entryNodes[0];
497
+ const entryLocation = firstEntry ? locationFromOffsets(filename, source, utf8ByteOffsetToUtf16Offset(source, firstEntry.location.startOffset), utf8ByteOffsetToUtf16Offset(source, (entryNodes.at(-1)?.location.startOffset ?? 0) + (entryNodes.at(-1)?.location.length ?? 0))) : location;
498
+ const entryVisible = new Set();
499
+ const entryBlock = {
500
+ kind: /** @type {const} */ ("Block"),
501
+ location: entryLocation,
502
+ statements: entryNodes.map((statement) => convertStatement(statement, result.comments, entryVisible, filename, source))
503
+ };
504
+ return {
505
+ entryPoint: {
506
+ body: entryBlock,
507
+ kind: "EntryPoint",
508
+ location: entryLocation
509
+ },
510
+ functions,
511
+ kind: "Module",
512
+ location
513
+ };
514
+ }
515
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVieS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mcm9udGVuZHMvcnVieS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxFQUNMLE9BQU8sRUFDUCxRQUFRLEVBQ1IsT0FBTyxFQUNQLFFBQVEsRUFDUixTQUFTLEVBQ1QsTUFBTSxFQUNOLFdBQVcsRUFDWCxzQkFBc0IsRUFDdEIscUJBQXFCLEVBQ3JCLHNCQUFzQixFQUN0QixNQUFNLEVBQ04sZUFBZSxFQUNmLFdBQVcsRUFDWCxxQkFBcUIsRUFDckIsVUFBVSxFQUNWLGNBQWMsRUFDZCxVQUFVLEVBQ1YsUUFBUSxFQUNSLFNBQVMsRUFDVixNQUFNLGFBQWEsQ0FBQTtBQUNwQixPQUFPLEVBQUMsV0FBVyxFQUFFLHFCQUFxQixFQUFFLGlCQUFpQixFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDdEYsT0FBTyxFQUFDLG1CQUFtQixFQUFFLGNBQWMsRUFBRSwyQkFBMkIsRUFBQyxNQUFNLHlCQUF5QixDQUFBO0FBQ3hHLE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLDBCQUEwQixDQUFBO0FBQzdELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLDJCQUEyQixDQUFBO0FBQzFELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLHdCQUF3QixDQUFBO0FBQzVELE9BQU8sRUFBQyx1QkFBdUIsRUFBQyxNQUFNLGNBQWMsQ0FBQTtBQUNwRCxNQUFNLFVBQVUsR0FBRyxNQUFNLFNBQVMsRUFBRSxDQUFBO0FBQ3BDLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDbkMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDO0lBQ1osQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDO0lBQ2pCLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQztJQUNqQixDQUFDLElBQUksRUFBRSxPQUFPLENBQUM7SUFDZixDQUFDLElBQUksRUFBRSxVQUFVLENBQUM7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SUFBSSxDQUFDLENBQUMsQ0FDM0YsQ0FDRixDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUE7SUFDWixNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO0lBQzlCLE1BQU0sVUFBVSxHQUFHO1FBQ2pCLElBQUksRUFBRSxvQkFBb0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUNwQyxRQUFRLEVBQUUsYUFBYTtRQUN2QixVQUFVLEVBQUUsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztLQUN4SCxDQUFBO0lBRUQsT0FBTztRQUNMLFVBQVUsRUFBRTtZQUNWLElBQUksRUFBRSxVQUFVO1lBQ2hCLElBQUksRUFBRSxZQUFZO1lBQ2xCLFFBQVEsRUFBRSxhQUFhO1NBQ3hCO1FBQ0QsU0FBUztRQUNULElBQUksRUFBRSxRQUFRO1FBQ2QsUUFBUTtLQUNULENBQUE7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7XG4gIEFuZE5vZGUsXG4gIENhbGxOb2RlLFxuICBEZWZOb2RlLFxuICBFbHNlTm9kZSxcbiAgRmFsc2VOb2RlLFxuICBJZk5vZGUsXG4gIEludGVnZXJOb2RlLFxuICBJbnRlcnBvbGF0ZWRTdHJpbmdOb2RlLFxuICBMb2NhbFZhcmlhYmxlUmVhZE5vZGUsXG4gIExvY2FsVmFyaWFibGVXcml0ZU5vZGUsXG4gIE9yTm9kZSxcbiAgUGFyZW50aGVzZXNOb2RlLFxuICBQcm9ncmFtTm9kZSxcbiAgUmVxdWlyZWRQYXJhbWV0ZXJOb2RlLFxuICBSZXR1cm5Ob2RlLFxuICBTdGF0ZW1lbnRzTm9kZSxcbiAgU3RyaW5nTm9kZSxcbiAgVHJ1ZU5vZGUsXG4gIGxvYWRQcmlzbVxufSBmcm9tIFwiQHJ1YnkvcHJpc21cIlxuaW1wb3J0IHttaXNzaW5nVHlwZSwgU2VtYW50aWZvbGREaWFnbm9zdGljLCB1bnN1cHBvcnRlZFN5bnRheH0gZnJvbSBcIi4uL2RpYWdub3N0aWMuanNcIlxuaW1wb3J0IHtsb2NhdGlvbkZyb21PZmZzZXRzLCBtb2R1bGVMb2NhdGlvbiwgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0fSBmcm9tIFwiLi4vc2VtYW50aWMvbG9jYXRpb24uanNcIlxuaW1wb3J0IHt3aXRoQWRhcHRlZE9wZXJhdGlvbn0gZnJvbSBcIi4uL3NlbWFudGljL29wZXJhdG9ycy5qc1wiXG5pbXBvcnQge3dpdGhQYXJzZXJSYW5nZXN9IGZyb20gXCIuLi9zZW1hbnRpYy9wcm92ZW5hbmNlLmpzXCJcbmltcG9ydCB7aGFzT25seVVuaWNvZGVTY2FsYXJzfSBmcm9tIFwiLi4vc2VtYW50aWMvc2NhbGFycy5qc1wiXG5pbXBvcnQge3JlcXVpcmVTb3VyY2VTY2FsYXJUeXBlfSBmcm9tIFwiLi9zY2FsYXJzLmpzXCJcbmNvbnN0IHBhcnNlUHJpc20gPSBhd2FpdCBsb2FkUHJpc20oKVxuY29uc3QgcnVieUJpbmFyeU9wZXJhdGlvbnMgPSBuZXcgTWFwKFtcbiAgW1wiK1wiLCBcIkFkZFwiXSxcbiAgW1wiLVwiLCBcIlN1YnRyYWN0XCJdLFxuICBbXCIqXCIsIFwiTXVsdGlwbHlcIl0sXG4gIFtcIj09XCIsIFwiRXF1YWxcIl0sXG4gIFtcIiE9XCIsIFwiTm90RXF1YWxcIl0sXG4gIFtcIjxcIiwgXCJMZXNzVGhhblwiXSxcbiAgW1wiPD1cIiwgXCJMZXNzVGhhbk9yRXF1YWxcIl0sXG4gIFtcIj5cIiwgXCJHcmVhdGVyVGhhblwiXSxcbiAgW1wiPj1cIiwgXCJHcmVhdGVyVGhhbk9yRXF1YWxcIl1cbl0pXG5cbi8qKlxuICogUmV0dXJucyBhIG5vcm1hbGl6ZWQgUHJpc20gbm9kZSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7e2xvY2F0aW9uOiBpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Mb2NhdGlvbn19IG5vZGUgLSBQcmlzbSBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gU291cmNlIGxvY2F0aW9uLlxuICovXG5mdW5jdGlvbiBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICByZXR1cm4gcHJpc21Mb2NhdGlvbihub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgUHJpc20gbG9jYXRpb24gaW50byBhIG5vcm1hbGl6ZWQgc291cmNlIGxvY2F0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Mb2NhdGlvbn0gbG9jYXRpb24gLSBQcmlzbSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IFNvdXJjZSBsb2NhdGlvbi5cbiAqL1xuZnVuY3Rpb24gcHJpc21Mb2NhdGlvbihsb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICByZXR1cm4gbG9jYXRpb25Gcm9tT2Zmc2V0cyhcbiAgICBmaWxlbmFtZSxcbiAgICBzb3VyY2UsXG4gICAgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0KHNvdXJjZSwgbG9jYXRpb24uc3RhcnRPZmZzZXQpLFxuICAgIHV0ZjhCeXRlT2Zmc2V0VG9VdGYxNk9mZnNldChzb3VyY2UsIGxvY2F0aW9uLnN0YXJ0T2Zmc2V0ICsgbG9jYXRpb24ubGVuZ3RoKVxuICApXG59XG5cbi8qKlxuICogU2xpY2VzIEphdmFTY3JpcHQgc291cmNlIHVzaW5nIFByaXNtJ3MgVVRGLTggYnl0ZSBvZmZzZXRzLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydE9mZnNldCAtIEluY2x1c2l2ZSBQcmlzbSBieXRlIG9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmRPZmZzZXQgLSBFeGNsdXNpdmUgUHJpc20gYnl0ZSBvZmZzZXQuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTb3VyY2UgdGV4dCBpbiB0aGUgYnl0ZSByYW5nZS5cbiAqL1xuZnVuY3Rpb24gc2xpY2VQcmlzbVNvdXJjZShzb3VyY2UsIHN0YXJ0T2Zmc2V0LCBlbmRPZmZzZXQpIHtcbiAgcmV0dXJuIHNvdXJjZS5zbGljZShcbiAgICB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBzdGFydE9mZnNldCksXG4gICAgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0KHNvdXJjZSwgZW5kT2Zmc2V0KVxuICApXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBzdXBwb3J0ZWQgUHJpc20gZXhwcmVzc2lvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZX0gbm9kZSAtIFByaXNtIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259IFNlbWFudGljIGV4cHJlc3Npb24uXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRFeHByZXNzaW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIFBhcmVudGhlc2VzTm9kZSAmJiBub2RlLmJvZHkgaW5zdGFuY2VvZiBTdGF0ZW1lbnRzTm9kZSAmJiBub2RlLmJvZHkuYm9keS5sZW5ndGggPT0gMSkge1xuICAgIHJldHVybiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLmJvZHkuYm9keVswXSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgTG9jYWxWYXJpYWJsZVJlYWROb2RlKSB7XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklkZW50aWZpZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbiwgbmFtZTogbm9kZS5uYW1lfSwge25hbWU6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgSW50ZWdlck5vZGUpIHtcbiAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKG5vZGUudmFsdWUpKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibm9uLXNhZmUgaW50ZWdlciBsaXRlcmFsXCIsIGxvY2F0aW9uKVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkludGVnZXJMaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IG5vZGUudmFsdWV9LCB7bGl0ZXJhbDogbG9jYXRpb259KVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBUcnVlTm9kZSB8fCBub2RlIGluc3RhbmNlb2YgRmFsc2VOb2RlKSB7XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkJvb2xlYW5MaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IG5vZGUgaW5zdGFuY2VvZiBUcnVlTm9kZX0sIHtsaXRlcmFsOiBsb2NhdGlvbn0pXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIFN0cmluZ05vZGUpIHtcbiAgICBjb25zdCBkZWNvZGVkID0gbm9kZS51bmVzY2FwZWRcblxuICAgIGlmICghZGVjb2RlZC52YWxpZEVuY29kaW5nIHx8IGRlY29kZWQuZW5jb2RpbmcgIT0gXCJ1dGYtOFwiIHx8IG5vZGUuaXNGb3JjZWRCaW5hcnlFbmNvZGluZygpIHx8XG4gICAgICAhaGFzT25seVVuaWNvZGVTY2FsYXJzKGRlY29kZWQudmFsdWUpKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiaW52YWxpZCBVbmljb2RlIHN0cmluZyBsaXRlcmFsXCIsIGxvY2F0aW9uKVxuICAgIH1cblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJTdHJpbmdMaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IGRlY29kZWQudmFsdWV9LCB7bGl0ZXJhbDogbG9jYXRpb259KVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBJbnRlcnBvbGF0ZWRTdHJpbmdOb2RlKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiaW50ZXJwb2xhdGVkIHN0cmluZ1wiLCBsb2NhdGlvbilcblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgbm9kZS5uYW1lID09IFwiIVwiKSB7XG4gICAgY29uc3Qgb3BlcmF0b3JMb2NhdGlvbiA9IHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jID8/IG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICBpZiAobm9kZS5jYWxsT3BlcmF0b3JMb2MpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJxdWFsaWZpZWQgYm9vbGVhbiBub3RcIiwgb3BlcmF0b3JMb2NhdGlvbilcbiAgICBpZiAobm9kZS5tZXNzYWdlTG9jPy5sZW5ndGggIT0gMSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInByZWNlZGVuY2Utc2Vuc2l0aXZlIGJvb2xlYW4gbm90XCIsIG9wZXJhdG9yTG9jYXRpb24pXG4gICAgfVxuICAgIGlmIChub2RlLmFyZ3VtZW50c18pIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJib29sZWFuIG5vdCBhcmd1bWVudCBsaXN0XCIsIG9wZXJhdG9yTG9jYXRpb24pXG5cbiAgICBjb25zdCBzZW1hbnRpYyA9IHdpdGhBZGFwdGVkT3BlcmF0aW9uKHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogXCJVbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgb3BlcmFuZDogY29udmVydEV4cHJlc3Npb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9LCB7b3BlcmF0b3I6IG9wZXJhdG9yTG9jYXRpb259KSwgXCJOb3RcIilcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChzZW1hbnRpYykpXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgbm9kZS5uYW1lID09IFwiLUBcIikge1xuICAgIGNvbnN0IG9wZXJhdG9yTG9jYXRpb24gPSBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gICAgaWYgKG5vZGUuY2FsbE9wZXJhdG9yTG9jKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwicXVhbGlmaWVkIGludGVnZXIgbmVnYXRpb25cIiwgb3BlcmF0b3JMb2NhdGlvbilcbiAgICBpZiAobm9kZS5hcmd1bWVudHNfKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiaW50ZWdlciBuZWdhdGlvbiBhcmd1bWVudCBsaXN0XCIsIG9wZXJhdG9yTG9jYXRpb24pXG5cbiAgICBjb25zdCBzZW1hbnRpYyA9IHdpdGhBZGFwdGVkT3BlcmF0aW9uKHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogXCJVbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgb3BlcmFuZDogY29udmVydEV4cHJlc3Npb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9LCB7b3BlcmF0b3I6IG9wZXJhdG9yTG9jYXRpb259KSwgXCJOZWdhdGVcIilcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChzZW1hbnRpYykpXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIEFuZE5vZGUgfHwgbm9kZSBpbnN0YW5jZW9mIE9yTm9kZSkge1xuICAgIGNvbnN0IG9wZXJhdG9yTG9jYXRpb24gPSBwcmlzbUxvY2F0aW9uKG5vZGUub3BlcmF0b3JMb2MsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgY29uc3Qgc291cmNlT3BlcmF0b3IgPSBzb3VyY2Uuc2xpY2Uob3BlcmF0b3JMb2NhdGlvbi5zdGFydC5vZmZzZXQsIG9wZXJhdG9yTG9jYXRpb24uZW5kLm9mZnNldClcblxuICAgIGlmIChzb3VyY2VPcGVyYXRvciAhPSBcIiYmXCIgJiYgc291cmNlT3BlcmF0b3IgIT0gXCJ8fFwiKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIGBwcmVjZWRlbmNlLXNlbnNpdGl2ZSBib29sZWFuICR7c291cmNlT3BlcmF0b3J9YCwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgY29uc3Qgc2VtYW50aWMgPSB3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IFwiQmluYXJ5RXhwcmVzc2lvblwiLFxuICAgICAgbGVmdDogY29udmVydEV4cHJlc3Npb24obm9kZS5sZWZ0LCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgcmlnaHQ6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmlnaHQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSwge29wZXJhdG9yOiBvcGVyYXRvckxvY2F0aW9ufSksIG5vZGUgaW5zdGFuY2VvZiBBbmROb2RlID8gXCJBbmRcIiA6IFwiT3JcIilcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChzZW1hbnRpYykpXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgcnVieUJpbmFyeU9wZXJhdGlvbnMuaGFzKG5vZGUubmFtZSkgJiYgbm9kZS5jYWxsT3BlcmF0b3JMb2MgJiZcbiAgICBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoID09IDEpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXG4gICAgICBcInJ1YnlcIixcbiAgICAgIGBxdWFsaWZpZWQgYmluYXJ5IG9wZXJhdG9yICR7bm9kZS5uYW1lfWAsXG4gICAgICBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIClcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgQ2FsbE5vZGUgJiYgbm9kZS5yZWNlaXZlciAmJiBydWJ5QmluYXJ5T3BlcmF0aW9ucy5oYXMobm9kZS5uYW1lKSAmJiBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoID09IDEpIHtcbiAgICBjb25zdCBzZW1hbnRpYyA9IHdpdGhBZGFwdGVkT3BlcmF0aW9uKHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogXCJCaW5hcnlFeHByZXNzaW9uXCIsXG4gICAgICBsZWZ0OiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLnJlY2VpdmVyLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgcmlnaHQ6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUuYXJndW1lbnRzXy5hcmd1bWVudHNfWzBdLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0sIHtvcGVyYXRvcjogcHJpc21Mb2NhdGlvbihub2RlLm1lc3NhZ2VMb2MgPz8gbm9kZS5sb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSl9KSwgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy9vcGVyYXRvcnMuanNcIikuQWRhcHRlZE9wZXJhdGlvbn0gKi8gKHJ1YnlCaW5hcnlPcGVyYXRpb25zLmdldChub2RlLm5hbWUpKSlcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChzZW1hbnRpYykpXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmICFub2RlLnJlY2VpdmVyKSB7XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgYXJndW1lbnRzOiAobm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfID8/IFtdKS5tYXAoKGFyZ3VtZW50KSA9PiBjb252ZXJ0RXhwcmVzc2lvbihhcmd1bWVudCwgZmlsZW5hbWUsIHNvdXJjZSkpLFxuICAgICAgY2FsbGVlOiBub2RlLm5hbWUsXG4gICAgICBraW5kOiBcIkNhbGxFeHByZXNzaW9uXCIsXG4gICAgICBsb2NhdGlvblxuICAgIH0sIHtjYWxsZWU6IHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jID8/IG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpfSlcbiAgfVxuXG4gIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgbm9kZS5jb25zdHJ1Y3Rvci5uYW1lLCBsb2NhdGlvbilcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgZXhwbGljaXQgUnVieSByZXR1cm4uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQcmlzbSBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5SZXR1cm5TdGF0ZW1lbnR9IFNlbWFudGljIHJldHVybi5cbiAqL1xuZnVuY3Rpb24gY29udmVydFJldHVybihub2RlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKCEobm9kZSBpbnN0YW5jZW9mIFJldHVybk5vZGUpIHx8IG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzXy5sZW5ndGggIT0gMSkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgbm9kZS5jb25zdHJ1Y3Rvci5uYW1lLCBsb2NhdGlvbilcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZXhwcmVzc2lvbjogY29udmVydEV4cHJlc3Npb24obm9kZS5hcmd1bWVudHNfLmFyZ3VtZW50c19bMF0sIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgIGtpbmQ6IFwiUmV0dXJuU3RhdGVtZW50XCIsXG4gICAgbG9jYXRpb25cbiAgfVxufVxuXG4vKipcbiAqIFJlYWRzIFByaXNtLW93bmVkIFJCUy1zdHlsZSB0eXBlIGNvbW1lbnRzIGRpcmVjdGx5IHByZWNlZGluZyBhIGRlZmluaXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge3tsb2NhdGlvbjogaW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTG9jYXRpb259fSBub2RlIC0gQ29tbWVudCBvd25lci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7e3BhcmFtZXRlcnM6IE1hcDxzdHJpbmcsIHtsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIHNvdXJjZVR5cGU6IHN0cmluZ30+LCByZXR1cm5UeXBlOiB7bG9jYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBzb3VyY2VUeXBlOiBzdHJpbmd9IHwgdW5kZWZpbmVkfX0gRGVjbGFyZWQgdHlwZXMuXG4gKi9cbmZ1bmN0aW9uIHR5cGVDb21tZW50cyhjb21tZW50cywgbm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBwcmVjZWRpbmcgPSBhc3NvY2lhdGVkQ29tbWVudHMoY29tbWVudHMsIG5vZGUsIHNvdXJjZSlcbiAgY29uc3QgcGFyYW1ldGVyVHlwZXMgPSBuZXcgTWFwKClcbiAgLyoqIEB0eXBlIHt7bG9jYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBzb3VyY2VUeXBlOiBzdHJpbmd9IHwgdW5kZWZpbmVkfSAqL1xuICBsZXQgcmV0dXJuVHlwZVxuXG4gIGZvciAoY29uc3QgY29tbWVudCBvZiBwcmVjZWRpbmcpIHtcbiAgICBjb25zdCB3b3JkcyA9IGNvbW1lbnRUb2tlbnMoY29tbWVudCwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIGlmICh3b3Jkc1swXT8udGV4dCA9PSBcIkBwYXJhbVwiICYmIHdvcmRzLmxlbmd0aCA9PSAzKSB7XG4gICAgICBwYXJhbWV0ZXJUeXBlcy5zZXQod29yZHNbMV0udGV4dCwge2xvY2F0aW9uOiB3b3Jkc1syXS5sb2NhdGlvbiwgc291cmNlVHlwZTogd29yZHNbMl0udGV4dH0pXG4gICAgfVxuICAgIGlmICh3b3Jkc1swXT8udGV4dCA9PSBcIkByZXR1cm5cIiAmJiB3b3Jkcy5sZW5ndGggPT0gMikge1xuICAgICAgcmV0dXJuVHlwZSA9IHtsb2NhdGlvbjogd29yZHNbMV0ubG9jYXRpb24sIHNvdXJjZVR5cGU6IHdvcmRzWzFdLnRleHR9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtwYXJhbWV0ZXJzOiBwYXJhbWV0ZXJUeXBlcywgcmV0dXJuVHlwZX1cbn1cblxuLyoqXG4gKiBMZXhlcyB3aGl0ZXNwYWNlLXNlcGFyYXRlZCBtZXRhZGF0YSB0b2tlbnMgaW5zaWRlIGEgUHJpc20tb3duZWQgUnVieSBjb21tZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudH0gY29tbWVudCAtIFByaXNtIGNvbW1lbnQgdG9rZW4uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3tsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIHRleHQ6IHN0cmluZ31bXX0gTWV0YWRhdGEgdG9rZW5zLlxuICovXG5mdW5jdGlvbiBjb21tZW50VG9rZW5zKGNvbW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3Qgc3RhcnQgPSB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0KVxuICBjb25zdCBlbmQgPSB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0ICsgY29tbWVudC5sb2NhdGlvbi5sZW5ndGgpXG4gIGNvbnN0IHRva2VucyA9IFtdXG4gIGxldCBvZmZzZXQgPSBzdGFydCArIDFcblxuICB3aGlsZSAob2Zmc2V0IDwgZW5kKSB7XG4gICAgd2hpbGUgKG9mZnNldCA8IGVuZCAmJiBpc1J1YnlNZXRhZGF0YVdoaXRlc3BhY2Uoc291cmNlW29mZnNldF0pKSBvZmZzZXQrK1xuICAgIGNvbnN0IHRva2VuU3RhcnQgPSBvZmZzZXRcblxuICAgIHdoaWxlIChvZmZzZXQgPCBlbmQgJiYgIWlzUnVieU1ldGFkYXRhV2hpdGVzcGFjZShzb3VyY2Vbb2Zmc2V0XSkpIG9mZnNldCsrXG4gICAgaWYgKHRva2VuU3RhcnQgPCBvZmZzZXQpIHtcbiAgICAgIHRva2Vucy5wdXNoKHtsb2NhdGlvbjogbG9jYXRpb25Gcm9tT2Zmc2V0cyhmaWxlbmFtZSwgc291cmNlLCB0b2tlblN0YXJ0LCBvZmZzZXQpLCB0ZXh0OiBzb3VyY2Uuc2xpY2UodG9rZW5TdGFydCwgb2Zmc2V0KX0pXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRva2Vuc1xufVxuXG4vKipcbiAqIENoZWNrcyBvbmUgUnVieSBtZXRhZGF0YSBzZXBhcmF0b3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gY2hhcmFjdGVyIC0gU291cmNlIGNoYXJhY3Rlci5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIGl0IHNlcGFyYXRlcyBtZXRhZGF0YSB0b2tlbnMuXG4gKi9cbmZ1bmN0aW9uIGlzUnVieU1ldGFkYXRhV2hpdGVzcGFjZShjaGFyYWN0ZXIpIHtcbiAgcmV0dXJuIGNoYXJhY3RlciA9PSBcIiBcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXHRcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXHJcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXG5cIlxufVxuXG4vKipcbiAqIFNlbGVjdHMgb25seSB0aGUgY29udGlndW91cyBjb21tZW50IGJsb2NrIGltbWVkaWF0ZWx5IGJlZm9yZSBhIGRlZmluaXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge3tsb2NhdGlvbjogaW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTG9jYXRpb259fSBub2RlIC0gQ29tbWVudCBvd25lci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiQHJ1YnkvcHJpc20vc3JjL2Rlc2VyaWFsaXplLmpzXCIpLkNvbW1lbnRbXX0gQXNzb2NpYXRlZCBjb21tZW50cy5cbiAqL1xuZnVuY3Rpb24gYXNzb2NpYXRlZENvbW1lbnRzKGNvbW1lbnRzLCBub2RlLCBzb3VyY2UpIHtcbiAgY29uc3QgcHJlY2VkaW5nID0gY29tbWVudHMuZmlsdGVyKChjb21tZW50KSA9PiBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0IDwgbm9kZS5sb2NhdGlvbi5zdGFydE9mZnNldClcbiAgICAuc29ydCgobGVmdCwgcmlnaHQpID0+IGxlZnQubG9jYXRpb24uc3RhcnRPZmZzZXQgLSByaWdodC5sb2NhdGlvbi5zdGFydE9mZnNldClcbiAgY29uc3QgYXNzb2NpYXRlZCA9IFtdXG4gIGxldCBib3VuZGFyeSA9IG5vZGUubG9jYXRpb24uc3RhcnRPZmZzZXRcblxuICBmb3IgKGxldCBpbmRleCA9IHByZWNlZGluZy5sZW5ndGggLSAxOyBpbmRleCA+PSAwOyBpbmRleC0tKSB7XG4gICAgY29uc3QgY29tbWVudCA9IHByZWNlZGluZ1tpbmRleF1cbiAgICBjb25zdCBlbmRPZmZzZXQgPSBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0ICsgY29tbWVudC5sb2NhdGlvbi5sZW5ndGhcbiAgICBjb25zdCBnYXAgPSBzbGljZVByaXNtU291cmNlKHNvdXJjZSwgZW5kT2Zmc2V0LCBib3VuZGFyeSlcblxuICAgIGlmICghaXNJbW1lZGlhdGVDb21tZW50R2FwKGdhcCkpIGJyZWFrXG5cbiAgICBhc3NvY2lhdGVkLnVuc2hpZnQoY29tbWVudClcbiAgICBib3VuZGFyeSA9IGNvbW1lbnQubG9jYXRpb24uc3RhcnRPZmZzZXRcbiAgfVxuXG4gIHJldHVybiBhc3NvY2lhdGVkXG59XG5cbi8qKlxuICogUmVhZHMgb25lIGV4YWN0IFJ1YnkgbG9jYWwgdHlwZSBjYXJyaWVyIGFuZCBpbW11dGFiaWxpdHkgbWFya2VyLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtMb2NhbFZhcmlhYmxlV3JpdGVOb2RlfSBub2RlIC0gTG9jYWwgd3JpdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3tpbW11dGFibGU6IGJvb2xlYW4sIHR5cGU6IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlR5cGVSZWZlcmVuY2V9IHwgdW5kZWZpbmVkfSBNZXRhZGF0YSB3aGVuIHByZXNlbnQuXG4gKi9cbmZ1bmN0aW9uIGxvY2FsTWV0YWRhdGEoY29tbWVudHMsIG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgYXNzb2NpYXRlZCA9IGFzc29jaWF0ZWRDb21tZW50cyhjb21tZW50cywgbm9kZSwgc291cmNlKVxuICBjb25zdCBtZXRhZGF0YSA9IGFzc29jaWF0ZWQubWFwKChjb21tZW50KSA9PiBjb21tZW50VG9rZW5zKGNvbW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICBjb25zdCB0eXBlTWV0YWRhdGEgPSBtZXRhZGF0YS5maWx0ZXIoKFt0b2tlbl0pID0+IHRva2VuPy50ZXh0ID09IFwiQHR5cGVcIilcbiAgY29uc3QgaW1tdXRhYmxlTWV0YWRhdGEgPSBtZXRhZGF0YS5maWx0ZXIoKFt0b2tlbl0pID0+IHRva2VuPy50ZXh0ID09IFwiQHNlbWFudGlmb2xkLWltbXV0YWJsZVwiKVxuICBjb25zdCBwcm9maWxlTWV0YWRhdGEgPSBtZXRhZGF0YS5maWx0ZXIoKFt0b2tlbl0pID0+IHtcbiAgICByZXR1cm4gdG9rZW4/LnRleHQuc3RhcnRzV2l0aChcIkB0eXBlXCIpIHx8IHRva2VuPy50ZXh0LnN0YXJ0c1dpdGgoXCJAc2VtYW50aWZvbGQtaW1tdXRhYmxlXCIpXG4gIH0pXG5cbiAgaWYgKHByb2ZpbGVNZXRhZGF0YS5sZW5ndGggPT0gMCkgcmV0dXJuIHVuZGVmaW5lZFxuXG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKHR5cGVNZXRhZGF0YS5sZW5ndGggIT0gMSB8fCB0eXBlTWV0YWRhdGFbMF0ubGVuZ3RoICE9IDIgfHxcbiAgICBpbW11dGFibGVNZXRhZGF0YS5sZW5ndGggPiAxIHx8IGltbXV0YWJsZU1ldGFkYXRhLnNvbWUoKHRva2VucykgPT4gdG9rZW5zLmxlbmd0aCAhPSAxKSB8fFxuICAgIHByb2ZpbGVNZXRhZGF0YS5sZW5ndGggIT0gdHlwZU1ldGFkYXRhLmxlbmd0aCArIGltbXV0YWJsZU1ldGFkYXRhLmxlbmd0aCkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJtYWxmb3JtZWQgbG9jYWwgdHlwZSBtZXRhZGF0YVwiLCBsb2NhdGlvbilcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgaW1tdXRhYmxlOiBpbW11dGFibGVNZXRhZGF0YS5sZW5ndGggPT0gMSxcbiAgICB0eXBlOiBjb252ZXJ0VHlwZSh0eXBlTWV0YWRhdGFbMF1bMV0udGV4dCwgYExvY2FsICcke25vZGUubmFtZX0nYCwgbG9jYXRpb24sIHR5cGVNZXRhZGF0YVswXVsxXS5sb2NhdGlvbilcbiAgfVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBSdWJ5IGxvY2FsIGRlY2xhcmF0aW9uIG9yIGFzc2lnbm1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQcmlzbSBub2RlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gdmlzaWJsZSAtIE5hbWVzIHZpc2libGUgZHVyaW5nIGFkYXB0YXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkxvY2FsU3RhdGVtZW50fSBTZW1hbnRpYyBsb2NhbCBzdGF0ZW1lbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRMb2NhbFN0YXRlbWVudChub2RlLCBjb21tZW50cywgdmlzaWJsZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmICghKG5vZGUgaW5zdGFuY2VvZiBMb2NhbFZhcmlhYmxlV3JpdGVOb2RlKSkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIGxvY2F0aW9uKVxuXG4gIGNvbnN0IG1ldGFkYXRhID0gbG9jYWxNZXRhZGF0YShjb21tZW50cywgbm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobWV0YWRhdGEpIHtcbiAgICB2aXNpYmxlLmFkZChub2RlLm5hbWUpXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgaW5pdGlhbGl6ZXI6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUudmFsdWUsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAga2luZDogXCJMb2NhbERlY2xhcmF0aW9uXCIsXG4gICAgICBsb2NhdGlvbixcbiAgICAgIG11dGFibGU6ICFtZXRhZGF0YS5pbW11dGFibGUsXG4gICAgICBuYW1lOiBub2RlLm5hbWUsXG4gICAgICB0eXBlOiBtZXRhZGF0YS50eXBlXG4gICAgfSwge25hbWU6IHByaXNtTG9jYXRpb24obm9kZS5uYW1lTG9jLCBmaWxlbmFtZSwgc291cmNlKSwgb3BlcmF0b3I6IHByaXNtTG9jYXRpb24obm9kZS5vcGVyYXRvckxvYywgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9XG5cbiAgaWYgKCF2aXNpYmxlLmhhcyhub2RlLm5hbWUpKSByZXR1cm4gbWlzc2luZ1R5cGUoXCJydWJ5XCIsIGBMb2NhbCAnJHtub2RlLm5hbWV9J2AsIGxvY2F0aW9uKVxuXG4gIGNvbnN0IHRhcmdldExvY2F0aW9uID0gcHJpc21Mb2NhdGlvbihub2RlLm5hbWVMb2MsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IHRhcmdldCA9IHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklkZW50aWZpZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbjogdGFyZ2V0TG9jYXRpb24sIG5hbWU6IG5vZGUubmFtZX0sIHtcbiAgICBuYW1lOiB0YXJnZXRMb2NhdGlvblxuICB9KVxuXG4gIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICBleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLnZhbHVlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBraW5kOiBcIkFzc2lnbm1lbnRTdGF0ZW1lbnRcIixcbiAgICBsb2NhdGlvbixcbiAgICB0YXJnZXRcbiAgfSwge29wZXJhdG9yOiBwcmlzbUxvY2F0aW9uKG5vZGUub3BlcmF0b3JMb2MsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgZXhoYXVzdGl2ZSBQcmlzbSBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQcmlzbSBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSB2aXNpYmxlIC0gTmFtZXMgdmlzaWJsZSBkdXJpbmcgYWRhcHRhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU3RhdGVtZW50fSBTZW1hbnRpYyBzdGF0ZW1lbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRTdGF0ZW1lbnQobm9kZSwgY29tbWVudHMsIHZpc2libGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBSZXR1cm5Ob2RlKSByZXR1cm4gY29udmVydFJldHVybihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIElmTm9kZSkgcmV0dXJuIGNvbnZlcnRJZihub2RlLCBjb21tZW50cywgdmlzaWJsZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBMb2NhbFZhcmlhYmxlV3JpdGVOb2RlKSByZXR1cm4gY29udmVydExvY2FsU3RhdGVtZW50KG5vZGUsIGNvbW1lbnRzLCB2aXNpYmxlLCBmaWxlbmFtZSwgc291cmNlKVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlKSByZXR1cm4gY29udmVydFByaW50KG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgb3JkZXJlZCBQcmlzbSBzdGF0ZW1lbnQgbGlzdC5cbiAqIEBwYXJhbSB7U3RhdGVtZW50c05vZGUgfCBudWxsfSBub2RlIC0gUHJpc20gc3RhdGVtZW50cywgb3IgYW4gZW1wdHkgc291cmNlIGJsb2NrLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gdmlzaWJsZSAtIE5hbWVzIHZpc2libGUgb24gYmxvY2sgZW50cnkuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gZmFsbGJhY2tMb2NhdGlvbiAtIEVtcHR5IGJsb2NrIGxvY2F0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkJsb2NrfSBTZW1hbnRpYyBibG9jay5cbiAqL1xuZnVuY3Rpb24gY29udmVydEJsb2NrKG5vZGUsIGNvbW1lbnRzLCB2aXNpYmxlLCBmaWxlbmFtZSwgc291cmNlLCBmYWxsYmFja0xvY2F0aW9uKSB7XG4gIHJldHVybiB7XG4gICAga2luZDogXCJCbG9ja1wiLFxuICAgIGxvY2F0aW9uOiBub2RlID8gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIDogZmFsbGJhY2tMb2NhdGlvbixcbiAgICBzdGF0ZW1lbnRzOiBub2RlID8gbm9kZS5ib2R5Lm1hcCgoc3RhdGVtZW50KSA9PiBjb252ZXJ0U3RhdGVtZW50KHN0YXRlbWVudCwgY29tbWVudHMsIHZpc2libGUsIGZpbGVuYW1lLCBzb3VyY2UpKSA6IFtdXG4gIH1cbn1cblxuLyoqXG4gKiBDaGVja3MgdGhhdCBhIGNvbW1lbnQgYW5kIGl0cyBvd25lciBhcmUgc2VwYXJhdGVkIGJ5IGF0IG1vc3Qgb25lIG5ld2xpbmUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZ2FwIC0gU291cmNlIGJldHdlZW4gdGhlIGNvbW1lbnQgYW5kIGZvbGxvd2luZyBpdGVtLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGdhcCBpcyBpbW1lZGlhdGUgd2hpdGVzcGFjZS5cbiAqL1xuZnVuY3Rpb24gaXNJbW1lZGlhdGVDb21tZW50R2FwKGdhcCkge1xuICBsZXQgbmV3bGluZXMgPSAwXG5cbiAgZm9yIChjb25zdCBjaGFyYWN0ZXIgb2YgZ2FwKSB7XG4gICAgaWYgKGNoYXJhY3RlciA9PSBcIlxcblwiKSB7XG4gICAgICBuZXdsaW5lcysrXG4gICAgfSBlbHNlIGlmIChjaGFyYWN0ZXIgIT0gXCIgXCIgJiYgY2hhcmFjdGVyICE9IFwiXFx0XCIgJiYgY2hhcmFjdGVyICE9IFwiXFxyXCIpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdsaW5lcyA8PSAxXG59XG5cbi8qKlxuICogUmVxdWlyZXMgYW4gZXhhY3Qgc3VwcG9ydGVkIFJ1Ynkgc2NhbGFyIHNwZWxsaW5nLlxuICogQHBhcmFtIHtzdHJpbmcgfCB1bmRlZmluZWR9IHNvdXJjZVR5cGUgLSBSdWJ5IHR5cGUgY29tbWVudCB2YWx1ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzdWJqZWN0IC0gVHlwZWQgc3ViamVjdC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gU291cmNlIGxvY2F0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gW3R5cGVMb2NhdGlvbl0gLSBFeGFjdCB0eXBlIGNvbW1lbnQgdG9rZW4gbG9jYXRpb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuVHlwZVJlZmVyZW5jZX0gU2VtYW50aWMgdHlwZS5cbiAqL1xuZnVuY3Rpb24gY29udmVydFR5cGUoc291cmNlVHlwZSwgc3ViamVjdCwgbG9jYXRpb24sIHR5cGVMb2NhdGlvbiA9IGxvY2F0aW9uKSB7XG4gIHJldHVybiByZXF1aXJlU291cmNlU2NhbGFyVHlwZShcInJ1YnlcIiwgc291cmNlVHlwZSwgc3ViamVjdCwgbG9jYXRpb24sIHR5cGVMb2NhdGlvbilcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIFJ1YnkgZGVmaW5pdGlvbi5cbiAqIEBwYXJhbSB7RGVmTm9kZX0gbm9kZSAtIFByaXNtIGRlZmluaXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkZ1bmN0aW9uRGVjbGFyYXRpb259IFNlbWFudGljIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0RnVuY3Rpb24obm9kZSwgY29tbWVudHMsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoIW5vZGUucGFyYW1ldGVycyB8fCBub2RlLnBhcmFtZXRlcnMub3B0aW9uYWxzLmxlbmd0aCA+IDAgfHwgbm9kZS5wYXJhbWV0ZXJzLnJlc3QgfHwgbm9kZS5wYXJhbWV0ZXJzLnBvc3RzLmxlbmd0aCA+IDAgfHxcbiAgICBub2RlLnBhcmFtZXRlcnMua2V5d29yZHMubGVuZ3RoID4gMCB8fCBub2RlLnBhcmFtZXRlcnMua2V5d29yZFJlc3QgfHwgbm9kZS5wYXJhbWV0ZXJzLmJsb2NrIHx8XG4gICAgbm9kZS5wYXJhbWV0ZXJzLnJlcXVpcmVkcy5zb21lKChwYXJhbWV0ZXIpID0+ICEocGFyYW1ldGVyIGluc3RhbmNlb2YgUmVxdWlyZWRQYXJhbWV0ZXJOb2RlKSkpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwicGFyYW1ldGVyc1wiLCBsb2NhdGlvbilcbiAgfVxuXG4gIGNvbnN0IGRlY2xhcmVkVHlwZXMgPSB0eXBlQ29tbWVudHMoY29tbWVudHMsIG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IHBhcmFtZXRlcnMgPSBub2RlLnBhcmFtZXRlcnMucmVxdWlyZWRzLm1hcCgocGFyYW1ldGVyKSA9PiB7XG4gICAgaWYgKCEocGFyYW1ldGVyIGluc3RhbmNlb2YgUmVxdWlyZWRQYXJhbWV0ZXJOb2RlKSkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBwYXJhbWV0ZXIuY29uc3RydWN0b3IubmFtZSwgbG9jYXRpb24pXG5cbiAgICBjb25zdCBwYXJhbWV0ZXJMb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihwYXJhbWV0ZXIsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICBjb25zdCBkZWNsYXJlZFR5cGUgPSBkZWNsYXJlZFR5cGVzLnBhcmFtZXRlcnMuZ2V0KHBhcmFtZXRlci5uYW1lKVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUGFyYW1ldGVyXCIpLFxuICAgICAgbG9jYXRpb246IHBhcmFtZXRlckxvY2F0aW9uLFxuICAgICAgbmFtZTogcGFyYW1ldGVyLm5hbWUsXG4gICAgICB0eXBlOiBjb252ZXJ0VHlwZShkZWNsYXJlZFR5cGU/LnNvdXJjZVR5cGUsIGBQYXJhbWV0ZXIgJyR7cGFyYW1ldGVyLm5hbWV9J2AsIHBhcmFtZXRlckxvY2F0aW9uLCBkZWNsYXJlZFR5cGU/LmxvY2F0aW9uKVxuICAgIH0sIHtuYW1lOiBwYXJhbWV0ZXJMb2NhdGlvbn0pXG4gIH0pXG4gIGNvbnN0IHZpc2libGUgPSBuZXcgU2V0KHBhcmFtZXRlcnMubWFwKChwYXJhbWV0ZXIpID0+IHBhcmFtZXRlci5uYW1lKSlcbiAgY29uc3QgYm9keSA9IGNvbnZlcnRCbG9jayhub2RlLmJvZHkgaW5zdGFuY2VvZiBTdGF0ZW1lbnRzTm9kZSA/IG5vZGUuYm9keSA6IG51bGwsIGNvbW1lbnRzLCB2aXNpYmxlLCBmaWxlbmFtZSwgc291cmNlLCBsb2NhdGlvbilcblxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgYm9keSxcbiAgICBraW5kOiBcIkZ1bmN0aW9uRGVjbGFyYXRpb25cIixcbiAgICBsb2NhdGlvbixcbiAgICBuYW1lOiBub2RlLm5hbWUsXG4gICAgcGFyYW1ldGVycyxcbiAgICByZXR1cm5UeXBlOiBjb252ZXJ0VHlwZShkZWNsYXJlZFR5cGVzLnJldHVyblR5cGU/LnNvdXJjZVR5cGUsIGBGdW5jdGlvbiAnJHtub2RlLm5hbWV9JyByZXR1cm5gLCBsb2NhdGlvbiwgZGVjbGFyZWRUeXBlcy5yZXR1cm5UeXBlPy5sb2NhdGlvbilcbiAgfSwge25hbWU6IHByaXNtTG9jYXRpb24obm9kZS5uYW1lTG9jLCBmaWxlbmFtZSwgc291cmNlKX0pXG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGV4aXN0aW5nIFJ1YnkgaWYvZWxzZSB0ZXJtaW5hbCB3aXRoIHJlc3RyaWN0ZWQgYnJhbmNoIHByZWZpeGVzLlxuICogQHBhcmFtIHtJZk5vZGV9IG5vZGUgLSBQcmlzbSBpZiBub2RlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gdmlzaWJsZSAtIEVuY2xvc2luZyB2aXNpYmxlIG5hbWVzLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5JZlN0YXRlbWVudH0gU2VtYW50aWMgYnJhbmNoLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0SWYobm9kZSwgY29tbWVudHMsIHZpc2libGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoIW5vZGUuaWZLZXl3b3JkTG9jIHx8IG5vZGUuaWZLZXl3b3JkTG9jLnN0YXJ0T2Zmc2V0ICE9IG5vZGUubG9jYXRpb24uc3RhcnRPZmZzZXQpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibW9kaWZpZXIgY29uZGl0aW9uYWxcIiwgbm9kZS5pZktleXdvcmRMb2NcbiAgICAgID8gcHJpc21Mb2NhdGlvbihub2RlLmlmS2V5d29yZExvYywgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICAgIDogbG9jYXRpb24pXG4gIH1cblxuICBjb25zdCBjb25zZXF1ZW50VmlzaWJsZSA9IG5ldyBTZXQodmlzaWJsZSlcbiAgbGV0IGFsdGVybmF0ZVxuXG4gIGlmIChub2RlLnN1YnNlcXVlbnQpIHtcbiAgICBjb25zdCBhbHRlcm5hdGVWaXNpYmxlID0gbmV3IFNldCh2aXNpYmxlKVxuXG4gICAgaWYgKG5vZGUuc3Vic2VxdWVudCBpbnN0YW5jZW9mIEVsc2VOb2RlKSB7XG4gICAgICBhbHRlcm5hdGUgPSBjb252ZXJ0QmxvY2sobm9kZS5zdWJzZXF1ZW50LnN0YXRlbWVudHMsIGNvbW1lbnRzLCBhbHRlcm5hdGVWaXNpYmxlLCBmaWxlbmFtZSwgc291cmNlLFxuICAgICAgICBub2RlTG9jYXRpb24obm9kZS5zdWJzZXF1ZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICB9IGVsc2UgaWYgKG5vZGUuc3Vic2VxdWVudCBpbnN0YW5jZW9mIElmTm9kZSkge1xuICAgICAgYWx0ZXJuYXRlID0ge1xuICAgICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJCbG9ja1wiKSxcbiAgICAgICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbihub2RlLnN1YnNlcXVlbnQsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgICBzdGF0ZW1lbnRzOiBbY29udmVydElmKG5vZGUuc3Vic2VxdWVudCwgY29tbWVudHMsIGFsdGVybmF0ZVZpc2libGUsIGZpbGVuYW1lLCBzb3VyY2UpXVxuICAgICAgfVxuICAgIH0gZWxzZSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIG5vZGUuc3Vic2VxdWVudC5jb25zdHJ1Y3Rvci5uYW1lLCBub2RlTG9jYXRpb24obm9kZS5zdWJzZXF1ZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uKGFsdGVybmF0ZSA/IHthbHRlcm5hdGV9IDoge30pLFxuICAgIGNvbmRpdGlvbjogY29udmVydEV4cHJlc3Npb24obm9kZS5wcmVkaWNhdGUsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgIGNvbnNlcXVlbnQ6IGNvbnZlcnRCbG9jayhub2RlLnN0YXRlbWVudHMsIGNvbW1lbnRzLCBjb25zZXF1ZW50VmlzaWJsZSwgZmlsZW5hbWUsIHNvdXJjZSwgbG9jYXRpb24pLFxuICAgIGtpbmQ6IFwiSWZTdGF0ZW1lbnRcIixcbiAgICBsb2NhdGlvblxuICB9XG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIHN1cHBvcnRlZCBSdWJ5IHB1dHMgZW50cnkgcG9pbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQcmlzbSBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QcmludFN0YXRlbWVudH0gUHJpbnQgc3RhdGVtZW50LlxuICovXG5mdW5jdGlvbiBjb252ZXJ0UHJpbnQobm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmICghKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSkgfHwgbm9kZS5yZWNlaXZlciB8fCBub2RlLm5hbWUgIT0gXCJwdXRzXCIgfHwgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCAhPSAxKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIGxvY2F0aW9uKVxuICB9XG5cbiAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXSwgZmlsZW5hbWUsIHNvdXJjZSksIGtpbmQ6IFwiUHJpbnRTdGF0ZW1lbnRcIiwgbG9jYXRpb259XG59XG5cbi8qKlxuICogUGFyc2VzIFJ1YnkgaW50byB0aGUgc2hhcmVkIHNlbWFudGljIG1vZHVsZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSBpbnB1dCAtIFBhcnNlciBpbnB1dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5maWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5zb3VyY2UgLSBTb3VyY2UgdGV4dC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gU2VtYW50aWMgbW9kdWxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VSdWJ5KHtmaWxlbmFtZSwgc291cmNlfSkge1xuICBjb25zdCByZXN1bHQgPSBwYXJzZVByaXNtKHNvdXJjZSwge2ZpbGVwYXRoOiBmaWxlbmFtZX0pXG5cbiAgaWYgKHJlc3VsdC5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGVycm9yID0gcmVzdWx0LmVycm9yc1swXVxuICAgIGNvbnN0IGxvY2F0aW9uID0gbG9jYXRpb25Gcm9tT2Zmc2V0cyhmaWxlbmFtZSwgc291cmNlLCBlcnJvci5sb2NhdGlvbi5zdGFydE9mZnNldCwgZXJyb3IubG9jYXRpb24uc3RhcnRPZmZzZXQgKyBlcnJvci5sb2NhdGlvbi5sZW5ndGgpXG5cbiAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtjb2RlOiBcIlBBUlNFX0VSUk9SXCIsIGxhbmd1YWdlOiBcInJ1YnlcIiwgbG9jYXRpb24sIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2V9KVxuICB9XG5cbiAgaWYgKCEocmVzdWx0LnZhbHVlIGluc3RhbmNlb2YgUHJvZ3JhbU5vZGUpKSB0aHJvdyBuZXcgRXJyb3IoXCJQcmlzbSByZXR1cm5lZCBhIG5vbi1wcm9ncmFtIHJvb3QuXCIpXG5cbiAgY29uc3QgYm9keSA9IHJlc3VsdC52YWx1ZS5zdGF0ZW1lbnRzLmJvZHlcbiAgY29uc3QgZnVuY3Rpb25zID0gYm9keS5maWx0ZXIoKG5vZGUpID0+IG5vZGUgaW5zdGFuY2VvZiBEZWZOb2RlKVxuICAgIC5tYXAoKG5vZGUpID0+IGNvbnZlcnRGdW5jdGlvbihub2RlLCByZXN1bHQuY29tbWVudHMsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICBjb25zdCBlbnRyeU5vZGVzID0gYm9keS5maWx0ZXIoKG5vZGUpID0+ICEobm9kZSBpbnN0YW5jZW9mIERlZk5vZGUpKVxuICBjb25zdCBsb2NhdGlvbiA9IG1vZHVsZUxvY2F0aW9uKGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKGZ1bmN0aW9ucy5sZW5ndGggPT0gMCkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcIm1vZHVsZSB3aXRob3V0IGEgZnVuY3Rpb25cIiwgbG9jYXRpb24pXG4gIGNvbnN0IGZpcnN0RW50cnkgPSBlbnRyeU5vZGVzWzBdXG4gIGNvbnN0IGVudHJ5TG9jYXRpb24gPSBmaXJzdEVudHJ5ID8gbG9jYXRpb25Gcm9tT2Zmc2V0cyhcbiAgICBmaWxlbmFtZSxcbiAgICBzb3VyY2UsXG4gICAgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0KHNvdXJjZSwgZmlyc3RFbnRyeS5sb2NhdGlvbi5zdGFydE9mZnNldCksXG4gICAgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0KFxuICAgICAgc291cmNlLFxuICAgICAgKGVudHJ5Tm9kZXMuYXQoLTEpPy5sb2NhdGlvbi5zdGFydE9mZnNldCA/PyAwKSArIChlbnRyeU5vZGVzLmF0KC0xKT8ubG9jYXRpb24ubGVuZ3RoID8/IDApXG4gICAgKVxuICApIDogbG9jYXRpb25cbiAgY29uc3QgZW50cnlWaXNpYmxlID0gbmV3IFNldCgpXG4gIGNvbnN0IGVudHJ5QmxvY2sgPSB7XG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQmxvY2tcIiksXG4gICAgbG9jYXRpb246IGVudHJ5TG9jYXRpb24sXG4gICAgc3RhdGVtZW50czogZW50cnlOb2Rlcy5tYXAoKHN0YXRlbWVudCkgPT4gY29udmVydFN0YXRlbWVudChzdGF0ZW1lbnQsIHJlc3VsdC5jb21tZW50cywgZW50cnlWaXNpYmxlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZW50cnlQb2ludDoge1xuICAgICAgYm9keTogZW50cnlCbG9jayxcbiAgICAgIGtpbmQ6IFwiRW50cnlQb2ludFwiLFxuICAgICAgbG9jYXRpb246IGVudHJ5TG9jYXRpb25cbiAgICB9LFxuICAgIGZ1bmN0aW9ucyxcbiAgICBraW5kOiBcIk1vZHVsZVwiLFxuICAgIGxvY2F0aW9uXG4gIH1cbn1cbiJdfQ==