semantifold 0.3.0 → 0.5.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.
- package/README.md +61 -15
- package/build/index.d.ts +52 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +60 -8
- package/build/src/artifact-path.d.ts +23 -1
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +45 -3
- package/build/src/artifacts.d.ts.map +1 -1
- package/build/src/artifacts.js +66 -1
- package/build/src/backends/android.d.ts +49 -0
- package/build/src/backends/android.d.ts.map +1 -0
- package/build/src/backends/android.js +1274 -0
- package/build/src/backends/c-validation.d.ts.map +1 -1
- package/build/src/backends/c-validation.js +7 -3
- package/build/src/backends/cpp-validation.d.ts.map +1 -1
- package/build/src/backends/cpp-validation.js +7 -3
- package/build/src/backends/csharp.js +7 -1
- package/build/src/backends/dart-runtime.d.ts +2 -0
- package/build/src/backends/dart-runtime.d.ts.map +1 -0
- package/build/src/backends/dart-runtime.js +41 -0
- package/build/src/backends/dart.d.ts +20 -0
- package/build/src/backends/dart.d.ts.map +1 -0
- package/build/src/backends/dart.js +321 -0
- package/build/src/backends/effects.d.ts +60 -0
- package/build/src/backends/effects.d.ts.map +1 -0
- package/build/src/backends/effects.js +746 -0
- package/build/src/backends/go.js +18 -4
- package/build/src/backends/identifiers.d.ts +36 -4
- package/build/src/backends/identifiers.d.ts.map +1 -1
- package/build/src/backends/identifiers.js +160 -10
- package/build/src/backends/index.d.ts.map +1 -1
- package/build/src/backends/index.js +27 -4
- package/build/src/backends/ios.d.ts +68 -0
- package/build/src/backends/ios.d.ts.map +1 -0
- package/build/src/backends/ios.js +1503 -0
- package/build/src/backends/java.d.ts.map +1 -1
- package/build/src/backends/java.js +429 -36
- package/build/src/backends/javascript.d.ts +6 -0
- package/build/src/backends/javascript.d.ts.map +1 -1
- package/build/src/backends/javascript.js +380 -24
- package/build/src/backends/kotlin-runtime.d.ts +3 -0
- package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
- package/build/src/backends/kotlin-runtime.js +29 -0
- package/build/src/backends/kotlin.d.ts +33 -0
- package/build/src/backends/kotlin.d.ts.map +1 -0
- package/build/src/backends/kotlin.js +138 -0
- package/build/src/backends/native-validation.d.ts +2 -2
- package/build/src/backends/native-validation.d.ts.map +1 -1
- package/build/src/backends/native-validation.js +2 -2
- package/build/src/backends/ordered-expressions.d.ts.map +1 -1
- package/build/src/backends/ordered-expressions.js +39 -7
- package/build/src/backends/php-stdlib-support.d.ts +19 -0
- package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
- package/build/src/backends/php-stdlib-support.js +227 -0
- package/build/src/backends/php.d.ts.map +1 -1
- package/build/src/backends/php.js +448 -33
- package/build/src/backends/program.d.ts +83 -0
- package/build/src/backends/program.d.ts.map +1 -0
- package/build/src/backends/program.js +1309 -0
- package/build/src/backends/python.js +7 -1
- package/build/src/backends/ruby.d.ts.map +1 -1
- package/build/src/backends/ruby.js +310 -24
- package/build/src/backends/rust-runtime.d.ts +7 -0
- package/build/src/backends/rust-runtime.d.ts.map +1 -0
- package/build/src/backends/rust-runtime.js +32 -0
- package/build/src/backends/rust-validation.d.ts +9 -0
- package/build/src/backends/rust-validation.d.ts.map +1 -0
- package/build/src/backends/rust-validation.js +78 -0
- package/build/src/backends/rust.d.ts +24 -0
- package/build/src/backends/rust.d.ts.map +1 -0
- package/build/src/backends/rust.js +344 -0
- package/build/src/backends/scalars.d.ts +14 -6
- package/build/src/backends/scalars.d.ts.map +1 -1
- package/build/src/backends/scalars.js +167 -17
- package/build/src/backends/shared.d.ts +23 -4
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +2174 -62
- package/build/src/backends/stdlib-support.d.ts +14 -0
- package/build/src/backends/stdlib-support.d.ts.map +1 -0
- package/build/src/backends/stdlib-support.js +237 -0
- package/build/src/backends/swift-runtime.d.ts +3 -0
- package/build/src/backends/swift-runtime.d.ts.map +1 -0
- package/build/src/backends/swift-runtime.js +14 -0
- package/build/src/backends/swift.d.ts +8 -0
- package/build/src/backends/swift.d.ts.map +1 -0
- package/build/src/backends/swift.js +127 -0
- package/build/src/backends/typescript.d.ts.map +1 -1
- package/build/src/backends/typescript.js +344 -24
- package/build/src/backends/wasm.d.ts +43 -0
- package/build/src/backends/wasm.d.ts.map +1 -0
- package/build/src/backends/wasm.js +2164 -0
- package/build/src/backends/writer.d.ts +255 -4
- package/build/src/backends/writer.d.ts.map +1 -1
- package/build/src/backends/writer.js +491 -3
- package/build/src/diagnostic.d.ts +4 -3
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +5 -3
- package/build/src/frontends/c.d.ts.map +1 -1
- package/build/src/frontends/c.js +5 -3
- package/build/src/frontends/cpp.d.ts.map +1 -1
- package/build/src/frontends/cpp.js +5 -3
- package/build/src/frontends/csharp.d.ts.map +1 -1
- package/build/src/frontends/csharp.js +7 -3
- package/build/src/frontends/dart.d.ts +10 -0
- package/build/src/frontends/dart.d.ts.map +1 -0
- package/build/src/frontends/dart.js +913 -0
- package/build/src/frontends/index.d.ts +3 -1
- package/build/src/frontends/index.d.ts.map +1 -1
- package/build/src/frontends/index.js +15 -5
- package/build/src/frontends/java.d.ts +110 -1
- package/build/src/frontends/java.d.ts.map +1 -1
- package/build/src/frontends/java.js +1725 -70
- package/build/src/frontends/javascript-typescript.d.ts +69 -1
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
- package/build/src/frontends/javascript-typescript.js +1825 -93
- package/build/src/frontends/kotlin.d.ts +10 -0
- package/build/src/frontends/kotlin.d.ts.map +1 -0
- package/build/src/frontends/kotlin.js +685 -0
- package/build/src/frontends/php.d.ts +118 -1
- package/build/src/frontends/php.d.ts.map +1 -1
- package/build/src/frontends/php.js +1583 -76
- package/build/src/frontends/program.d.ts +74 -0
- package/build/src/frontends/program.d.ts.map +1 -0
- package/build/src/frontends/program.js +989 -0
- package/build/src/frontends/ruby.d.ts +68 -1
- package/build/src/frontends/ruby.d.ts.map +1 -1
- package/build/src/frontends/ruby.js +1446 -101
- package/build/src/frontends/rust-parser.d.ts +11 -0
- package/build/src/frontends/rust-parser.d.ts.map +1 -0
- package/build/src/frontends/rust-parser.js +15 -0
- package/build/src/frontends/rust.d.ts +14 -0
- package/build/src/frontends/rust.d.ts.map +1 -0
- package/build/src/frontends/rust.js +715 -0
- package/build/src/frontends/scalars.d.ts +10 -0
- package/build/src/frontends/scalars.d.ts.map +1 -1
- package/build/src/frontends/scalars.js +28 -2
- package/build/src/frontends/swift.d.ts +10 -0
- package/build/src/frontends/swift.d.ts.map +1 -0
- package/build/src/frontends/swift.js +860 -0
- package/build/src/frontends/types.d.ts +186 -0
- package/build/src/frontends/types.d.ts.map +1 -0
- package/build/src/frontends/types.js +634 -0
- package/build/src/language-registry.d.ts +46 -4
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +177 -13
- package/build/src/mapping.d.ts +2 -2
- package/build/src/mapping.d.ts.map +1 -1
- package/build/src/mapping.js +31 -10
- package/build/src/semantic/capabilities.d.ts +66 -0
- package/build/src/semantic/capabilities.d.ts.map +1 -0
- package/build/src/semantic/capabilities.js +649 -0
- package/build/src/semantic/effects.d.ts +26 -0
- package/build/src/semantic/effects.d.ts.map +1 -0
- package/build/src/semantic/effects.js +764 -0
- package/build/src/semantic/generics.d.ts +23 -0
- package/build/src/semantic/generics.d.ts.map +1 -0
- package/build/src/semantic/generics.js +61 -0
- package/build/src/semantic/lifetime.d.ts +37 -0
- package/build/src/semantic/lifetime.d.ts.map +1 -0
- package/build/src/semantic/lifetime.js +527 -0
- package/build/src/semantic/provenance.d.ts +9 -2
- package/build/src/semantic/provenance.d.ts.map +1 -1
- package/build/src/semantic/provenance.js +462 -20
- package/build/src/semantic/scalars.d.ts +11 -0
- package/build/src/semantic/scalars.d.ts.map +1 -1
- package/build/src/semantic/scalars.js +16 -1
- package/build/src/semantic/stdlib.d.ts +254 -0
- package/build/src/semantic/stdlib.d.ts.map +1 -0
- package/build/src/semantic/stdlib.js +880 -0
- package/build/src/semantic/types.d.ts +3108 -178
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +730 -15
- package/build/src/semantic/validate.d.ts +85 -5
- package/build/src/semantic/validate.d.ts.map +1 -1
- package/build/src/semantic/validate.js +2576 -98
- package/build/src/stdlib-facades.d.ts +304 -0
- package/build/src/stdlib-facades.d.ts.map +1 -0
- package/build/src/stdlib-facades.js +1167 -0
- package/build/src/stdlib-negotiation.d.ts +69 -0
- package/build/src/stdlib-negotiation.d.ts.map +1 -0
- package/build/src/stdlib-negotiation.js +403 -0
- package/build/src/stdlib-providers.d.ts +72 -0
- package/build/src/stdlib-providers.d.ts.map +1 -0
- package/build/src/stdlib-providers.js +339 -0
- package/build/src/toolchains.d.ts +55 -1
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +15 -4
- package/docs/android.md +79 -0
- package/docs/architecture.md +47 -13
- package/docs/dart.md +60 -0
- package/docs/goals.md +3 -3
- package/docs/ios.md +121 -0
- package/docs/kotlin.md +42 -0
- package/docs/language-support.md +238 -26
- package/docs/multi-file-modules.md +52 -0
- package/docs/parser-qualification.md +121 -8
- package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
- package/docs/rust.md +88 -0
- package/docs/source-maps.md +17 -7
- package/docs/specification.md +5 -0
- package/docs/standard-library-portability.md +39 -8
- package/docs/swift.md +44 -0
- package/docs/testing.md +381 -4
- package/docs/webassembly.md +52 -0
- package/index.js +66 -8
- package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
- package/package.json +5 -2
- package/src/artifact-path.js +47 -2
- package/src/artifacts.js +67 -0
- package/src/backends/android.js +1370 -0
- package/src/backends/c-validation.js +6 -1
- package/src/backends/cpp-validation.js +6 -1
- package/src/backends/csharp.js +3 -0
- package/src/backends/dart-runtime.js +41 -0
- package/src/backends/dart.js +326 -0
- package/src/backends/effects.js +705 -0
- package/src/backends/go.js +14 -2
- package/src/backends/identifiers.js +166 -9
- package/src/backends/index.js +27 -2
- package/src/backends/ios.js +1612 -0
- package/src/backends/java.js +454 -36
- package/src/backends/javascript.js +389 -23
- package/src/backends/kotlin-runtime.js +29 -0
- package/src/backends/kotlin.js +144 -0
- package/src/backends/native-validation.js +1 -1
- package/src/backends/ordered-expressions.js +40 -6
- package/src/backends/php-stdlib-support.js +239 -0
- package/src/backends/php.js +469 -32
- package/src/backends/program.js +1408 -0
- package/src/backends/python.js +3 -0
- package/src/backends/ruby.js +326 -23
- package/src/backends/rust-runtime.js +34 -0
- package/src/backends/rust-validation.js +75 -0
- package/src/backends/rust.js +335 -0
- package/src/backends/scalars.js +141 -16
- package/src/backends/shared.js +2314 -115
- package/src/backends/stdlib-support.js +234 -0
- package/src/backends/swift-runtime.js +14 -0
- package/src/backends/swift.js +132 -0
- package/src/backends/typescript.js +349 -23
- package/src/backends/wasm.js +2208 -0
- package/src/backends/writer.js +545 -2
- package/src/diagnostic.js +4 -2
- package/src/frontends/c.js +4 -2
- package/src/frontends/cpp.js +4 -2
- package/src/frontends/csharp.js +4 -2
- package/src/frontends/dart.js +963 -0
- package/src/frontends/index.js +14 -4
- package/src/frontends/java.js +1977 -69
- package/src/frontends/javascript-typescript.js +2046 -102
- package/src/frontends/kotlin.js +713 -0
- package/src/frontends/php.js +1725 -79
- package/src/frontends/program.js +1062 -0
- package/src/frontends/ruby.js +1624 -98
- package/src/frontends/rust-parser.js +18 -0
- package/src/frontends/rust.js +714 -0
- package/src/frontends/scalars.js +31 -1
- package/src/frontends/swift.js +893 -0
- package/src/frontends/types.js +750 -0
- package/src/language-registry.js +182 -12
- package/src/mapping.js +33 -9
- package/src/semantic/capabilities.js +671 -0
- package/src/semantic/effects.js +737 -0
- package/src/semantic/generics.js +58 -0
- package/src/semantic/lifetime.js +517 -0
- package/src/semantic/provenance.js +412 -19
- package/src/semantic/scalars.js +17 -0
- package/src/semantic/stdlib.js +921 -0
- package/src/semantic/types.js +810 -14
- package/src/semantic/validate.js +2934 -209
- package/src/stdlib-facades.js +1211 -0
- package/src/stdlib-negotiation.js +446 -0
- package/src/stdlib-providers.js +377 -0
- package/src/toolchains.js +16 -3
|
@@ -0,0 +1,913 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import Parser from "tree-sitter";
|
|
3
|
+
import DartLanguage from "tree-sitter-dart-orchard/bindings/node/index.js";
|
|
4
|
+
import { isDartIdentifier } from "../backends/identifiers.js";
|
|
5
|
+
import { dartRuntime } from "../backends/dart-runtime.js";
|
|
6
|
+
import { missingType, SemantifoldDiagnostic, unsupportedSyntax } from "../diagnostic.js";
|
|
7
|
+
import { locationFromOffsets, moduleLocation, utf8ByteOffsetToUtf16Offset } from "../semantic/location.js";
|
|
8
|
+
import { withAdaptedOperation } from "../semantic/operators.js";
|
|
9
|
+
import { withParserRanges } from "../semantic/provenance.js";
|
|
10
|
+
import { hasOnlyUnicodeScalars } from "../semantic/scalars.js";
|
|
11
|
+
import { validateParsedModule } from "../semantic/validate.js";
|
|
12
|
+
import { sourceScalarType } from "./scalars.js";
|
|
13
|
+
const parser = new Parser();
|
|
14
|
+
parser.setLanguage(/** @type {import("tree-sitter").Language} */ ( /** @type {unknown} */(DartLanguage)));
|
|
15
|
+
const binaryOperations = new Map([
|
|
16
|
+
["+", "Add"], ["-", "Subtract"], ["*", "Multiply"], ["==", "Equal"], ["!=", "NotEqual"],
|
|
17
|
+
["<", "LessThan"], ["<=", "LessThanOrEqual"], [">", "GreaterThan"], [">=", "GreaterThanOrEqual"],
|
|
18
|
+
["&&", "And"], ["||", "Or"]
|
|
19
|
+
]);
|
|
20
|
+
/** @type {Map<string, readonly [string, Set<string>]>} */
|
|
21
|
+
const binaryNodeOperators = new Map([
|
|
22
|
+
["additive_expression", ["additive_operator", new Set(["+", "-"])]],
|
|
23
|
+
["multiplicative_expression", ["multiplicative_operator", new Set(["*"])]],
|
|
24
|
+
["equality_expression", ["equality_operator", new Set(["==", "!="])]],
|
|
25
|
+
["relational_expression", ["relational_operator", new Set(["<", "<=", ">", ">="])]],
|
|
26
|
+
["logical_and_expression", ["logical_and_operator", new Set(["&&"])]],
|
|
27
|
+
["logical_or_expression", ["logical_or_operator", new Set(["||"])]]
|
|
28
|
+
]);
|
|
29
|
+
const commentTypes = new Set(["comment", "documentation_comment"]);
|
|
30
|
+
/** @type {Map<string, import("../semantic/operators.js").AdaptedOperation>} */
|
|
31
|
+
const helperOperations = new Map([
|
|
32
|
+
["_semantifoldIntegerAdd", "Add"], ["_semantifoldIntegerSubtract", "Subtract"],
|
|
33
|
+
["_semantifoldIntegerMultiply", "Multiply"], ["_semantifoldIntegerNegate", "Negate"]
|
|
34
|
+
]);
|
|
35
|
+
/**
|
|
36
|
+
* Verifies a binding-reported UTF-16 index through the shared UTF-8 converter.
|
|
37
|
+
* @param {string} source Complete source.
|
|
38
|
+
* @param {number} index Binding index.
|
|
39
|
+
* @returns {number} Verified UTF-16 offset.
|
|
40
|
+
*/
|
|
41
|
+
function bindingIndexToUtf16Offset(source, index) {
|
|
42
|
+
if (!Number.isInteger(index) || index < 0 || index > source.length ||
|
|
43
|
+
index > 0 && index < source.length && /[\uD800-\uDBFF]/u.test(source[index - 1]) && /[\uDC00-\uDFFF]/u.test(source[index])) {
|
|
44
|
+
throw new RangeError("Invalid Tree-sitter source index: " + index);
|
|
45
|
+
}
|
|
46
|
+
return utf8ByteOffsetToUtf16Offset(source, new TextEncoder().encode(source.slice(0, index)).length);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Finds the first unpaired UTF-16 surrogate.
|
|
50
|
+
* @param {string} source Complete source.
|
|
51
|
+
* @returns {number} Invalid offset or -1.
|
|
52
|
+
*/
|
|
53
|
+
function firstLoneSurrogateOffset(source) {
|
|
54
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
55
|
+
const unit = source.charCodeAt(index);
|
|
56
|
+
if (unit >= 0xD800 && unit <= 0xDBFF) {
|
|
57
|
+
const next = source.charCodeAt(index + 1);
|
|
58
|
+
if (next >= 0xDC00 && next <= 0xDFFF)
|
|
59
|
+
index += 1;
|
|
60
|
+
else
|
|
61
|
+
return index;
|
|
62
|
+
}
|
|
63
|
+
else if (unit >= 0xDC00 && unit <= 0xDFFF)
|
|
64
|
+
return index;
|
|
65
|
+
}
|
|
66
|
+
return -1;
|
|
67
|
+
}
|
|
68
|
+
/** Consumes exact qualified Dart CST shapes without retaining parser values. */
|
|
69
|
+
class DartReader {
|
|
70
|
+
/**
|
|
71
|
+
* Creates a reader bound to one exact Dart source unit.
|
|
72
|
+
* @param {string} filename Original filename.
|
|
73
|
+
* @param {string} source Complete source.
|
|
74
|
+
*/
|
|
75
|
+
constructor(filename, source) {
|
|
76
|
+
this.filename = filename;
|
|
77
|
+
this.source = source;
|
|
78
|
+
/** @type {Set<string>} */
|
|
79
|
+
this.functionNames = new Set();
|
|
80
|
+
this.runtime = false;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Builds a semantic source location from one parser node.
|
|
84
|
+
* @param {import("tree-sitter").SyntaxNode} node Parser node.
|
|
85
|
+
* @returns {import("../semantic/types.js").SourceLocation} Exact location.
|
|
86
|
+
*/
|
|
87
|
+
location(node) {
|
|
88
|
+
return locationFromOffsets(this.filename, this.source, bindingIndexToUtf16Offset(this.source, node.startIndex), bindingIndexToUtf16Offset(this.source, node.endIndex));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Rejects one parser node with a located unsupported-syntax diagnostic.
|
|
92
|
+
* @param {import("tree-sitter").SyntaxNode} node Violating node.
|
|
93
|
+
* @param {string} [detail] Profile detail.
|
|
94
|
+
* @returns {never} Always throws.
|
|
95
|
+
*/
|
|
96
|
+
fail(node, detail = node.type) {
|
|
97
|
+
unsupportedSyntax("dart", detail, this.location(node));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Traverses every named, anonymous, extra, field, and recovery edge.
|
|
101
|
+
* @param {import("tree-sitter").SyntaxNode} root Complete parser root.
|
|
102
|
+
* @returns {void}
|
|
103
|
+
*/
|
|
104
|
+
validateTree(root) {
|
|
105
|
+
const pending = [{ depth: 0, node: root, visited: false }];
|
|
106
|
+
while (pending.length > 0) {
|
|
107
|
+
const current = pending.pop();
|
|
108
|
+
if (!current)
|
|
109
|
+
throw new Error("Dart traversal lost a pending parser node.");
|
|
110
|
+
const { depth, node, visited } = current;
|
|
111
|
+
if (depth > 512)
|
|
112
|
+
this.fail(node, "CST exceeds the 512-level traversal limit");
|
|
113
|
+
if (!visited) {
|
|
114
|
+
pending.push({ depth, node, visited: true });
|
|
115
|
+
for (let index = node.childCount - 1; index >= 0; index -= 1) {
|
|
116
|
+
const child = node.child(index);
|
|
117
|
+
if (!child)
|
|
118
|
+
throw new Error(`Tree-sitter omitted child ${index} of ${node.type}.`);
|
|
119
|
+
node.fieldNameForChild(index);
|
|
120
|
+
pending.push({ depth: depth + 1, node: child, visited: false });
|
|
121
|
+
}
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (node.hasError || node.isError || node.isMissing) {
|
|
125
|
+
throw new SemantifoldDiagnostic({
|
|
126
|
+
code: "PARSE_ERROR",
|
|
127
|
+
language: "dart",
|
|
128
|
+
location: this.location(node),
|
|
129
|
+
message: `Tree-sitter exposed recovery at '${node.type}'.`
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
if (["annotation", "import_or_export", "library_name", "part_header", "part_of_header"].includes(node.type)) {
|
|
133
|
+
this.fail(node, node.type);
|
|
134
|
+
}
|
|
135
|
+
if (commentTypes.has(node.type) && (/(?:@dart\s*=|dartfmt|ignore(?:_for_file)?\s*:|language[-_ ]version)/iu.test(node.text) ||
|
|
136
|
+
/^\/\/ dart format (?:off|on)[\t ]*$/u.test(node.text))) {
|
|
137
|
+
this.fail(node, "directive-bearing comment");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Omits only ordinary comments already covered by exhaustive traversal.
|
|
143
|
+
* @param {import("tree-sitter").SyntaxNode} node Parent node.
|
|
144
|
+
* @returns {import("tree-sitter").SyntaxNode[]} Structural children.
|
|
145
|
+
*/
|
|
146
|
+
parts(node) {
|
|
147
|
+
return node.children.filter((child) => !commentTypes.has(child.type));
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Verifies an exact structural child sequence.
|
|
151
|
+
* @param {import("tree-sitter").SyntaxNode} node Shape owner.
|
|
152
|
+
* @param {(import("tree-sitter").SyntaxNode | string)[]} expected Exact child sequence.
|
|
153
|
+
* @returns {void}
|
|
154
|
+
*/
|
|
155
|
+
shape(node, expected) {
|
|
156
|
+
const actual = this.parts(node);
|
|
157
|
+
if (actual.length != expected.length)
|
|
158
|
+
this.fail(actual[Math.min(actual.length, expected.length)] ?? node, `${node.type} child shape`);
|
|
159
|
+
for (let index = 0; index < expected.length; index += 1) {
|
|
160
|
+
const wanted = expected[index];
|
|
161
|
+
const child = actual[index];
|
|
162
|
+
const matches = typeof wanted == "string" ? child.text == wanted : child.id == wanted.id;
|
|
163
|
+
if (!matches)
|
|
164
|
+
this.fail(child, `${node.type} child shape`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Consumes an Orchard operator wrapper whether its token is aliased into the wrapper or exposed anonymously.
|
|
169
|
+
* @param {import("tree-sitter").SyntaxNode} node Operator node.
|
|
170
|
+
* @returns {void}
|
|
171
|
+
*/
|
|
172
|
+
operatorShape(node) {
|
|
173
|
+
const parts = this.parts(node);
|
|
174
|
+
if (parts.length > 1 || parts.length == 1 && (parts[0].isNamed || parts[0].text != node.text)) {
|
|
175
|
+
this.fail(node, `${node.type} child shape`);
|
|
176
|
+
}
|
|
177
|
+
this.shape(node, parts.length == 0 ? [] : [node.text]);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Returns exactly one parser child carrying a requested field name.
|
|
181
|
+
* @param {import("tree-sitter").SyntaxNode} node Field owner.
|
|
182
|
+
* @param {string} name Field name.
|
|
183
|
+
* @returns {import("tree-sitter").SyntaxNode} Sole field node.
|
|
184
|
+
*/
|
|
185
|
+
field(node, name) {
|
|
186
|
+
const matches = [];
|
|
187
|
+
for (let index = 0; index < node.childCount; index += 1) {
|
|
188
|
+
const child = node.child(index);
|
|
189
|
+
if (!child)
|
|
190
|
+
throw new Error(`Tree-sitter omitted child ${index} of ${node.type}.`);
|
|
191
|
+
if (node.fieldNameForChild(index) == name)
|
|
192
|
+
matches.push(child);
|
|
193
|
+
}
|
|
194
|
+
if (matches.length != 1)
|
|
195
|
+
this.fail(node, `expected one '${name}' field`);
|
|
196
|
+
return matches[0];
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Validates and returns a source identifier.
|
|
200
|
+
* @param {import("tree-sitter").SyntaxNode} node Identifier token.
|
|
201
|
+
* @param {boolean} [allowMain] Whether fixed main is expected.
|
|
202
|
+
* @param {boolean} [allowPrint] Whether fixed print is expected.
|
|
203
|
+
* @returns {string} Accepted name.
|
|
204
|
+
*/
|
|
205
|
+
identifier(node, allowMain = false, allowPrint = false) {
|
|
206
|
+
const name = node.text;
|
|
207
|
+
if (node.type != "identifier" || !(allowMain && name == "main") && !(allowPrint && name == "print") &&
|
|
208
|
+
!isDartIdentifier(name))
|
|
209
|
+
this.fail(node, "reserved or unsupported identifier");
|
|
210
|
+
return name;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Converts one explicitly named scalar type.
|
|
214
|
+
* @param {import("tree-sitter").SyntaxNode} node Type node.
|
|
215
|
+
* @returns {import("../semantic/types.js").TypeReference} Scalar type.
|
|
216
|
+
*/
|
|
217
|
+
scalarType(node) {
|
|
218
|
+
if (node.type != "type_identifier" || this.parts(node).length != 0)
|
|
219
|
+
this.fail(node, "scalar type shape");
|
|
220
|
+
const type = sourceScalarType("dart", node.text, this.location(node));
|
|
221
|
+
if (!type)
|
|
222
|
+
this.fail(node, `unsupported scalar type '${node.text}'`);
|
|
223
|
+
return type;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Converts one explicit scalar or void result type.
|
|
227
|
+
* @param {import("tree-sitter").SyntaxNode} node Return type node.
|
|
228
|
+
* @returns {import("../semantic/types.js").SemanticFunctionReturnType} Function return type.
|
|
229
|
+
*/
|
|
230
|
+
returnType(node) {
|
|
231
|
+
if (node.type == "void_type") {
|
|
232
|
+
const parts = this.parts(node);
|
|
233
|
+
if (node.text != "void" || parts.length > 1 || parts.length == 1 && parts[0].text != "void") {
|
|
234
|
+
this.fail(node, "void type shape");
|
|
235
|
+
}
|
|
236
|
+
this.shape(node, parts);
|
|
237
|
+
const type = { kind: /** @type {const} */ ("TypeReference"), name: /** @type {const} */ ("void") };
|
|
238
|
+
return withParserRanges(type, { type: this.location(node) });
|
|
239
|
+
}
|
|
240
|
+
return this.scalarType(node);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Decodes one ordinary noninterpolated, non-raw, single-line Dart string.
|
|
244
|
+
* @param {import("tree-sitter").SyntaxNode} node String node.
|
|
245
|
+
* @returns {string} Decoded Unicode scalar value.
|
|
246
|
+
*/
|
|
247
|
+
string(node) {
|
|
248
|
+
const parts = this.parts(node);
|
|
249
|
+
const delimiter = node.text[0];
|
|
250
|
+
if (node.type != "string_literal" || !["\"", "'"].includes(delimiter) || node.text.startsWith(delimiter.repeat(3)) ||
|
|
251
|
+
node.text.at(-1) != delimiter || parts.length < 2 || parts[0].text != delimiter || parts.at(-1)?.text != delimiter ||
|
|
252
|
+
parts.slice(1, -1).some(({ type }) => type != "escape_sequence")) {
|
|
253
|
+
this.fail(node, "ordinary noninterpolated string literal required");
|
|
254
|
+
}
|
|
255
|
+
this.shape(node, parts);
|
|
256
|
+
const source = node.text.slice(1, -1);
|
|
257
|
+
const simpleEscapes = new Map([
|
|
258
|
+
["b", "\b"], ["f", "\f"], ["n", "\n"], ["r", "\r"], ["t", "\t"], ["v", "\v"],
|
|
259
|
+
["$", "$"], ["'", "'"], ['"', '"'], ["\\", "\\"]
|
|
260
|
+
]);
|
|
261
|
+
let value = "";
|
|
262
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
263
|
+
const character = source[index];
|
|
264
|
+
if (character != "\\") {
|
|
265
|
+
if (character == "\n" || character == "\r" || character == delimiter || character == "$") {
|
|
266
|
+
this.fail(node, "invalid or interpolated string content");
|
|
267
|
+
}
|
|
268
|
+
value += character;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
const escaped = source[++index];
|
|
272
|
+
if (simpleEscapes.has(escaped))
|
|
273
|
+
value += simpleEscapes.get(escaped);
|
|
274
|
+
else if (escaped == "x") {
|
|
275
|
+
const hexadecimal = source.slice(index + 1, index + 3);
|
|
276
|
+
if (!/^[0-9A-Fa-f]{2}$/u.test(hexadecimal))
|
|
277
|
+
this.fail(node, "unsupported string escape");
|
|
278
|
+
value += String.fromCodePoint(Number.parseInt(hexadecimal, 16));
|
|
279
|
+
index += 2;
|
|
280
|
+
}
|
|
281
|
+
else if (escaped == "u") {
|
|
282
|
+
if (source[index + 1] == "{") {
|
|
283
|
+
const closing = source.indexOf("}", index + 2);
|
|
284
|
+
const hexadecimal = closing < 0 ? "" : source.slice(index + 2, closing);
|
|
285
|
+
const codePoint = /^[0-9A-Fa-f]{1,6}$/u.test(hexadecimal) ? Number.parseInt(hexadecimal, 16) : -1;
|
|
286
|
+
if (codePoint < 0 || codePoint > 0x10FFFF)
|
|
287
|
+
this.fail(node, "unsupported string escape");
|
|
288
|
+
value += String.fromCodePoint(codePoint);
|
|
289
|
+
index = closing;
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
const hexadecimal = source.slice(index + 1, index + 5);
|
|
293
|
+
if (!/^[0-9A-Fa-f]{4}$/u.test(hexadecimal))
|
|
294
|
+
this.fail(node, "unsupported string escape");
|
|
295
|
+
value += String.fromCharCode(Number.parseInt(hexadecimal, 16));
|
|
296
|
+
index += 4;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else
|
|
300
|
+
this.fail(node, "unsupported string escape");
|
|
301
|
+
}
|
|
302
|
+
if (!hasOnlyUnicodeScalars(value))
|
|
303
|
+
this.fail(node, "invalid Unicode string literal");
|
|
304
|
+
return value;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Extracts exact required positional arguments.
|
|
308
|
+
* @param {import("tree-sitter").SyntaxNode} part Call argument part.
|
|
309
|
+
* @returns {import("tree-sitter").SyntaxNode[][]} Argument expression edges.
|
|
310
|
+
*/
|
|
311
|
+
arguments(part) {
|
|
312
|
+
const partChildren = this.parts(part);
|
|
313
|
+
if (part.type != "argument_part" || partChildren.length != 1 || partChildren[0].type != "arguments") {
|
|
314
|
+
this.fail(part, "call argument part shape");
|
|
315
|
+
}
|
|
316
|
+
this.shape(part, [partChildren[0]]);
|
|
317
|
+
const list = partChildren[0];
|
|
318
|
+
const listParts = this.parts(list);
|
|
319
|
+
if (listParts.length < 2 || listParts[0].text != "(" || listParts.at(-1)?.text != ")") {
|
|
320
|
+
this.fail(list, "call argument list shape");
|
|
321
|
+
}
|
|
322
|
+
const interior = listParts.slice(1, -1);
|
|
323
|
+
const hasGeneratedTrailingComma = this.runtime && interior.at(-1)?.text == ",";
|
|
324
|
+
const argumentParts = hasGeneratedTrailingComma ? interior.slice(0, -1) : interior;
|
|
325
|
+
const arguments_ = argumentParts.filter((_child, index) => index % 2 == 0);
|
|
326
|
+
this.shape(list, ["(", ...arguments_.flatMap((argument, index) => index ? [",", argument] : [argument]),
|
|
327
|
+
...(hasGeneratedTrailingComma ? [","] : []), ")"]);
|
|
328
|
+
return arguments_.map((argument) => {
|
|
329
|
+
if (argument.type != "argument")
|
|
330
|
+
this.fail(argument, "required positional argument");
|
|
331
|
+
const expressionParts = this.parts(argument);
|
|
332
|
+
if (expressionParts.length == 0)
|
|
333
|
+
this.fail(argument, "empty argument");
|
|
334
|
+
return expressionParts;
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Converts one direct method-invocation node whose function is a plain identifier.
|
|
339
|
+
* @param {import("tree-sitter").SyntaxNode[]} nodes Exact one-node call.
|
|
340
|
+
* @param {import("tree-sitter").SyntaxNode} owner Expression owner.
|
|
341
|
+
* @param {boolean} [allowPrint] Whether this is the print scaffold.
|
|
342
|
+
* @returns {import("../semantic/types.js").Expression} Semantic call or private generated operation.
|
|
343
|
+
*/
|
|
344
|
+
call(nodes, owner, allowPrint = false) {
|
|
345
|
+
if (nodes.length != 1 || nodes[0].type != "method_invocation") {
|
|
346
|
+
this.fail(nodes[0] ?? owner, "direct call shape");
|
|
347
|
+
}
|
|
348
|
+
const invocation = nodes[0];
|
|
349
|
+
const parts = this.parts(invocation);
|
|
350
|
+
const functionNode = this.field(invocation, "function");
|
|
351
|
+
const argumentPart = this.field(invocation, "arguments");
|
|
352
|
+
if (parts.length != 2 || parts[0].id != functionNode.id || functionNode.type != "identifier" ||
|
|
353
|
+
parts[1].id != argumentPart.id || argumentPart.type != "argument_part")
|
|
354
|
+
this.fail(invocation, "direct call shape");
|
|
355
|
+
this.shape(invocation, [functionNode, argumentPart]);
|
|
356
|
+
const name = functionNode.text;
|
|
357
|
+
const helper = this.runtime ? helperOperations.get(name) : undefined;
|
|
358
|
+
const location = this.location(invocation);
|
|
359
|
+
const argumentNodes = this.arguments(argumentPart);
|
|
360
|
+
if (this.runtime && name == "_semantifoldBoolean") {
|
|
361
|
+
if (argumentNodes.length != 1)
|
|
362
|
+
this.fail(argumentPart, "Dart Boolean literal helper shape");
|
|
363
|
+
const literal = this.expression(argumentNodes[0], owner);
|
|
364
|
+
if (literal.kind != "BooleanLiteral")
|
|
365
|
+
this.fail(argumentPart, "Dart Boolean literal helper shape");
|
|
366
|
+
return literal;
|
|
367
|
+
}
|
|
368
|
+
if (helper) {
|
|
369
|
+
const count = helper == "Negate" ? 1 : 2;
|
|
370
|
+
if (argumentNodes.length != count)
|
|
371
|
+
this.fail(argumentPart, "Dart checked-integer helper shape");
|
|
372
|
+
if (helper == "Negate") {
|
|
373
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(withAdaptedOperation(withParserRanges({
|
|
374
|
+
kind: /** @type {const} */ ("UnaryExpression"), location,
|
|
375
|
+
operand: this.expression(argumentNodes[0], owner)
|
|
376
|
+
}, { operator: this.location(functionNode) }), helper)));
|
|
377
|
+
}
|
|
378
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(withAdaptedOperation(withParserRanges({
|
|
379
|
+
kind: /** @type {const} */ ("BinaryExpression"), left: this.expression(argumentNodes[0], owner), location,
|
|
380
|
+
right: this.expression(argumentNodes[1], owner)
|
|
381
|
+
}, { operator: this.location(functionNode) }), helper)));
|
|
382
|
+
}
|
|
383
|
+
this.identifier(functionNode, false, allowPrint);
|
|
384
|
+
return withParserRanges({
|
|
385
|
+
arguments: argumentNodes.map((argument) => this.expression(argument, owner)),
|
|
386
|
+
callee: name,
|
|
387
|
+
kind: /** @type {const} */ ("CallExpression"),
|
|
388
|
+
location
|
|
389
|
+
}, { callee: this.location(functionNode) });
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Recursively compares one source support subtree with the canonical runtime CST.
|
|
393
|
+
* @param {import("tree-sitter").SyntaxNode} actual Source node.
|
|
394
|
+
* @param {import("tree-sitter").SyntaxNode} expected Canonical node.
|
|
395
|
+
* @returns {void}
|
|
396
|
+
*/
|
|
397
|
+
compareTree(actual, expected) {
|
|
398
|
+
if (actual.type != expected.type || actual.isNamed != expected.isNamed || actual.isExtra != expected.isExtra ||
|
|
399
|
+
actual.childCount != expected.childCount)
|
|
400
|
+
this.fail(actual, "modified Dart support node");
|
|
401
|
+
if (actual.childCount == 0 && actual.text != expected.text)
|
|
402
|
+
this.fail(actual, "modified Dart support token");
|
|
403
|
+
for (let index = 0; index < actual.childCount; index += 1) {
|
|
404
|
+
const left = actual.child(index);
|
|
405
|
+
const right = expected.child(index);
|
|
406
|
+
if (!left || !right || actual.fieldNameForChild(index) != expected.fieldNameForChild(index)) {
|
|
407
|
+
this.fail(left ?? actual, "modified Dart support field");
|
|
408
|
+
}
|
|
409
|
+
this.compareTree(left, right);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Converts an expression represented by one or more adjacent Dart CST nodes.
|
|
414
|
+
* @param {import("tree-sitter").SyntaxNode[]} nodes Expression nodes.
|
|
415
|
+
* @param {import("tree-sitter").SyntaxNode} owner Owning node.
|
|
416
|
+
* @returns {import("../semantic/types.js").Expression} Semantic expression.
|
|
417
|
+
*/
|
|
418
|
+
expression(nodes, owner) {
|
|
419
|
+
if (nodes.length == 1 && nodes[0].type == "method_invocation")
|
|
420
|
+
return this.call(nodes, owner);
|
|
421
|
+
if (nodes.length != 1)
|
|
422
|
+
return this.fail(nodes[0] ?? owner, "scalar expression shape");
|
|
423
|
+
const node = nodes[0];
|
|
424
|
+
const location = this.location(node);
|
|
425
|
+
if (node.type == "identifier") {
|
|
426
|
+
const name = this.identifier(node);
|
|
427
|
+
if (this.functionNames.has(name))
|
|
428
|
+
this.fail(node, "function tear-off");
|
|
429
|
+
return withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location, name }, { name: location });
|
|
430
|
+
}
|
|
431
|
+
if (node.type == "decimal_integer_literal") {
|
|
432
|
+
if (this.parts(node).length != 0 || !/^(?:0|[1-9][0-9]*)$/u.test(node.text))
|
|
433
|
+
this.fail(node, "noncanonical integer literal");
|
|
434
|
+
const value = Number(BigInt(node.text));
|
|
435
|
+
if (!Number.isSafeInteger(value))
|
|
436
|
+
this.fail(node, "non-safe integer literal");
|
|
437
|
+
return withParserRanges({ kind: /** @type {const} */ ("IntegerLiteral"), location, value }, { literal: location });
|
|
438
|
+
}
|
|
439
|
+
if (node.type == "true" || node.type == "false") {
|
|
440
|
+
this.shape(node, [node.type]);
|
|
441
|
+
return withParserRanges({ kind: /** @type {const} */ ("BooleanLiteral"), location, value: node.type == "true" }, { literal: location });
|
|
442
|
+
}
|
|
443
|
+
if (node.type == "string_literal") {
|
|
444
|
+
return withParserRanges({ kind: /** @type {const} */ ("StringLiteral"), location, value: this.string(node) }, { literal: location });
|
|
445
|
+
}
|
|
446
|
+
if (node.type == "parenthesized_expression") {
|
|
447
|
+
const parts = this.parts(node);
|
|
448
|
+
if (parts.length < 3 || parts[0].text != "(" || parts.at(-1)?.text != ")")
|
|
449
|
+
this.fail(node, "parenthesized expression shape");
|
|
450
|
+
this.shape(node, ["(", ...parts.slice(1, -1), ")"]);
|
|
451
|
+
return this.expression(parts.slice(1, -1), node);
|
|
452
|
+
}
|
|
453
|
+
if (node.type == "unary_expression") {
|
|
454
|
+
const parts = this.parts(node);
|
|
455
|
+
const operator = parts[0];
|
|
456
|
+
if (parts.length < 2 || operator.type != "prefix_operator" || !["-", "!"].includes(operator.text)) {
|
|
457
|
+
this.fail(node, "unary operator");
|
|
458
|
+
}
|
|
459
|
+
const operatorParts = this.parts(operator);
|
|
460
|
+
if (operatorParts.length != 1 || operatorParts[0].text != operator.text ||
|
|
461
|
+
!["minus_operator", "negation_operator"].includes(operatorParts[0].type))
|
|
462
|
+
this.fail(operator, "unary operator shape");
|
|
463
|
+
this.operatorShape(operatorParts[0]);
|
|
464
|
+
this.shape(node, [operator, ...parts.slice(1)]);
|
|
465
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(withAdaptedOperation(withParserRanges({
|
|
466
|
+
kind: /** @type {const} */ ("UnaryExpression"),
|
|
467
|
+
location,
|
|
468
|
+
operand: this.expression(parts.slice(1), node)
|
|
469
|
+
}, { operator: this.location(operator) }), operator.text == "-" ? "Negate" : "Not")));
|
|
470
|
+
}
|
|
471
|
+
if (binaryNodeOperators.has(node.type))
|
|
472
|
+
return this.binary(node);
|
|
473
|
+
return this.fail(node);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Converts a bounded binary expression tree.
|
|
477
|
+
* @param {import("tree-sitter").SyntaxNode} node Binary expression node.
|
|
478
|
+
* @returns {import("../semantic/types.js").Expression} Semantic binary expression.
|
|
479
|
+
*/
|
|
480
|
+
binary(node) {
|
|
481
|
+
/** @type {import("tree-sitter").SyntaxNode[][]} */
|
|
482
|
+
const operands = [];
|
|
483
|
+
/** @type {import("tree-sitter").SyntaxNode[]} */
|
|
484
|
+
const operators = [];
|
|
485
|
+
let current = node;
|
|
486
|
+
while (true) {
|
|
487
|
+
const parts = this.parts(current);
|
|
488
|
+
const declaration = binaryNodeOperators.get(current.type);
|
|
489
|
+
const operatorType = declaration?.[0];
|
|
490
|
+
const accepted = declaration?.[1];
|
|
491
|
+
const operatorIndexes = parts.flatMap((part, index) => part.type == operatorType ? [index] : []);
|
|
492
|
+
if (operatorIndexes.length != 1)
|
|
493
|
+
this.fail(current, `${current.type} child shape`);
|
|
494
|
+
const operatorIndex = operatorIndexes[0];
|
|
495
|
+
const operator = parts[operatorIndex];
|
|
496
|
+
if (operatorIndex == 0 || operatorIndex == parts.length - 1 || !accepted?.has(operator.text) ||
|
|
497
|
+
!binaryOperations.has(operator.text))
|
|
498
|
+
this.fail(operator, "unsupported binary operator");
|
|
499
|
+
this.operatorShape(operator);
|
|
500
|
+
this.shape(current, parts);
|
|
501
|
+
operands.push(parts.slice(0, operatorIndex));
|
|
502
|
+
operators.push(operator);
|
|
503
|
+
const right = parts.slice(operatorIndex + 1);
|
|
504
|
+
if (right.length == 1 && right[0].type == node.type)
|
|
505
|
+
current = right[0];
|
|
506
|
+
else {
|
|
507
|
+
operands.push(right);
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
let expression = this.expression(operands[0], node);
|
|
512
|
+
for (let index = 0; index < operators.length; index += 1) {
|
|
513
|
+
const operator = operators[index];
|
|
514
|
+
const operation = binaryOperations.get(operator.text);
|
|
515
|
+
const right = this.expression(operands[index + 1], node);
|
|
516
|
+
const first = operands[0][0];
|
|
517
|
+
const last = operands[index + 1].at(-1);
|
|
518
|
+
const location = first && last
|
|
519
|
+
? locationFromOffsets(this.filename, this.source, bindingIndexToUtf16Offset(this.source, first.startIndex), bindingIndexToUtf16Offset(this.source, last.endIndex))
|
|
520
|
+
: this.location(node);
|
|
521
|
+
expression = /** @type {import("../semantic/types.js").Expression} */ (withAdaptedOperation(withParserRanges({
|
|
522
|
+
kind: /** @type {const} */ ("BinaryExpression"), left: expression, location, right
|
|
523
|
+
}, { operator: this.location(operator) }), /** @type {import("../semantic/operators.js").AdaptedOperation} */ (operation)));
|
|
524
|
+
}
|
|
525
|
+
return expression;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Converts one explicitly typed initialized local declaration.
|
|
529
|
+
* @param {import("tree-sitter").SyntaxNode} node Local declaration.
|
|
530
|
+
* @returns {import("../semantic/types.js").LocalDeclaration} Semantic local.
|
|
531
|
+
*/
|
|
532
|
+
local(node) {
|
|
533
|
+
const declarationParts = this.parts(node);
|
|
534
|
+
if (node.type != "local_variable_declaration" || declarationParts.length != 2 ||
|
|
535
|
+
declarationParts[0].type != "initialized_variable_definition" || declarationParts[1].text != ";") {
|
|
536
|
+
this.fail(node, "local declaration shape");
|
|
537
|
+
}
|
|
538
|
+
this.shape(node, [declarationParts[0], ";"]);
|
|
539
|
+
const definition = declarationParts[0];
|
|
540
|
+
const parts = this.parts(definition);
|
|
541
|
+
if (parts[0]?.type == "inferred_type" || parts[0]?.type == "final_builtin" && parts[1]?.type == "identifier") {
|
|
542
|
+
return missingType("dart", "Local", this.location(definition));
|
|
543
|
+
}
|
|
544
|
+
const immutable = parts[0]?.type == "final_builtin";
|
|
545
|
+
const typeIndex = immutable ? 1 : 0;
|
|
546
|
+
const typeNode = parts[typeIndex];
|
|
547
|
+
const nameNode = parts[typeIndex + 1];
|
|
548
|
+
const equals = parts[typeIndex + 2];
|
|
549
|
+
const expressionParts = parts.slice(typeIndex + 3);
|
|
550
|
+
if (parts.length < typeIndex + 4 || typeNode?.type != "type_identifier" || nameNode?.type != "identifier" ||
|
|
551
|
+
equals?.text != "=" || expressionParts.length == 0 || immutable && parts[0].text != "final") {
|
|
552
|
+
this.fail(parts[0] ?? definition, "explicitly typed initialized local required");
|
|
553
|
+
}
|
|
554
|
+
this.shape(definition, [...(immutable ? [parts[0]] : []), typeNode, nameNode, "=", ...expressionParts]);
|
|
555
|
+
if (this.field(definition, "name").id != nameNode.id)
|
|
556
|
+
this.fail(nameNode, "local name field");
|
|
557
|
+
const name = this.identifier(nameNode);
|
|
558
|
+
return withParserRanges({
|
|
559
|
+
initializer: this.expression(expressionParts, definition),
|
|
560
|
+
kind: /** @type {const} */ ("LocalDeclaration"),
|
|
561
|
+
location: this.location(node),
|
|
562
|
+
mutable: !immutable,
|
|
563
|
+
name,
|
|
564
|
+
type: this.scalarType(typeNode)
|
|
565
|
+
}, { name: this.location(nameNode), operator: this.location(equals) });
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Converts one simple identifier assignment.
|
|
569
|
+
* @param {import("tree-sitter").SyntaxNode} node Assignment expression.
|
|
570
|
+
* @returns {import("../semantic/types.js").AssignmentStatement} Semantic assignment.
|
|
571
|
+
*/
|
|
572
|
+
assignment(node) {
|
|
573
|
+
const parts = this.parts(node);
|
|
574
|
+
const target = parts[0];
|
|
575
|
+
const operator = parts[1];
|
|
576
|
+
if (node.type != "assignment_expression" || parts.length < 3 || target?.type != "assignable_expression" ||
|
|
577
|
+
operator?.type != "assignment_operator" || operator.text != "=")
|
|
578
|
+
this.fail(node, "simple assignment shape");
|
|
579
|
+
const targetParts = this.parts(target);
|
|
580
|
+
if (targetParts.length != 1 || targetParts[0].type != "identifier")
|
|
581
|
+
this.fail(target, "simple assignment target");
|
|
582
|
+
this.shape(target, [targetParts[0]]);
|
|
583
|
+
this.operatorShape(operator);
|
|
584
|
+
this.shape(node, [target, "=", ...parts.slice(2)]);
|
|
585
|
+
const name = this.identifier(targetParts[0]);
|
|
586
|
+
const targetLocation = this.location(targetParts[0]);
|
|
587
|
+
return withParserRanges({
|
|
588
|
+
expression: this.expression(parts.slice(2), node),
|
|
589
|
+
kind: /** @type {const} */ ("AssignmentStatement"),
|
|
590
|
+
location: this.location(node),
|
|
591
|
+
target: withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location: targetLocation, name }, { name: targetLocation })
|
|
592
|
+
}, { operator: this.location(operator) });
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Converts one supported Dart statement.
|
|
596
|
+
* @param {import("tree-sitter").SyntaxNode} node Source statement.
|
|
597
|
+
* @returns {import("../semantic/types.js").Statement} Semantic statement.
|
|
598
|
+
*/
|
|
599
|
+
statement(node) {
|
|
600
|
+
if (node.type == "local_variable_declaration")
|
|
601
|
+
return this.local(node);
|
|
602
|
+
if (node.type == "if_statement")
|
|
603
|
+
return this.conditional(node);
|
|
604
|
+
if (node.type == "return_statement") {
|
|
605
|
+
const parts = this.parts(node);
|
|
606
|
+
if (parts.length < 2 || parts[0].text != "return" || parts.at(-1)?.text != ";")
|
|
607
|
+
this.fail(node, "return statement shape");
|
|
608
|
+
this.shape(node, ["return", ...parts.slice(1, -1), ";"]);
|
|
609
|
+
const expressionParts = parts.slice(1, -1);
|
|
610
|
+
return {
|
|
611
|
+
...(expressionParts.length > 0 ? { expression: this.expression(expressionParts, node) } : {}),
|
|
612
|
+
kind: /** @type {const} */ ("ReturnStatement"),
|
|
613
|
+
location: this.location(node)
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
if (node.type == "expression_statement") {
|
|
617
|
+
const parts = this.parts(node);
|
|
618
|
+
if (parts.length < 2 || parts.at(-1)?.text != ";")
|
|
619
|
+
this.fail(node, "expression statement shape");
|
|
620
|
+
this.shape(node, [...parts.slice(0, -1), ";"]);
|
|
621
|
+
if (parts.length == 2 && parts[0].type == "assignment_expression")
|
|
622
|
+
return this.assignment(parts[0]);
|
|
623
|
+
const callParts = parts.slice(0, -1);
|
|
624
|
+
const callChildren = callParts.length == 1 && callParts[0].type == "method_invocation"
|
|
625
|
+
? this.parts(callParts[0]) : [];
|
|
626
|
+
const print = callChildren[0]?.type == "identifier" && callChildren[0].text == "print";
|
|
627
|
+
const expression = this.call(callParts, node, print);
|
|
628
|
+
if (print) {
|
|
629
|
+
if (expression.kind != "CallExpression" || expression.arguments.length != 1) {
|
|
630
|
+
this.fail(callParts[0], "print argument count");
|
|
631
|
+
}
|
|
632
|
+
return { expression: expression.arguments[0], kind: /** @type {const} */ ("PrintStatement"), location: this.location(node) };
|
|
633
|
+
}
|
|
634
|
+
if (expression.kind != "CallExpression")
|
|
635
|
+
this.fail(callParts[0], "generated helper expression statement");
|
|
636
|
+
return { expression, kind: /** @type {const} */ ("ExpressionStatement"), location: this.location(node) };
|
|
637
|
+
}
|
|
638
|
+
return this.fail(node);
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Consumes one compiler-owned read that prevents Dart from rejecting an otherwise unread local.
|
|
642
|
+
* @param {import("tree-sitter").SyntaxNode} node Candidate source statement.
|
|
643
|
+
* @param {import("../semantic/types.js").Statement | undefined} previous Previous semantic statement.
|
|
644
|
+
* @returns {boolean} Whether the exact authenticated support statement was consumed.
|
|
645
|
+
*/
|
|
646
|
+
generatedLocalUse(node, previous) {
|
|
647
|
+
if (!this.runtime || previous?.kind != "LocalDeclaration" || node.type != "expression_statement")
|
|
648
|
+
return false;
|
|
649
|
+
const statementParts = this.parts(node);
|
|
650
|
+
const invocation = statementParts[0];
|
|
651
|
+
if (statementParts.length != 2 || invocation?.type != "method_invocation" || statementParts[1].text != ";")
|
|
652
|
+
return false;
|
|
653
|
+
const invocationParts = this.parts(invocation);
|
|
654
|
+
const functionNode = this.field(invocation, "function");
|
|
655
|
+
const argumentPart = this.field(invocation, "arguments");
|
|
656
|
+
if (invocationParts.length != 2 || invocationParts[0].id != functionNode.id || functionNode.type != "identifier" ||
|
|
657
|
+
functionNode.text != "_semantifoldUse" || invocationParts[1].id != argumentPart.id || argumentPart.type != "argument_part") {
|
|
658
|
+
return false;
|
|
659
|
+
}
|
|
660
|
+
this.shape(node, [invocation, ";"]);
|
|
661
|
+
this.shape(invocation, [functionNode, argumentPart]);
|
|
662
|
+
const arguments_ = this.arguments(argumentPart);
|
|
663
|
+
if (arguments_.length != 1 || arguments_[0].length != 1 || arguments_[0][0].type != "identifier" ||
|
|
664
|
+
this.identifier(arguments_[0][0]) != previous.name)
|
|
665
|
+
this.fail(argumentPart, "Dart analyzer local-use support shape");
|
|
666
|
+
return true;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Converts a braced Dart block.
|
|
670
|
+
* @param {import("tree-sitter").SyntaxNode} node Braced block.
|
|
671
|
+
* @returns {import("../semantic/types.js").Block} Semantic block.
|
|
672
|
+
*/
|
|
673
|
+
block(node) {
|
|
674
|
+
const parts = this.parts(node);
|
|
675
|
+
if (node.type != "block" || parts.length < 2 || parts[0].text != "{" || parts.at(-1)?.text != "}") {
|
|
676
|
+
this.fail(node, "braced block shape");
|
|
677
|
+
}
|
|
678
|
+
this.shape(node, ["{", ...parts.slice(1, -1), "}"]);
|
|
679
|
+
/** @type {import("../semantic/types.js").Statement[]} */
|
|
680
|
+
const statements = [];
|
|
681
|
+
for (const statement of parts.slice(1, -1)) {
|
|
682
|
+
if (!this.generatedLocalUse(statement, statements.at(-1)))
|
|
683
|
+
statements.push(this.statement(statement));
|
|
684
|
+
}
|
|
685
|
+
return {
|
|
686
|
+
kind: /** @type {const} */ ("Block"),
|
|
687
|
+
location: this.location(node),
|
|
688
|
+
statements
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Unwraps a synchronous braced function body.
|
|
693
|
+
* @param {import("tree-sitter").SyntaxNode} body Function body wrapper.
|
|
694
|
+
* @returns {import("../semantic/types.js").Block} Semantic body.
|
|
695
|
+
*/
|
|
696
|
+
functionBody(body) {
|
|
697
|
+
const parts = this.parts(body);
|
|
698
|
+
if (body.type != "function_body" || parts.length != 1 || parts[0].type != "block") {
|
|
699
|
+
this.fail(body, "synchronous braced function body required");
|
|
700
|
+
}
|
|
701
|
+
this.shape(body, [parts[0]]);
|
|
702
|
+
return this.block(parts[0]);
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Converts one strict-Boolean conditional.
|
|
706
|
+
* @param {import("tree-sitter").SyntaxNode} node Strict Boolean conditional.
|
|
707
|
+
* @returns {import("../semantic/types.js").IfStatement} Semantic conditional.
|
|
708
|
+
*/
|
|
709
|
+
conditional(node) {
|
|
710
|
+
const parts = this.parts(node);
|
|
711
|
+
const consequence = this.field(node, "consequence");
|
|
712
|
+
const consequenceIndex = parts.findIndex(({ id }) => id == consequence.id);
|
|
713
|
+
if (node.type != "if_statement" || parts[0]?.text != "if" || parts[1]?.text != "(" || consequence.type != "block" ||
|
|
714
|
+
consequenceIndex < 4 || parts[consequenceIndex - 1]?.text != ")")
|
|
715
|
+
this.fail(node, "if statement shape");
|
|
716
|
+
const conditionParts = parts.slice(2, consequenceIndex - 1);
|
|
717
|
+
if (conditionParts.length == 0)
|
|
718
|
+
this.fail(node, "empty if condition");
|
|
719
|
+
const statement = /** @type {import("../semantic/types.js").IfStatement} */ ({
|
|
720
|
+
condition: this.expression(conditionParts, node),
|
|
721
|
+
consequent: this.block(consequence),
|
|
722
|
+
kind: /** @type {const} */ ("IfStatement"),
|
|
723
|
+
location: this.location(node)
|
|
724
|
+
});
|
|
725
|
+
if (parts.length == consequenceIndex + 1) {
|
|
726
|
+
this.shape(node, ["if", "(", ...conditionParts, ")", consequence]);
|
|
727
|
+
return statement;
|
|
728
|
+
}
|
|
729
|
+
const alternative = this.field(node, "alternative");
|
|
730
|
+
if (parts.length != consequenceIndex + 3 || parts[consequenceIndex + 1]?.text != "else" ||
|
|
731
|
+
parts[consequenceIndex + 2]?.id != alternative.id)
|
|
732
|
+
this.fail(alternative, "if alternate shape");
|
|
733
|
+
this.shape(node, ["if", "(", ...conditionParts, ")", consequence, "else", alternative]);
|
|
734
|
+
if (alternative.type == "block")
|
|
735
|
+
return { ...statement, alternate: this.block(alternative) };
|
|
736
|
+
if (alternative.type == "if_statement") {
|
|
737
|
+
return { ...statement, alternate: {
|
|
738
|
+
kind: /** @type {const} */ ("Block"), location: this.location(alternative), statements: [this.conditional(alternative)]
|
|
739
|
+
} };
|
|
740
|
+
}
|
|
741
|
+
return this.fail(alternative, "braced block or else-if required");
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Converts one required explicitly typed positional parameter.
|
|
745
|
+
* @param {import("tree-sitter").SyntaxNode} node Required positional parameter.
|
|
746
|
+
* @returns {import("../semantic/types.js").Parameter} Semantic parameter.
|
|
747
|
+
*/
|
|
748
|
+
parameter(node) {
|
|
749
|
+
const parts = this.parts(node);
|
|
750
|
+
if (parts.length == 1 && parts[0].type == "identifier")
|
|
751
|
+
return missingType("dart", "Parameter", this.location(node));
|
|
752
|
+
if (node.type != "formal_parameter" || parts.length != 2 || parts[0].type != "type_identifier" ||
|
|
753
|
+
parts[1].type != "identifier")
|
|
754
|
+
this.fail(node, "required explicitly typed positional parameter");
|
|
755
|
+
this.shape(node, [parts[0], parts[1]]);
|
|
756
|
+
if (this.field(node, "name").id != parts[1].id)
|
|
757
|
+
this.fail(parts[1], "parameter name field");
|
|
758
|
+
const name = this.identifier(parts[1]);
|
|
759
|
+
return withParserRanges({
|
|
760
|
+
kind: /** @type {const} */ ("Parameter"), location: this.location(node), name, type: this.scalarType(parts[0])
|
|
761
|
+
}, { name: this.location(parts[1]) });
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Converts a required positional parameter list.
|
|
765
|
+
* @param {import("tree-sitter").SyntaxNode} node Parameter list.
|
|
766
|
+
* @returns {import("../semantic/types.js").Parameter[]} Semantic parameters.
|
|
767
|
+
*/
|
|
768
|
+
parameters(node) {
|
|
769
|
+
const parts = this.parts(node);
|
|
770
|
+
if (node.type != "formal_parameter_list" || parts.length < 2 || parts[0].text != "(" || parts.at(-1)?.text != ")") {
|
|
771
|
+
this.fail(node, "formal parameter list shape");
|
|
772
|
+
}
|
|
773
|
+
const interior = parts.slice(1, -1);
|
|
774
|
+
const hasGeneratedTrailingComma = this.runtime && interior.at(-1)?.text == ",";
|
|
775
|
+
const parameterParts = hasGeneratedTrailingComma ? interior.slice(0, -1) : interior;
|
|
776
|
+
const parameters = parameterParts.filter((_child, index) => index % 2 == 0);
|
|
777
|
+
this.shape(node, ["(", ...parameters.flatMap((parameter, index) => index ? [",", parameter] : [parameter]),
|
|
778
|
+
...(hasGeneratedTrailingComma ? [","] : []), ")"]);
|
|
779
|
+
return parameters.map((parameter) => this.parameter(parameter));
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Converts one ordinary top-level function declaration.
|
|
783
|
+
* @param {import("tree-sitter").SyntaxNode} signature Function signature.
|
|
784
|
+
* @param {import("tree-sitter").SyntaxNode} body Function body.
|
|
785
|
+
* @returns {import("../semantic/types.js").FunctionDeclaration} Semantic function.
|
|
786
|
+
*/
|
|
787
|
+
function(signature, body) {
|
|
788
|
+
const parts = this.parts(signature);
|
|
789
|
+
if (signature.type != "function_signature")
|
|
790
|
+
this.fail(signature, "function signature");
|
|
791
|
+
if (parts.length == 2 && parts[0].type == "identifier")
|
|
792
|
+
return missingType("dart", "Function return", this.location(signature));
|
|
793
|
+
if (parts.length != 3 || !["type_identifier", "void_type"].includes(parts[0].type) || parts[1].type != "identifier" ||
|
|
794
|
+
parts[2].type != "formal_parameter_list")
|
|
795
|
+
this.fail(signature, "explicit top-level function signature");
|
|
796
|
+
this.shape(signature, [parts[0], parts[1], parts[2]]);
|
|
797
|
+
if (this.field(signature, "name").id != parts[1].id)
|
|
798
|
+
this.fail(parts[1], "function name field");
|
|
799
|
+
const name = this.identifier(parts[1]);
|
|
800
|
+
const location = locationFromOffsets(this.filename, this.source, bindingIndexToUtf16Offset(this.source, signature.startIndex), bindingIndexToUtf16Offset(this.source, body.endIndex));
|
|
801
|
+
return withParserRanges({
|
|
802
|
+
body: this.functionBody(body),
|
|
803
|
+
kind: /** @type {const} */ ("FunctionDeclaration"),
|
|
804
|
+
location,
|
|
805
|
+
name,
|
|
806
|
+
parameters: this.parameters(parts[2]),
|
|
807
|
+
returnType: this.returnType(parts[0])
|
|
808
|
+
}, { name: this.location(parts[1]) });
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Converts the exact void main entry shell.
|
|
812
|
+
* @param {import("tree-sitter").SyntaxNode} signature Main signature.
|
|
813
|
+
* @param {import("tree-sitter").SyntaxNode} body Main body.
|
|
814
|
+
* @returns {import("../semantic/types.js").EntryPoint} Semantic entry point.
|
|
815
|
+
*/
|
|
816
|
+
main(signature, body) {
|
|
817
|
+
const parts = this.parts(signature);
|
|
818
|
+
if (signature.type != "function_signature" || parts.length != 3 || parts[0].type != "void_type" ||
|
|
819
|
+
this.identifier(parts[1], true) != "main" || parts[2].type != "formal_parameter_list") {
|
|
820
|
+
this.fail(signature, "exact void main() signature required");
|
|
821
|
+
}
|
|
822
|
+
this.shape(signature, [parts[0], parts[1], parts[2]]);
|
|
823
|
+
this.shape(parts[2], ["(", ")"]);
|
|
824
|
+
const location = locationFromOffsets(this.filename, this.source, bindingIndexToUtf16Offset(this.source, signature.startIndex), bindingIndexToUtf16Offset(this.source, body.endIndex));
|
|
825
|
+
return { body: this.functionBody(body), kind: /** @type {const} */ ("EntryPoint"), location };
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Converts one complete Dart compilation unit.
|
|
829
|
+
* @param {import("tree-sitter").SyntaxNode} root Complete Dart program.
|
|
830
|
+
* @returns {import("../semantic/types.js").SemanticModule} Semantic module.
|
|
831
|
+
*/
|
|
832
|
+
module(root) {
|
|
833
|
+
this.validateTree(root);
|
|
834
|
+
if (root.type != "program")
|
|
835
|
+
this.fail(root, "program root");
|
|
836
|
+
const parts = this.parts(root);
|
|
837
|
+
const supportTree = parser.parse(dartRuntime);
|
|
838
|
+
const support = this.parts(supportTree.rootNode);
|
|
839
|
+
let supportIndex = 0;
|
|
840
|
+
while (supportIndex < parts.length && supportIndex < support.length &&
|
|
841
|
+
parts[supportIndex].type == support[supportIndex].type) {
|
|
842
|
+
this.compareTree(parts[supportIndex], support[supportIndex]);
|
|
843
|
+
supportIndex += 1;
|
|
844
|
+
}
|
|
845
|
+
if (supportIndex > 0 && supportIndex != support.length) {
|
|
846
|
+
this.fail(parts[supportIndex - 1], "complete Dart support required");
|
|
847
|
+
}
|
|
848
|
+
this.runtime = supportIndex == support.length;
|
|
849
|
+
const semanticParts = parts.slice(supportIndex);
|
|
850
|
+
if (semanticParts.length == 0)
|
|
851
|
+
this.fail(root, "program without main");
|
|
852
|
+
/** @type {{body: import("tree-sitter").SyntaxNode, signature: import("tree-sitter").SyntaxNode}[]} */
|
|
853
|
+
const declarations = [];
|
|
854
|
+
for (const declaration of semanticParts) {
|
|
855
|
+
if (declaration.type != "function_declaration")
|
|
856
|
+
this.fail(declaration, "top-level function declaration required");
|
|
857
|
+
const signature = this.field(declaration, "signature");
|
|
858
|
+
const body = this.field(declaration, "body");
|
|
859
|
+
const declarationParts = this.parts(declaration);
|
|
860
|
+
if (declarationParts.length != 2 || declarationParts[0].id != signature.id || signature.type != "function_signature" ||
|
|
861
|
+
declarationParts[1].id != body.id || body.type != "function_body") {
|
|
862
|
+
this.fail(declaration, "paired top-level function signature and body required");
|
|
863
|
+
}
|
|
864
|
+
this.shape(declaration, [signature, body]);
|
|
865
|
+
declarations.push({ body, signature });
|
|
866
|
+
}
|
|
867
|
+
const mainIndexes = declarations.flatMap(({ signature }, index) => this.parts(signature)[1]?.text == "main" ? [index] : []);
|
|
868
|
+
if (mainIndexes.length != 1)
|
|
869
|
+
this.fail(root, "exactly one main declaration required");
|
|
870
|
+
const mainIndex = mainIndexes[0];
|
|
871
|
+
this.functionNames = new Set(declarations.map(({ signature }) => this.parts(signature)[1]?.text).filter(Boolean));
|
|
872
|
+
if (mainIndex != declarations.length - 1)
|
|
873
|
+
this.fail(declarations[mainIndex + 1].signature, "declaration after main");
|
|
874
|
+
const main = declarations[mainIndex];
|
|
875
|
+
const module = {
|
|
876
|
+
entryPoint: this.main(main.signature, main.body),
|
|
877
|
+
functions: declarations.slice(0, mainIndex).map(({ body, signature }) => this.function(signature, body)),
|
|
878
|
+
kind: /** @type {const} */ ("Module"),
|
|
879
|
+
location: this.location(root)
|
|
880
|
+
};
|
|
881
|
+
validateParsedModule(module, "dart");
|
|
882
|
+
return module;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Parses the strict Task 029 Dart VM/native profile through the qualified grammar.
|
|
887
|
+
* @param {{filename: string, source: string}} input Exact source request.
|
|
888
|
+
* @returns {import("../semantic/types.js").SemanticModule} Semantic module.
|
|
889
|
+
*/
|
|
890
|
+
export function parseDart({ filename, source }) {
|
|
891
|
+
if (!hasOnlyUnicodeScalars(source)) {
|
|
892
|
+
const offset = firstLoneSurrogateOffset(source);
|
|
893
|
+
throw new SemantifoldDiagnostic({
|
|
894
|
+
code: "PARSE_ERROR", language: "dart", location: locationFromOffsets(filename, source, offset, offset + 1),
|
|
895
|
+
message: "Dart source contains an invalid lone UTF-16 surrogate."
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
let tree;
|
|
899
|
+
try {
|
|
900
|
+
tree = parser.parse(source);
|
|
901
|
+
}
|
|
902
|
+
catch (error) {
|
|
903
|
+
throw new SemantifoldDiagnostic({
|
|
904
|
+
cause: error instanceof Error ? error : undefined,
|
|
905
|
+
code: "PARSE_ERROR",
|
|
906
|
+
language: "dart",
|
|
907
|
+
location: moduleLocation(filename, source),
|
|
908
|
+
message: "The qualified Dart parser could not produce a complete CST."
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
return new DartReader(filename, source).module(tree.rootNode);
|
|
912
|
+
}
|
|
913
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGFydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mcm9udGVuZHMvZGFydC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxNQUFNLE1BQU0sYUFBYSxDQUFBO0FBQ2hDLE9BQU8sWUFBWSxNQUFNLGlEQUFpRCxDQUFBO0FBQzFFLE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLDRCQUE0QixDQUFBO0FBQzNELE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSw2QkFBNkIsQ0FBQTtBQUN2RCxPQUFPLEVBQUMsV0FBVyxFQUFFLHFCQUFxQixFQUFFLGlCQUFpQixFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDdEYsT0FBTyxFQUFDLG1CQUFtQixFQUFFLGNBQWMsRUFBRSwyQkFBMkIsRUFBQyxNQUFNLHlCQUF5QixDQUFBO0FBQ3hHLE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLDBCQUEwQixDQUFBO0FBQzdELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLDJCQUEyQixDQUFBO0FBQzFELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLHdCQUF3QixDQUFBO0FBQzVELE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLHlCQUF5QixDQUFBO0FBQzVELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLGNBQWMsQ0FBQTtBQUU3QyxNQUFNLE1BQU0sR0FBRyxJQUFJLE1BQU0sRUFBRSxDQUFBO0FBRTNCLE1BQU0sQ0FBQyxXQUFXLENBQUMsNkNBQTZDLENBQUMsRUFBQyxzQkFBdUIsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFFekcsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUMvQixDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksRUFB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LENBQUMsRUFBRSxJQUFJLElBQUksZUFBZSxDQUFBO1FBQ25ELE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDbkMsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBQ2pDLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDckMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUNuQyxNQUFNLGVBQWUsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUVsRCxJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsU0FBUyxHQUFHLENBQUMsSUFBSSxRQUFRLEVBQUUsSUFBSSxJQUFJLGlCQUFpQixJQUFJLFFBQVEsRUFBRSxJQUFJLElBQUksWUFBWTtZQUN2RyxNQUFNLEVBQUUsSUFBSSxJQUFJLEdBQUcsSUFBSSxlQUFlLENBQUMsTUFBTSxJQUFJLENBQUMsSUFBSSxTQUFTLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUM5RixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxVQUFVLEVBQUUsNkNBQTZDLENBQUMsQ0FBQTtRQUNsRixDQUFDO1FBQ0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxHQUFHLGVBQWUsQ0FBQyxDQUFDLENBQUE7UUFDdkcsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQyxFQUFFLElBQUks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QUE7SUFFUixJQUFJLENBQUM7UUFDSCxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUM3QixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE1BQU0sSUFBSSxxQkFBcUIsQ0FBQztZQUM5QixLQUFLLEVBQUUsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTO1lBQ2pELElBQUksRUFBRSxhQUFhO1lBQ25CLFFBQVEsRUFBRSxNQUFNO1lBQ2hCLFFBQVEsRUFBRSxjQUFjLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQztZQUMxQyxPQUFPLEVBQUUsNkRBQTZEO1NBQ3ZFLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFDRCxPQUFPLElBQUksVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQy9ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IFBhcnNlciBmcm9tIFwidHJlZS1zaXR0ZXJcIlxuaW1wb3J0IERhcnRMYW5ndWFnZSBmcm9tIFwidHJlZS1zaXR0ZXItZGFydC1vcmNoYXJkL2JpbmRpbmdzL25vZGUvaW5kZXguanNcIlxuaW1wb3J0IHtpc0RhcnRJZGVudGlmaWVyfSBmcm9tIFwiLi4vYmFja2VuZHMvaWRlbnRpZmllcnMuanNcIlxuaW1wb3J0IHtkYXJ0UnVudGltZX0gZnJvbSBcIi4uL2JhY2tlbmRzL2RhcnQtcnVudGltZS5qc1wiXG5pbXBvcnQge21pc3NpbmdUeXBlLCBTZW1hbnRpZm9sZERpYWdub3N0aWMsIHVuc3VwcG9ydGVkU3ludGF4fSBmcm9tIFwiLi4vZGlhZ25vc3RpYy5qc1wiXG5pbXBvcnQge2xvY2F0aW9uRnJvbU9mZnNldHMsIG1vZHVsZUxvY2F0aW9uLCB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXR9IGZyb20gXCIuLi9zZW1hbnRpYy9sb2NhdGlvbi5qc1wiXG5pbXBvcnQge3dpdGhBZGFwdGVkT3BlcmF0aW9ufSBmcm9tIFwiLi4vc2VtYW50aWMvb3BlcmF0b3JzLmpzXCJcbmltcG9ydCB7d2l0aFBhcnNlclJhbmdlc30gZnJvbSBcIi4uL3NlbWFudGljL3Byb3ZlbmFuY2UuanNcIlxuaW1wb3J0IHtoYXNPbmx5VW5pY29kZVNjYWxhcnN9IGZyb20gXCIuLi9zZW1hbnRpYy9zY2FsYXJzLmpzXCJcbmltcG9ydCB7dmFsaWRhdGVQYXJzZWRNb2R1bGV9IGZyb20gXCIuLi9zZW1hbnRpYy92YWxpZGF0ZS5qc1wiXG5pbXBvcnQge3NvdXJjZVNjYWxhclR5cGV9IGZyb20gXCIuL3NjYWxhcnMuanNcIlxuXG5jb25zdCBwYXJzZXIgPSBuZXcgUGFyc2VyKClcblxucGFyc2VyLnNldExhbmd1YWdlKC8qKiBAdHlwZSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuTGFuZ3VhZ2V9ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChEYXJ0TGFuZ3VhZ2UpKSlcblxuY29uc3QgYmluYXJ5T3BlcmF0aW9ucyA9IG5ldyBNYXAoW1xuICBbXCIrXCIsIFwiQWRkXCJdLCBbXCItXCIsIFwiU3VidHJhY3RcIl0sIFtcIipcIiwgXCJNdWx0aXBseVwiXSwgW1wiPT1cIiwgXCJFcXVhbFwiXSwgW1wiIT1cIiwgXCJOb3RFcXVhbFwiXSxcbiAgW1wiPFwiLCBcIkxlc3NUaGFuXCJdLCBbXCI8PVwiLCBcIkxlc3NUaGFuT3JFcXVhbFwiXSwgW1wiPlwiLCBcIkdyZWF0ZXJUaGFuXCJdLCBbXCI+PVwiLCBcIkdyZWF0ZXJUaGFuT3JFcXVhbFwiXSxcbiAgW1wiJiZcIiwgXCJBbmRcIl0sIFtcInx8XCIsIFwiT3JcIl1cbl0pXG4vKiogQHR5cGUge01hcDxzdHJpbmcsIHJlYWRvbmx5IFtzdHJpbmcsIFNldDxzdHJpbmc+XT59ICovXG5jb25zdCBiaW5hcnlOb2RlT3BlcmF0b3JzID0gbmV3IE1hcChbXG4gIFtcImFkZGl0aXZlX2V4cHJlc3Npb25cIiwgW1wiYWRkaXRpdmVfb3BlcmF0b3JcIiwgbmV3IFNldChbXCIrXCIsIFwiLVwiXSldXSxcbiAgW1wibXVsdGlwbGljYXRpdmVfZXhwcmVzc2lvblwiLCBbXCJtdWx0aXBsaWNhdGl2ZV9vcGVyYXRvclwiLCBuZXcgU2V0KFtcIipcIl0pXV0sXG4gIFtcImVxdWFsaXR5X2V4cHJlc3Npb25cIiwgW1wiZXF1YWxpdHlfb3BlcmF0b3JcIiwgbmV3IFNldChbXCI9PVwiLCBcIiE9XCJdKV1dLFxuICBbXCJyZWxhdGlvbmFsX2V4cHJlc3Npb25cIiwgW1wicmVsYXRpb25hbF9vcGVyYXRvclwiLCBuZXcgU2V0KFtcIjxcIiwgXCI8PVwiLCBcIj5cIiwgXCI+PVwiXSldXSxcbiAgW1wibG9naWNhbF9hbmRfZXhwcmVzc2lvblwiLCBbXCJsb2dpY2FsX2FuZF9vcGVyYXRvclwiLCBuZXcgU2V0KFtcIiYmXCJdKV1dLFxuICBbXCJsb2dpY2FsX29yX2V4cHJlc3Npb25cIiwgW1wibG9naWNhbF9vcl9vcGVyYXRvclwiLCBuZXcgU2V0KFtcInx8XCJdKV1dXG5dKVxuY29uc3QgY29tbWVudFR5cGVzID0gbmV3IFNldChbXCJjb21tZW50XCIsIFwiZG9jdW1lbnRhdGlvbl9jb21tZW50XCJdKVxuLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuLi9zZW1hbnRpYy9vcGVyYXRvcnMuanNcIikuQWRhcHRlZE9wZXJhdGlvbj59ICovXG5jb25zdCBoZWxwZXJPcGVyYXRpb25zID0gbmV3IE1hcChbXG4gIFtcIl9zZW1hbnRpZm9sZEludGVnZXJBZGRcIiwgXCJBZGRcIl0sIFtcIl9zZW1hbnRpZm9sZEludGVnZXJTdWJ0cmFjdFwiLCBcIlN1YnRyYWN0XCJdLFxuICBbXCJfc2VtYW50aWZvbGRJbnRlZ2VyTXVsdGlwbHlcIiwgXCJNdWx0aXBseVwiXSwgW1wiX3NlbWFudGlmb2xkSW50ZWdlck5lZ2F0ZVwiLCBcIk5lZ2F0ZVwiXVxuXSlcblxuLyoqXG4gKiBWZXJpZmllcyBhIGJpbmRpbmctcmVwb3J0ZWQgVVRGLTE2IGluZGV4IHRocm91Z2ggdGhlIHNoYXJlZCBVVEYtOCBjb252ZXJ0ZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIENvbXBsZXRlIHNvdXJjZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBCaW5kaW5nIGluZGV4LlxuICogQHJldHVybnMge251bWJlcn0gVmVyaWZpZWQgVVRGLTE2IG9mZnNldC5cbiAqL1xuZnVuY3Rpb24gYmluZGluZ0luZGV4VG9VdGYxNk9mZnNldChzb3VyY2UsIGluZGV4KSB7XG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcihpbmRleCkgfHwgaW5kZXggPCAwIHx8IGluZGV4ID4gc291cmNlLmxlbmd0aCB8fFxuICAgIGluZGV4ID4gMCAmJiBpbmRleCA8IHNvdXJjZS5sZW5ndGggJiYgL1tcXHVEODAwLVxcdURCRkZdL3UudGVzdChzb3VyY2VbaW5kZXggLSAxXSkgJiYgL1tcXHVEQzAwLVxcdURGRkZdL3UudGVzdChzb3VyY2VbaW5kZXhdKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKFwiSW52YWxpZCBUcmVlLXNpdHRlciBzb3VyY2UgaW5kZXg6IFwiICsgaW5kZXgpXG4gIH1cbiAgcmV0dXJuIHV0ZjhCeXRlT2Zmc2V0VG9VdGYxNk9mZnNldChzb3VyY2UsIG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzb3VyY2Uuc2xpY2UoMCwgaW5kZXgpKS5sZW5ndGgpXG59XG5cbi8qKlxuICogRmluZHMgdGhlIGZpcnN0IHVucGFpcmVkIFVURi0xNiBzdXJyb2dhdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IEludmFsaWQgb2Zmc2V0IG9yIC0xLlxuICovXG5mdW5jdGlvbiBmaXJzdExvbmVTdXJyb2dhdGVPZmZzZXQoc291cmNlKSB7XG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBzb3VyY2UubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgY29uc3QgdW5pdCA9IHNvdXJjZS5jaGFyQ29kZUF0KGluZGV4KVxuXG4gICAgaWYgKHVuaXQgPj0gMHhEODAwICYmIHVuaXQgPD0gMHhEQkZGKSB7XG4gICAgICBjb25zdCBuZXh0ID0gc291cmNlLmNoYXJDb2RlQXQoaW5kZXggKyAxKVxuXG4gICAgICBpZiAobmV4dCA+PSAweERDMDAgJiYgbmV4dCA8PSAweERGRkYpIGluZGV4ICs9IDFcbiAgICAgIGVsc2UgcmV0dXJuIGluZGV4XG4gICAgfSBlbHNlIGlmICh1bml0ID49IDB4REMwMCAmJiB1bml0IDw9IDB4REZGRikgcmV0dXJuIGluZGV4XG4gIH1cbiAgcmV0dXJuIC0xXG59XG5cbi8qKiBDb25zdW1lcyBleGFjdCBxdWFsaWZpZWQgRGFydCBDU1Qgc2hhcGVzIHdpdGhvdXQgcmV0YWluaW5nIHBhcnNlciB2YWx1ZXMuICovXG5jbGFzcyBEYXJ0UmVhZGVyIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSByZWFkZXIgYm91bmQgdG8gb25lIGV4YWN0IERhcnQgc291cmNlIHVuaXQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSBPcmlnaW5hbCBmaWxlbmFtZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSBDb21wbGV0ZSBzb3VyY2UuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihmaWxlbmFtZSwgc291cmNlKSB7XG4gICAgdGhpcy5maWxlbmFtZSA9IGZpbGVuYW1lXG4gICAgdGhpcy5zb3VyY2UgPSBzb3VyY2VcbiAgICAvKiogQHR5cGUge1NldDxzdHJpbmc+fSAqL1xuICAgIHRoaXMuZnVuY3Rpb25OYW1lcyA9IG5ldyBTZXQoKVxuICAgIHRoaXMucnVudGltZSA9IGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGEgc2VtYW50aWMgc291cmNlIGxvY2F0aW9uIGZyb20gb25lIHBhcnNlciBub2RlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IG5vZGUgUGFyc2VyIG5vZGUuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gRXhhY3QgbG9jYXRpb24uXG4gICAqL1xuICBsb2NhdGlvbihub2RlKSB7XG4gICAgcmV0dXJuIGxvY2F0aW9uRnJvbU9mZnNldHModGhpcy5maWxlbmFtZSwgdGhpcy5zb3VyY2UsIGJpbmRpbmdJbmRleFRvVXRmMTZPZmZzZXQodGhpcy5zb3VyY2UsIG5vZGUuc3RhcnRJbmRleCksXG4gICAgICBiaW5kaW5nSW5kZXhUb1V0ZjE2T2Zmc2V0KHRoaXMuc291cmNlLCBub2RlLmVuZEluZGV4KSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWplY3RzIG9uZSBwYXJzZXIgbm9kZSB3aXRoIGEgbG9jYXRlZCB1bnN1cHBvcnRlZC1zeW50YXggZGlhZ25vc3RpYy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIFZpb2xhdGluZyBub2RlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2RldGFpbF0gUHJvZmlsZSBkZXRhaWwuXG4gICAqIEByZXR1cm5zIHtuZXZlcn0gQWx3YXlzIHRocm93cy5cbiAgICovXG4gIGZhaWwobm9kZSwgZGV0YWlsID0gbm9kZS50eXBlKSB7XG4gICAgdW5zdXBwb3J0ZWRTeW50YXgoXCJkYXJ0XCIsIGRldGFpbCwgdGhpcy5sb2NhdGlvbihub2RlKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmF2ZXJzZXMgZXZlcnkgbmFtZWQsIGFub255bW91cywgZXh0cmEsIGZpZWxkLCBhbmQgcmVjb3ZlcnkgZWRnZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSByb290IENvbXBsZXRlIHBhcnNlciByb290LlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHZhbGlkYXRlVHJlZShyb290KSB7XG4gICAgY29uc3QgcGVuZGluZyA9IFt7ZGVwdGg6IDAsIG5vZGU6IHJvb3QsIHZpc2l0ZWQ6IGZhbHNlfV1cblxuICAgIHdoaWxlIChwZW5kaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGN1cnJlbnQgPSBwZW5kaW5nLnBvcCgpXG5cbiAgICAgIGlmICghY3VycmVudCkgdGhyb3cgbmV3IEVycm9yKFwiRGFydCB0cmF2ZXJzYWwgbG9zdCBhIHBlbmRpbmcgcGFyc2VyIG5vZGUuXCIpXG4gICAgICBjb25zdCB7ZGVwdGgsIG5vZGUsIHZpc2l0ZWR9ID0gY3VycmVudFxuXG4gICAgICBpZiAoZGVwdGggPiA1MTIpIHRoaXMuZmFpbChub2RlLCBcIkNTVCBleGNlZWRzIHRoZSA1MTItbGV2ZWwgdHJhdmVyc2FsIGxpbWl0XCIpXG4gICAgICBpZiAoIXZpc2l0ZWQpIHtcbiAgICAgICAgcGVuZGluZy5wdXNoKHtkZXB0aCwgbm9kZSwgdmlzaXRlZDogdHJ1ZX0pXG4gICAgICAgIGZvciAobGV0IGluZGV4ID0gbm9kZS5jaGlsZENvdW50IC0gMTsgaW5kZXggPj0gMDsgaW5kZXggLT0gMSkge1xuICAgICAgICAgIGNvbnN0IGNoaWxkID0gbm9kZS5jaGlsZChpbmRleClcblxuICAgICAgICAgIGlmICghY2hpbGQpIHRocm93IG5ldyBFcnJvcihgVHJlZS1zaXR0ZXIgb21pdHRlZCBjaGlsZCAke2luZGV4fSBvZiAke25vZGUudHlwZX0uYClcbiAgICAgICAgICBub2RlLmZpZWxkTmFtZUZvckNoaWxkKGluZGV4KVxuICAgICAgICAgIHBlbmRpbmcucHVzaCh7ZGVwdGg6IGRlcHRoICsgMSwgbm9kZTogY2hpbGQsIHZpc2l0ZWQ6IGZhbHNlfSlcbiAgICAgICAgfVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgaWYgKG5vZGUuaGFzRXJyb3IgfHwgbm9kZS5pc0Vycm9yIHx8IG5vZGUuaXNNaXNzaW5nKSB7XG4gICAgICAgIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgICAgICAgIGNvZGU6IFwiUEFSU0VfRVJST1JcIixcbiAgICAgICAgICBsYW5ndWFnZTogXCJkYXJ0XCIsXG4gICAgICAgICAgbG9jYXRpb246IHRoaXMubG9jYXRpb24obm9kZSksXG4gICAgICAgICAgbWVzc2FnZTogYFRyZWUtc2l0dGVyIGV4cG9zZWQgcmVjb3ZlcnkgYXQgJyR7bm9kZS50eXBlfScuYFxuICAgICAgICB9KVxuICAgICAgfVxuICAgICAgaWYgKFtcImFubm90YXRpb25cIiwgXCJpbXBvcnRfb3JfZXhwb3J0XCIsIFwibGlicmFyeV9uYW1lXCIsIFwicGFydF9oZWFkZXJcIiwgXCJwYXJ0X29mX2hlYWRlclwiXS5pbmNsdWRlcyhub2RlLnR5cGUpKSB7XG4gICAgICAgIHRoaXMuZmFpbChub2RlLCBub2RlLnR5cGUpXG4gICAgICB9XG4gICAgICBpZiAoY29tbWVudFR5cGVzLmhhcyhub2RlLnR5cGUpICYmICgvKD86QGRhcnRcXHMqPXxkYXJ0Zm10fGlnbm9yZSg/Ol9mb3JfZmlsZSk/XFxzKjp8bGFuZ3VhZ2VbLV8gXXZlcnNpb24pL2l1LnRlc3Qobm9kZS50ZXh0KSB8fFxuICAgICAgICAvXlxcL1xcLyBkYXJ0IGZvcm1hdCAoPzpvZmZ8b24pW1xcdCBdKiQvdS50ZXN0KG5vZGUudGV4dCkpKSB7XG4gICAgICAgIHRoaXMuZmFpbChub2RlLCBcImRpcmVjdGl2ZS1iZWFyaW5nIGNvbW1lbnRcIilcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogT21pdHMgb25seSBvcmRpbmFyeSBjb21tZW50cyBhbHJlYWR5IGNvdmVyZWQgYnkgZXhoYXVzdGl2ZSB0cmF2ZXJzYWwuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSBQYXJlbnQgbm9kZS5cbiAgICogQHJldHVybnMge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGVbXX0gU3RydWN0dXJhbCBjaGlsZHJlbi5cbiAgICovXG4gIHBhcnRzKG5vZGUpIHtcbiAgICByZXR1cm4gbm9kZS5jaGlsZHJlbi5maWx0ZXIoKGNoaWxkKSA9PiAhY29tbWVudFR5cGVzLmhhcyhjaGlsZC50eXBlKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmllcyBhbiBleGFjdCBzdHJ1Y3R1cmFsIGNoaWxkIHNlcXVlbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IG5vZGUgU2hhcGUgb3duZXIuXG4gICAqIEBwYXJhbSB7KGltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGUgfCBzdHJpbmcpW119IGV4cGVjdGVkIEV4YWN0IGNoaWxkIHNlcXVlbmNlLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHNoYXBlKG5vZGUsIGV4cGVjdGVkKSB7XG4gICAgY29uc3QgYWN0dWFsID0gdGhpcy5wYXJ0cyhub2RlKVxuXG4gICAgaWYgKGFjdHVhbC5sZW5ndGggIT0gZXhwZWN0ZWQubGVuZ3RoKSB0aGlzLmZhaWwoYWN0dWFsW01hdGgubWluKGFjdHVhbC5sZW5ndGgsIGV4cGVjdGVkLmxlbmd0aCldID8/IG5vZGUsIGAke25vZGUudHlwZX0gY2hpbGQgc2hhcGVgKVxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBleHBlY3RlZC5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IHdhbnRlZCA9IGV4cGVjdGVkW2luZGV4XVxuICAgICAgY29uc3QgY2hpbGQgPSBhY3R1YWxbaW5kZXhdXG4gICAgICBjb25zdCBtYXRjaGVzID0gdHlwZW9mIHdhbnRlZCA9PSBcInN0cmluZ1wiID8gY2hpbGQudGV4dCA9PSB3YW50ZWQgOiBjaGlsZC5pZCA9PSB3YW50ZWQuaWRcblxuICAgICAgaWYgKCFtYXRjaGVzKSB0aGlzLmZhaWwoY2hpbGQsIGAke25vZGUudHlwZX0gY2hpbGQgc2hhcGVgKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdW1lcyBhbiBPcmNoYXJkIG9wZXJhdG9yIHdyYXBwZXIgd2hldGhlciBpdHMgdG9rZW4gaXMgYWxpYXNlZCBpbnRvIHRoZSB3cmFwcGVyIG9yIGV4cG9zZWQgYW5vbnltb3VzbHkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSBPcGVyYXRvciBub2RlLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIG9wZXJhdG9yU2hhcGUobm9kZSkge1xuICAgIGNvbnN0IHBhcnRzID0gdGhpcy5wYXJ0cyhub2RlKVxuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCA+IDEgfHwgcGFydHMubGVuZ3RoID09IDEgJiYgKHBhcnRzWzBdLmlzTmFtZWQgfHwgcGFydHNbMF0udGV4dCAhPSBub2RlLnRleHQpKSB7XG4gICAgICB0aGlzLmZhaWwobm9kZSwgYCR7bm9kZS50eXBlfSBjaGlsZCBzaGFwZWApXG4gICAgfVxuICAgIHRoaXMuc2hhcGUobm9kZSwgcGFydHMubGVuZ3RoID09IDAgPyBbXSA6IFtub2RlLnRleHRdKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgZXhhY3RseSBvbmUgcGFyc2VyIGNoaWxkIGNhcnJ5aW5nIGEgcmVxdWVzdGVkIGZpZWxkIG5hbWUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSBGaWVsZCBvd25lci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgRmllbGQgbmFtZS5cbiAgICogQHJldHVybnMge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IFNvbGUgZmllbGQgbm9kZS5cbiAgICovXG4gIGZpZWxkKG5vZGUsIG5hbWUpIHtcbiAgICBjb25zdCBtYXRjaGVzID0gW11cblxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBub2RlLmNoaWxkQ291bnQ7IGluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IGNoaWxkID0gbm9kZS5jaGlsZChpbmRleClcblxuICAgICAgaWYgKCFjaGlsZCkgdGhyb3cgbmV3IEVycm9yKGBUcmVlLXNpdHRlciBvbWl0dGVkIGNoaWxkICR7aW5kZXh9IG9mICR7bm9kZS50eXBlfS5gKVxuICAgICAgaWYgKG5vZGUuZmllbGROYW1lRm9yQ2hpbGQoaW5kZXgpID09IG5hbWUpIG1hdGNoZXMucHVzaChjaGlsZClcbiAgICB9XG4gICAgaWYgKG1hdGNoZXMubGVuZ3RoICE9IDEpIHRoaXMuZmFpbChub2RlLCBgZXhwZWN0ZWQgb25lICcke25hbWV9JyBmaWVsZGApXG4gICAgcmV0dXJuIG1hdGNoZXNbMF1cbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYW5kIHJldHVybnMgYSBzb3VyY2UgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIElkZW50aWZpZXIgdG9rZW4uXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2FsbG93TWFpbl0gV2hldGhlciBmaXhlZCBtYWluIGlzIGV4cGVjdGVkLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFthbGxvd1ByaW50XSBXaGV0aGVyIGZpeGVkIHByaW50IGlzIGV4cGVjdGVkLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBBY2NlcHRlZCBuYW1lLlxuICAgKi9cbiAgaWRlbnRpZmllcihub2RlLCBhbGxvd01haW4gPSBmYWxzZSwgYWxsb3dQcmludCA9IGZhbHNlKSB7XG4gICAgY29uc3QgbmFtZSA9IG5vZGUudGV4dFxuXG4gICAgaWYgKG5vZGUudHlwZSAhPSBcImlkZW50aWZpZXJcIiB8fCAhKGFsbG93TWFpbiAmJiBuYW1lID09IFwibWFpblwiKSAmJiAhKGFsbG93UHJpbnQgJiYgbmFtZSA9PSBcInByaW50XCIpICYmXG4gICAgICAhaXNEYXJ0SWRlbnRpZmllcihuYW1lKSkgdGhpcy5mYWlsKG5vZGUsIFwicmVzZXJ2ZWQgb3IgdW5zdXBwb3J0ZWQgaWRlbnRpZmllclwiKVxuICAgIHJldHVybiBuYW1lXG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgb25lIGV4cGxpY2l0bHkgbmFtZWQgc2NhbGFyIHR5cGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSBUeXBlIG5vZGUuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UeXBlUmVmZXJlbmNlfSBTY2FsYXIgdHlwZS5cbiAgICovXG4gIHNjYWxhclR5cGUobm9kZSkge1xuICAgIGlmIChub2RlLnR5cGUgIT0gXCJ0eXBlX2lkZW50aWZpZXJcIiB8fCB0aGlzLnBhcnRzKG5vZGUpLmxlbmd0aCAhPSAwKSB0aGlzLmZhaWwobm9kZSwgXCJzY2FsYXIgdHlwZSBzaGFwZVwiKVxuICAgIGNvbnN0IHR5cGUgPSBzb3VyY2VTY2FsYXJUeXBlKFwiZGFydFwiLCBub2RlLnRleHQsIHRoaXMubG9jYXRpb24obm9kZSkpXG5cbiAgICBpZiAoIXR5cGUpIHRoaXMuZmFpbChub2RlLCBgdW5zdXBwb3J0ZWQgc2NhbGFyIHR5cGUgJyR7bm9kZS50ZXh0fSdgKVxuICAgIHJldHVybiB0eXBlXG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgb25lIGV4cGxpY2l0IHNjYWxhciBvciB2b2lkIHJlc3VsdCB0eXBlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IG5vZGUgUmV0dXJuIHR5cGUgbm9kZS5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljRnVuY3Rpb25SZXR1cm5UeXBlfSBGdW5jdGlvbiByZXR1cm4gdHlwZS5cbiAgICovXG4gIHJldHVyblR5cGUobm9kZSkge1xuICAgIGlmIChub2RlLnR5cGUgPT0gXCJ2b2lkX3R5cGVcIikge1xuICAgICAgY29uc3QgcGFydHMgPSB0aGlzLnBhcnRzKG5vZGUpXG5cbiAgICAgIGlmIChub2RlLnRleHQgIT0gXCJ2b2lkXCIgfHwgcGFydHMubGVuZ3RoID4gMSB8fCBwYXJ0cy5sZW5ndGggPT0gMSAmJiBwYXJ0c1swXS50ZXh0ICE9IFwidm9pZFwiKSB7XG4gICAgICAgIHRoaXMuZmFpbChub2RlLCBcInZvaWQgdHlwZSBzaGFwZVwiKVxuICAgICAgfVxuICAgICAgdGhpcy5zaGFwZShub2RlLCBwYXJ0cylcbiAgICAgIGNvbnN0IHR5cGUgPSB7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiVHlwZVJlZmVyZW5jZVwiKSwgbmFtZTogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwidm9pZFwiKX1cblxuICAgICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXModHlwZSwge3R5cGU6IHRoaXMubG9jYXRpb24obm9kZSl9KVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zY2FsYXJUeXBlKG5vZGUpXG4gIH1cblxuICAvKipcbiAgICogRGVjb2RlcyBvbmUgb3JkaW5hcnkgbm9uaW50ZXJwb2xhdGVkLCBub24tcmF3LCBzaW5nbGUtbGluZSBEYXJ0IHN0cmluZy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIFN0cmluZyBub2RlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBEZWNvZGVkIFVuaWNvZGUgc2NhbGFyIHZhbHVlLlxuICAgKi9cbiAgc3RyaW5nKG5vZGUpIHtcbiAgICBjb25zdCBwYXJ0cyA9IHRoaXMucGFydHMobm9kZSlcbiAgICBjb25zdCBkZWxpbWl0ZXIgPSBub2RlLnRleHRbMF1cblxuICAgIGlmIChub2RlLnR5cGUgIT0gXCJzdHJpbmdfbGl0ZXJhbFwiIHx8ICFbXCJcXFwiXCIsIFwiJ1wiXS5pbmNsdWRlcyhkZWxpbWl0ZXIpIHx8IG5vZGUudGV4dC5zdGFydHNXaXRoKGRlbGltaXRlci5yZXBlYXQoMykpIHx8XG4gICAgICBub2RlLnRleHQuYXQoLTEpICE9IGRlbGltaXRlciB8fCBwYXJ0cy5sZW5ndGggPCAyIHx8IHBhcnRzWzBdLnRleHQgIT0gZGVsaW1pdGVyIHx8IHBhcnRzLmF0KC0xKT8udGV4dCAhPSBkZWxpbWl0ZXIgfHxcbiAgICAgIHBhcnRzLnNsaWNlKDEsIC0xKS5zb21lKCh7dHlwZX0pID0+IHR5cGUgIT0gXCJlc2NhcGVfc2VxdWVuY2VcIikpIHtcbiAgICAgIHRoaXMuZmFpbChub2RlLCBcIm9yZGluYXJ5IG5vbmludGVycG9sYXRlZCBzdHJpbmcgbGl0ZXJhbCByZXF1aXJlZFwiKVxuICAgIH1cbiAgICB0aGlzLnNoYXBlKG5vZGUsIHBhcnRzKVxuICAgIGNvbnN0IHNvdXJjZSA9IG5vZGUudGV4dC5zbGljZSgxLCAtMSlcbiAgICBjb25zdCBzaW1wbGVFc2NhcGVzID0gbmV3IE1hcChbXG4gICAgICBbXCJiXCIsIFwiXFxiXCJdLCBbXCJmXCIsIFwiXFxmXCJdLCBbXCJuXCIsIFwiXFxuXCJdLCBbXCJyXCIsIFwiXFxyXCJdLCBbXCJ0XCIsIFwiXFx0XCJdLCBbXCJ2XCIsIFwiXFx2XCJdLFxuICAgICAgW1wiJFwiLCBcIiRcIl0sIFtcIidcIiwgXCInXCJdLCBbJ1wiJywgJ1wiJ10sIFtcIlxcXFxcIiwgXCJcXFxcXCJdXG4gICAgXSlcbiAgICBsZXQgdmFsdWUgPSBcIlwiXG5cbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgc291cmNlLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3QgY2hhcmFjdGVyID0gc291cmNlW2luZGV4XVxuXG4gICAgICBpZiAoY2hhcmFjdGVyICE9IFwiXFxcXFwiKSB7XG4gICAgICAgIGlmIChjaGFyYWN0ZXIgPT0gXCJcXG5cIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXHJcIiB8fCBjaGFyYWN0ZXIgPT0gZGVsaW1pdGVyIHx8IGNoYXJhY3RlciA9PSBcIiRcIikge1xuICAgICAgICAgIHRoaXMuZmFpbChub2RlLCBcImludmFsaWQgb3IgaW50ZXJwb2xhdGVkIHN0cmluZyBjb250ZW50XCIpXG4gICAgICAgIH1cbiAgICAgICAgdmFsdWUgKz0gY2hhcmFjdGVyXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb25zdCBlc2NhcGVkID0gc291cmNlWysraW5kZXhdXG5cbiAgICAgIGlmIChzaW1wbGVFc2NhcGVzLmhhcyhlc2NhcGVkKSkgdmFsdWUgKz0gc2ltcGxlRXNjYXBlcy5nZXQoZXNjYXBlZClcbiAgICAgIGVsc2UgaWYgKGVzY2FwZWQgPT0gXCJ4XCIpIHtcbiAgICAgICAgY29uc3QgaGV4YWRlY2ltYWwgPSBzb3VyY2Uuc2xpY2UoaW5kZXggKyAxLCBpbmRleCArIDMpXG5cbiAgICAgICAgaWYgKCEvXlswLTlBLUZhLWZdezJ9JC91LnRlc3QoaGV4YWRlY2ltYWwpKSB0aGlzLmZhaWwobm9kZSwgXCJ1bnN1cHBvcnRlZCBzdHJpbmcgZXNjYXBlXCIpXG4gICAgICAgIHZhbHVlICs9IFN0cmluZy5mcm9tQ29kZVBvaW50KE51bWJlci5wYXJzZUludChoZXhhZGVjaW1hbCwgMTYpKVxuICAgICAgICBpbmRleCArPSAyXG4gICAgICB9IGVsc2UgaWYgKGVzY2FwZWQgPT0gXCJ1XCIpIHtcbiAgICAgICAgaWYgKHNvdXJjZVtpbmRleCArIDFdID09IFwie1wiKSB7XG4gICAgICAgICAgY29uc3QgY2xvc2luZyA9IHNvdXJjZS5pbmRleE9mKFwifVwiLCBpbmRleCArIDIpXG4gICAgICAgICAgY29uc3QgaGV4YWRlY2ltYWwgPSBjbG9zaW5nIDwgMCA/IFwiXCIgOiBzb3VyY2Uuc2xpY2UoaW5kZXggKyAyLCBjbG9zaW5nKVxuICAgICAgICAgIGNvbnN0IGNvZGVQb2ludCA9IC9eWzAtOUEtRmEtZl17MSw2fSQvdS50ZXN0KGhleGFkZWNpbWFsKSA/IE51bWJlci5wYXJzZUludChoZXhhZGVjaW1hbCwgMTYpIDogLTFcblxuICAgICAgICAgIGlmIChjb2RlUG9pbnQgPCAwIHx8IGNvZGVQb2ludCA+IDB4MTBGRkZGKSB0aGlzLmZhaWwobm9kZSwgXCJ1bnN1cHBvcnRlZCBzdHJpbmcgZXNjYXBlXCIpXG4gICAgICAgICAgdmFsdWUgKz0gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZVBvaW50KVxuICAgICAgICAgIGluZGV4ID0gY2xvc2luZ1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IGhleGFkZWNpbWFsID0gc291cmNlLnNsaWNlKGluZGV4ICsgMSwgaW5kZXggKyA1KVxuXG4gICAgICAgICAgaWYgKCEvXlswLTlBLUZhLWZdezR9JC91LnRlc3QoaGV4YWRlY2ltYWwpKSB0aGlzLmZhaWwobm9kZSwgXCJ1bnN1cHBvcnRlZCBzdHJpbmcgZXNjYXBlXCIpXG4gICAgICAgICAgdmFsdWUgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShOdW1iZXIucGFyc2VJbnQoaGV4YWRlY2ltYWwsIDE2KSlcbiAgICAgICAgICBpbmRleCArPSA0XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB0aGlzLmZhaWwobm9kZSwgXCJ1bnN1cHBvcnRlZCBzdHJpbmcgZXNjYXBlXCIpXG4gICAgfVxuICAgIGlmICghaGFzT25seVVuaWNvZGVTY2FsYXJzKHZhbHVlKSkgdGhpcy5mYWlsKG5vZGUsIFwiaW52YWxpZCBVbmljb2RlIHN0cmluZyBsaXRlcmFsXCIpXG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cblxuICAvKipcbiAgICogRXh0cmFjdHMgZXhhY3QgcmVxdWlyZWQgcG9zaXRpb25hbCBhcmd1bWVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gcGFydCBDYWxsIGFyZ3VtZW50IHBhcnQuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlW11bXX0gQXJndW1lbnQgZXhwcmVzc2lvbiBlZGdlcy5cbiAgICovXG4gIGFyZ3VtZW50cyhwYXJ0KSB7XG4gICAgY29uc3QgcGFydENoaWxkcmVuID0gdGhpcy5wYXJ0cyhwYXJ0KVxuXG4gICAgaWYgKHBhcnQudHlwZSAhPSBcImFyZ3VtZW50X3BhcnRcIiB8fCBwYXJ0Q2hpbGRyZW4ubGVuZ3RoICE9IDEgfHwgcGFydENoaWxkcmVuWzBdLnR5cGUgIT0gXCJhcmd1bWVudHNcIikge1xuICAgICAgdGhpcy5mYWlsKHBhcnQsIFwiY2FsbCBhcmd1bWVudCBwYXJ0IHNoYXBlXCIpXG4gICAgfVxuICAgIHRoaXMuc2hhcGUocGFydCwgW3BhcnRDaGlsZHJlblswXV0pXG4gICAgY29uc3QgbGlzdCA9IHBhcnRDaGlsZHJlblswXVxuICAgIGNvbnN0IGxpc3RQYXJ0cyA9IHRoaXMucGFydHMobGlzdClcblxuICAgIGlmIChsaXN0UGFydHMubGVuZ3RoIDwgMiB8fCBsaXN0UGFydHNbMF0udGV4dCAhPSBcIihcIiB8fCBsaXN0UGFydHMuYXQoLTEpPy50ZXh0ICE9IFwiKVwiKSB7XG4gICAgICB0aGlzLmZhaWwobGlzdCwgXCJjYWxsIGFyZ3VtZW50IGxpc3Qgc2hhcGVcIilcbiAgICB9XG4gICAgY29uc3QgaW50ZXJpb3IgPSBsaXN0UGFydHMuc2xpY2UoMSwgLTEpXG4gICAgY29uc3QgaGFzR2VuZXJhdGVkVHJhaWxpbmdDb21tYSA9IHRoaXMucnVudGltZSAmJiBpbnRlcmlvci5hdCgtMSk/LnRleHQgPT0gXCIsXCJcbiAgICBjb25zdCBhcmd1bWVudFBhcnRzID0gaGFzR2VuZXJhdGVkVHJhaWxpbmdDb21tYSA/IGludGVyaW9yLnNsaWNlKDAsIC0xKSA6IGludGVyaW9yXG4gICAgY29uc3QgYXJndW1lbnRzXyA9IGFyZ3VtZW50UGFydHMuZmlsdGVyKChfY2hpbGQsIGluZGV4KSA9PiBpbmRleCAlIDIgPT0gMClcblxuICAgIHRoaXMuc2hhcGUobGlzdCwgW1wiKFwiLCAuLi5hcmd1bWVudHNfLmZsYXRNYXAoKGFyZ3VtZW50LCBpbmRleCkgPT4gaW5kZXggPyBbXCIsXCIsIGFyZ3VtZW50XSA6IFthcmd1bWVudF0pLFxuICAgICAgLi4uKGhhc0dlbmVyYXRlZFRyYWlsaW5nQ29tbWEgPyBbXCIsXCJdIDogW10pLCBcIilcIl0pXG4gICAgcmV0dXJuIGFyZ3VtZW50c18ubWFwKChhcmd1bWVudCkgPT4ge1xuICAgICAgaWYgKGFyZ3VtZW50LnR5cGUgIT0gXCJhcmd1bWVudFwiKSB0aGlzLmZhaWwoYXJndW1lbnQsIFwicmVxdWlyZWQgcG9zaXRpb25hbCBhcmd1bWVudFwiKVxuICAgICAgY29uc3QgZXhwcmVzc2lvblBhcnRzID0gdGhpcy5wYXJ0cyhhcmd1bWVudClcblxuICAgICAgaWYgKGV4cHJlc3Npb25QYXJ0cy5sZW5ndGggPT0gMCkgdGhpcy5mYWlsKGFyZ3VtZW50LCBcImVtcHR5IGFyZ3VtZW50XCIpXG4gICAgICByZXR1cm4gZXhwcmVzc2lvblBhcnRzXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBvbmUgZGlyZWN0IG1ldGhvZC1pbnZvY2F0aW9uIG5vZGUgd2hvc2UgZnVuY3Rpb24gaXMgYSBwbGFpbiBpZGVudGlmaWVyLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGVbXX0gbm9kZXMgRXhhY3Qgb25lLW5vZGUgY2FsbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBvd25lciBFeHByZXNzaW9uIG93bmVyLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFthbGxvd1ByaW50XSBXaGV0aGVyIHRoaXMgaXMgdGhlIHByaW50IHNjYWZmb2xkLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gU2VtYW50aWMgY2FsbCBvciBwcml2YXRlIGdlbmVyYXRlZCBvcGVyYXRpb24uXG4gICAqL1xuICBjYWxsKG5vZGVzLCBvd25lciwgYWxsb3dQcmludCA9IGZhbHNlKSB7XG4gICAgaWYgKG5vZGVzLmxlbmd0aCAhPSAxIHx8IG5vZGVzWzBdLnR5cGUgIT0gXCJtZXRob2RfaW52b2NhdGlvblwiKSB7XG4gICAgICB0aGlzLmZhaWwobm9kZXNbMF0gPz8gb3duZXIsIFwiZGlyZWN0IGNhbGwgc2hhcGVcIilcbiAgICB9XG4gICAgY29uc3QgaW52b2NhdGlvbiA9IG5vZGVzWzBdXG4gICAgY29uc3QgcGFydHMgPSB0aGlzLnBhcnRzKGludm9jYXRpb24pXG4gICAgY29uc3QgZnVuY3Rpb25Ob2RlID0gdGhpcy5maWVsZChpbnZvY2F0aW9uLCBcImZ1bmN0aW9uXCIpXG4gICAgY29uc3QgYXJndW1lbnRQYXJ0ID0gdGhpcy5maWVsZChpbnZvY2F0aW9uLCBcImFyZ3VtZW50c1wiKVxuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCAhPSAyIHx8IHBhcnRzWzBdLmlkICE9IGZ1bmN0aW9uTm9kZS5pZCB8fCBmdW5jdGlvbk5vZGUudHlwZSAhPSBcImlkZW50aWZpZXJcIiB8fFxuICAgICAgcGFydHNbMV0uaWQgIT0gYXJndW1lbnRQYXJ0LmlkIHx8IGFyZ3VtZW50UGFydC50eXBlICE9IFwiYXJndW1lbnRfcGFydFwiKSB0aGlzLmZhaWwoaW52b2NhdGlvbiwgXCJkaXJlY3QgY2FsbCBzaGFwZVwiKVxuICAgIHRoaXMuc2hhcGUoaW52b2NhdGlvbiwgW2Z1bmN0aW9uTm9kZSwgYXJndW1lbnRQYXJ0XSlcbiAgICBjb25zdCBuYW1lID0gZnVuY3Rpb25Ob2RlLnRleHRcbiAgICBjb25zdCBoZWxwZXIgPSB0aGlzLnJ1bnRpbWUgPyBoZWxwZXJPcGVyYXRpb25zLmdldChuYW1lKSA6IHVuZGVmaW5lZFxuICAgIGNvbnN0IGxvY2F0aW9uID0gdGhpcy5sb2NhdGlvbihpbnZvY2F0aW9uKVxuICAgIGNvbnN0IGFyZ3VtZW50Tm9kZXMgPSB0aGlzLmFyZ3VtZW50cyhhcmd1bWVudFBhcnQpXG5cbiAgICBpZiAodGhpcy5ydW50aW1lICYmIG5hbWUgPT0gXCJfc2VtYW50aWZvbGRCb29sZWFuXCIpIHtcbiAgICAgIGlmIChhcmd1bWVudE5vZGVzLmxlbmd0aCAhPSAxKSB0aGlzLmZhaWwoYXJndW1lbnRQYXJ0LCBcIkRhcnQgQm9vbGVhbiBsaXRlcmFsIGhlbHBlciBzaGFwZVwiKVxuICAgICAgY29uc3QgbGl0ZXJhbCA9IHRoaXMuZXhwcmVzc2lvbihhcmd1bWVudE5vZGVzWzBdLCBvd25lcilcblxuICAgICAgaWYgKGxpdGVyYWwua2luZCAhPSBcIkJvb2xlYW5MaXRlcmFsXCIpIHRoaXMuZmFpbChhcmd1bWVudFBhcnQsIFwiRGFydCBCb29sZWFuIGxpdGVyYWwgaGVscGVyIHNoYXBlXCIpXG4gICAgICByZXR1cm4gbGl0ZXJhbFxuICAgIH1cbiAgICBpZiAoaGVscGVyKSB7XG4gICAgICBjb25zdCBjb3VudCA9IGhlbHBlciA9PSBcIk5lZ2F0ZVwiID8gMSA6IDJcblxuICAgICAgaWYgKGFyZ3VtZW50Tm9kZXMubGVuZ3RoICE9IGNvdW50KSB0aGlzLmZhaWwoYXJndW1lbnRQYXJ0LCBcIkRhcnQgY2hlY2tlZC1pbnRlZ2VyIGhlbHBlciBzaGFwZVwiKVxuICAgICAgaWYgKGhlbHBlciA9PSBcIk5lZ2F0ZVwiKSB7XG4gICAgICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChcbiAgICAgICAgICB3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgICAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlVuYXJ5RXhwcmVzc2lvblwiKSwgbG9jYXRpb24sXG4gICAgICAgICAgICBvcGVyYW5kOiB0aGlzLmV4cHJlc3Npb24oYXJndW1lbnROb2Rlc1swXSwgb3duZXIpXG4gICAgICAgICAgfSwge29wZXJhdG9yOiB0aGlzLmxvY2F0aW9uKGZ1bmN0aW9uTm9kZSl9KSwgaGVscGVyKSkpXG4gICAgICB9XG4gICAgICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoXG4gICAgICAgIHdpdGhBZGFwdGVkT3BlcmF0aW9uKHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkJpbmFyeUV4cHJlc3Npb25cIiksIGxlZnQ6IHRoaXMuZXhwcmVzc2lvbihhcmd1bWVudE5vZGVzWzBdLCBvd25lciksIGxvY2F0aW9uLFxuICAgICAgICAgIHJpZ2h0OiB0aGlzLmV4cHJlc3Npb24oYXJndW1lbnROb2Rlc1sxXSwgb3duZXIpXG4gICAgICAgIH0sIHtvcGVyYXRvcjogdGhpcy5sb2NhdGlvbihmdW5jdGlvbk5vZGUpfSksIGhlbHBlcikpKVxuICAgIH1cbiAgICB0aGlzLmlkZW50aWZpZXIoZnVuY3Rpb25Ob2RlLCBmYWxzZSwgYWxsb3dQcmludClcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGFyZ3VtZW50czogYXJndW1lbnROb2Rlcy5tYXAoKGFyZ3VtZW50KSA9PiB0aGlzLmV4cHJlc3Npb24oYXJndW1lbnQsIG93bmVyKSksXG4gICAgICBjYWxsZWU6IG5hbWUsXG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJDYWxsRXhwcmVzc2lvblwiKSxcbiAgICAgIGxvY2F0aW9uXG4gICAgfSwge2NhbGxlZTogdGhpcy5sb2NhdGlvbihmdW5jdGlvbk5vZGUpfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWN1cnNpdmVseSBjb21wYXJlcyBvbmUgc291cmNlIHN1cHBvcnQgc3VidHJlZSB3aXRoIHRoZSBjYW5vbmljYWwgcnVudGltZSBDU1QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gYWN0dWFsIFNvdXJjZSBub2RlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IGV4cGVjdGVkIENhbm9uaWNhbCBub2RlLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGNvbXBhcmVUcmVlKGFjdHVhbCwgZXhwZWN0ZWQpIHtcbiAgICBpZiAoYWN0dWFsLnR5cGUgIT0gZXhwZWN0ZWQudHlwZSB8fCBhY3R1YWwuaXNOYW1lZCAhPSBleHBlY3RlZC5pc05hbWVkIHx8IGFjdHVhbC5pc0V4dHJhICE9IGV4cGVjdGVkLmlzRXh0cmEgfHxcbiAgICAgIGFjdHVhbC5jaGlsZENvdW50ICE9IGV4cGVjdGVkLmNoaWxkQ291bnQpIHRoaXMuZmFpbChhY3R1YWwsIFwibW9kaWZpZWQgRGFydCBzdXBwb3J0IG5vZGVcIilcbiAgICBpZiAoYWN0dWFsLmNoaWxkQ291bnQgPT0gMCAmJiBhY3R1YWwudGV4dCAhPSBleHBlY3RlZC50ZXh0KSB0aGlzLmZhaWwoYWN0dWFsLCBcIm1vZGlmaWVkIERhcnQgc3VwcG9ydCB0b2tlblwiKVxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBhY3R1YWwuY2hpbGRDb3VudDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3QgbGVmdCA9IGFjdHVhbC5jaGlsZChpbmRleClcbiAgICAgIGNvbnN0IHJpZ2h0ID0gZXhwZWN0ZWQuY2hpbGQoaW5kZXgpXG5cbiAgICAgIGlmICghbGVmdCB8fCAhcmlnaHQgfHwgYWN0dWFsLmZpZWxkTmFtZUZvckNoaWxkKGluZGV4KSAhPSBleHBlY3RlZC5maWVsZE5hbWVGb3JDaGlsZChpbmRleCkpIHtcbiAgICAgICAgdGhpcy5mYWlsKGxlZnQgPz8gYWN0dWFsLCBcIm1vZGlmaWVkIERhcnQgc3VwcG9ydCBmaWVsZFwiKVxuICAgICAgfVxuICAgICAgdGhpcy5jb21wYXJlVHJlZShsZWZ0LCByaWdodClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYW4gZXhwcmVzc2lvbiByZXByZXNlbnRlZCBieSBvbmUgb3IgbW9yZSBhZGphY2VudCBEYXJ0IENTVCBub2Rlcy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlW119IG5vZGVzIEV4cHJlc3Npb24gbm9kZXMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gb3duZXIgT3duaW5nIG5vZGUuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSBTZW1hbnRpYyBleHByZXNzaW9uLlxuICAgKi9cbiAgZXhwcmVzc2lvbihub2Rlcywgb3duZXIpIHtcbiAgICBpZiAobm9kZXMubGVuZ3RoID09IDEgJiYgbm9kZXNbMF0udHlwZSA9PSBcIm1ldGhvZF9pbnZvY2F0aW9uXCIpIHJldHVybiB0aGlzLmNhbGwobm9kZXMsIG93bmVyKVxuICAgIGlmIChub2Rlcy5sZW5ndGggIT0gMSkgcmV0dXJuIHRoaXMuZmFpbChub2Rlc1swXSA/PyBvd25lciwgXCJzY2FsYXIgZXhwcmVzc2lvbiBzaGFwZVwiKVxuICAgIGNvbnN0IG5vZGUgPSBub2Rlc1swXVxuICAgIGNvbnN0IGxvY2F0aW9uID0gdGhpcy5sb2NhdGlvbihub2RlKVxuXG4gICAgaWYgKG5vZGUudHlwZSA9PSBcImlkZW50aWZpZXJcIikge1xuICAgICAgY29uc3QgbmFtZSA9IHRoaXMuaWRlbnRpZmllcihub2RlKVxuXG4gICAgICBpZiAodGhpcy5mdW5jdGlvbk5hbWVzLmhhcyhuYW1lKSkgdGhpcy5mYWlsKG5vZGUsIFwiZnVuY3Rpb24gdGVhci1vZmZcIilcbiAgICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJJZGVudGlmaWVyRXhwcmVzc2lvblwiKSwgbG9jYXRpb24sIG5hbWV9LCB7bmFtZTogbG9jYXRpb259KVxuICAgIH1cbiAgICBpZiAobm9kZS50eXBlID09IFwiZGVjaW1hbF9pbnRlZ2VyX2xpdGVyYWxcIikge1xuICAgICAgaWYgKHRoaXMucGFydHMobm9kZSkubGVuZ3RoICE9IDAgfHwgIS9eKD86MHxbMS05XVswLTldKikkL3UudGVzdChub2RlLnRleHQpKSB0aGlzLmZhaWwobm9kZSwgXCJub25jYW5vbmljYWwgaW50ZWdlciBsaXRlcmFsXCIpXG4gICAgICBjb25zdCB2YWx1ZSA9IE51bWJlcihCaWdJbnQobm9kZS50ZXh0KSlcblxuICAgICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcih2YWx1ZSkpIHRoaXMuZmFpbChub2RlLCBcIm5vbi1zYWZlIGludGVnZXIgbGl0ZXJhbFwiKVxuICAgICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkludGVnZXJMaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWV9LCB7bGl0ZXJhbDogbG9jYXRpb259KVxuICAgIH1cbiAgICBpZiAobm9kZS50eXBlID09IFwidHJ1ZVwiIHx8IG5vZGUudHlwZSA9PSBcImZhbHNlXCIpIHtcbiAgICAgIHRoaXMuc2hhcGUobm9kZSwgW25vZGUudHlwZV0pXG4gICAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQm9vbGVhbkxpdGVyYWxcIiksIGxvY2F0aW9uLCB2YWx1ZTogbm9kZS50eXBlID09IFwidHJ1ZVwifSwge2xpdGVyYWw6IGxvY2F0aW9ufSlcbiAgICB9XG4gICAgaWYgKG5vZGUudHlwZSA9PSBcInN0cmluZ19saXRlcmFsXCIpIHtcbiAgICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJTdHJpbmdMaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IHRoaXMuc3RyaW5nKG5vZGUpfSwge2xpdGVyYWw6IGxvY2F0aW9ufSlcbiAgICB9XG4gICAgaWYgKG5vZGUudHlwZSA9PSBcInBhcmVudGhlc2l6ZWRfZXhwcmVzc2lvblwiKSB7XG4gICAgICBjb25zdCBwYXJ0cyA9IHRoaXMucGFydHMobm9kZSlcblxuICAgICAgaWYgKHBhcnRzLmxlbmd0aCA8IDMgfHwgcGFydHNbMF0udGV4dCAhPSBcIihcIiB8fCBwYXJ0cy5hdCgtMSk/LnRleHQgIT0gXCIpXCIpIHRoaXMuZmFpbChub2RlLCBcInBhcmVudGhlc2l6ZWQgZXhwcmVzc2lvbiBzaGFwZVwiKVxuICAgICAgdGhpcy5zaGFwZShub2RlLCBbXCIoXCIsIC4uLnBhcnRzLnNsaWNlKDEsIC0xKSwgXCIpXCJdKVxuICAgICAgcmV0dXJuIHRoaXMuZXhwcmVzc2lvbihwYXJ0cy5zbGljZSgxLCAtMSksIG5vZGUpXG4gICAgfVxuICAgIGlmIChub2RlLnR5cGUgPT0gXCJ1bmFyeV9leHByZXNzaW9uXCIpIHtcbiAgICAgIGNvbnN0IHBhcnRzID0gdGhpcy5wYXJ0cyhub2RlKVxuICAgICAgY29uc3Qgb3BlcmF0b3IgPSBwYXJ0c1swXVxuXG4gICAgICBpZiAocGFydHMubGVuZ3RoIDwgMiB8fCBvcGVyYXRvci50eXBlICE9IFwicHJlZml4X29wZXJhdG9yXCIgfHwgIVtcIi1cIiwgXCIhXCJdLmluY2x1ZGVzKG9wZXJhdG9yLnRleHQpKSB7XG4gICAgICAgIHRoaXMuZmFpbChub2RlLCBcInVuYXJ5IG9wZXJhdG9yXCIpXG4gICAgICB9XG4gICAgICBjb25zdCBvcGVyYXRvclBhcnRzID0gdGhpcy5wYXJ0cyhvcGVyYXRvcilcblxuICAgICAgaWYgKG9wZXJhdG9yUGFydHMubGVuZ3RoICE9IDEgfHwgb3BlcmF0b3JQYXJ0c1swXS50ZXh0ICE9IG9wZXJhdG9yLnRleHQgfHxcbiAgICAgICAgIVtcIm1pbnVzX29wZXJhdG9yXCIsIFwibmVnYXRpb25fb3BlcmF0b3JcIl0uaW5jbHVkZXMob3BlcmF0b3JQYXJ0c1swXS50eXBlKSkgdGhpcy5mYWlsKG9wZXJhdG9yLCBcInVuYXJ5IG9wZXJhdG9yIHNoYXBlXCIpXG4gICAgICB0aGlzLm9wZXJhdG9yU2hhcGUob3BlcmF0b3JQYXJ0c1swXSlcbiAgICAgIHRoaXMuc2hhcGUobm9kZSwgW29wZXJhdG9yLCAuLi5wYXJ0cy5zbGljZSgxKV0pXG4gICAgICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAod2l0aEFkYXB0ZWRPcGVyYXRpb24od2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlVuYXJ5RXhwcmVzc2lvblwiKSxcbiAgICAgICAgbG9jYXRpb24sXG4gICAgICAgIG9wZXJhbmQ6IHRoaXMuZXhwcmVzc2lvbihwYXJ0cy5zbGljZSgxKSwgbm9kZSlcbiAgICAgIH0sIHtvcGVyYXRvcjogdGhpcy5sb2NhdGlvbihvcGVyYXRvcil9KSwgb3BlcmF0b3IudGV4dCA9PSBcIi1cIiA/IFwiTmVnYXRlXCIgOiBcIk5vdFwiKSkpXG4gICAgfVxuICAgIGlmIChiaW5hcnlOb2RlT3BlcmF0b3JzLmhhcyhub2RlLnR5cGUpKSByZXR1cm4gdGhpcy5iaW5hcnkobm9kZSlcbiAgICByZXR1cm4gdGhpcy5mYWlsKG5vZGUpXG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYSBib3VuZGVkIGJpbmFyeSBleHByZXNzaW9uIHRyZWUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSBCaW5hcnkgZXhwcmVzc2lvbiBub2RlLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gU2VtYW50aWMgYmluYXJ5IGV4cHJlc3Npb24uXG4gICAqL1xuICBiaW5hcnkobm9kZSkge1xuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZVtdW119ICovXG4gICAgY29uc3Qgb3BlcmFuZHMgPSBbXVxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZVtdfSAqL1xuICAgIGNvbnN0IG9wZXJhdG9ycyA9IFtdXG4gICAgbGV0IGN1cnJlbnQgPSBub2RlXG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgcGFydHMgPSB0aGlzLnBhcnRzKGN1cnJlbnQpXG4gICAgICBjb25zdCBkZWNsYXJhdGlvbiA9IGJpbmFyeU5vZGVPcGVyYXRvcnMuZ2V0KGN1cnJlbnQudHlwZSlcbiAgICAgIGNvbnN0IG9wZXJhdG9yVHlwZSA9IGRlY2xhcmF0aW9uPy5bMF1cbiAgICAgIGNvbnN0IGFjY2VwdGVkID0gZGVjbGFyYXRpb24/LlsxXVxuICAgICAgY29uc3Qgb3BlcmF0b3JJbmRleGVzID0gcGFydHMuZmxhdE1hcCgocGFydCwgaW5kZXgpID0+IHBhcnQudHlwZSA9PSBvcGVyYXRvclR5cGUgPyBbaW5kZXhdIDogW10pXG5cbiAgICAgIGlmIChvcGVyYXRvckluZGV4ZXMubGVuZ3RoICE9IDEpIHRoaXMuZmFpbChjdXJyZW50LCBgJHtjdXJyZW50LnR5cGV9IGNoaWxkIHNoYXBlYClcbiAgICAgIGNvbnN0IG9wZXJhdG9ySW5kZXggPSBvcGVyYXRvckluZGV4ZXNbMF1cbiAgICAgIGNvbnN0IG9wZXJhdG9yID0gcGFydHNbb3BlcmF0b3JJbmRleF1cblxuICAgICAgaWYgKG9wZXJhdG9ySW5kZXggPT0gMCB8fCBvcGVyYXRvckluZGV4ID09IHBhcnRzLmxlbmd0aCAtIDEgfHwgIWFjY2VwdGVkPy5oYXMob3BlcmF0b3IudGV4dCkgfHxcbiAgICAgICAgIWJpbmFyeU9wZXJhdGlvbnMuaGFzKG9wZXJhdG9yLnRleHQpKSB0aGlzLmZhaWwob3BlcmF0b3IsIFwidW5zdXBwb3J0ZWQgYmluYXJ5IG9wZXJhdG9yXCIpXG4gICAgICB0aGlzLm9wZXJhdG9yU2hhcGUob3BlcmF0b3IpXG4gICAgICB0aGlzLnNoYXBlKGN1cnJlbnQsIHBhcnRzKVxuICAgICAgb3BlcmFuZHMucHVzaChwYXJ0cy5zbGljZSgwLCBvcGVyYXRvckluZGV4KSlcbiAgICAgIG9wZXJhdG9ycy5wdXNoKG9wZXJhdG9yKVxuICAgICAgY29uc3QgcmlnaHQgPSBwYXJ0cy5zbGljZShvcGVyYXRvckluZGV4ICsgMSlcblxuICAgICAgaWYgKHJpZ2h0Lmxlbmd0aCA9PSAxICYmIHJpZ2h0WzBdLnR5cGUgPT0gbm9kZS50eXBlKSBjdXJyZW50ID0gcmlnaHRbMF1cbiAgICAgIGVsc2Uge1xuICAgICAgICBvcGVyYW5kcy5wdXNoKHJpZ2h0KVxuICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cbiAgICBsZXQgZXhwcmVzc2lvbiA9IHRoaXMuZXhwcmVzc2lvbihvcGVyYW5kc1swXSwgbm9kZSlcblxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBvcGVyYXRvcnMubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgICBjb25zdCBvcGVyYXRvciA9IG9wZXJhdG9yc1tpbmRleF1cbiAgICAgIGNvbnN0IG9wZXJhdGlvbiA9IGJpbmFyeU9wZXJhdGlvbnMuZ2V0KG9wZXJhdG9yLnRleHQpXG4gICAgICBjb25zdCByaWdodCA9IHRoaXMuZXhwcmVzc2lvbihvcGVyYW5kc1tpbmRleCArIDFdLCBub2RlKVxuICAgICAgY29uc3QgZmlyc3QgPSBvcGVyYW5kc1swXVswXVxuICAgICAgY29uc3QgbGFzdCA9IG9wZXJhbmRzW2luZGV4ICsgMV0uYXQoLTEpXG4gICAgICBjb25zdCBsb2NhdGlvbiA9IGZpcnN0ICYmIGxhc3RcbiAgICAgICAgPyBsb2NhdGlvbkZyb21PZmZzZXRzKHRoaXMuZmlsZW5hbWUsIHRoaXMuc291cmNlLCBiaW5kaW5nSW5kZXhUb1V0ZjE2T2Zmc2V0KHRoaXMuc291cmNlLCBmaXJzdC5zdGFydEluZGV4KSxcbiAgICAgICAgICBiaW5kaW5nSW5kZXhUb1V0ZjE2T2Zmc2V0KHRoaXMuc291cmNlLCBsYXN0LmVuZEluZGV4KSlcbiAgICAgICAgOiB0aGlzLmxvY2F0aW9uKG5vZGUpXG5cbiAgICAgIGV4cHJlc3Npb24gPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICh3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQmluYXJ5RXhwcmVzc2lvblwiKSwgbGVmdDogZXhwcmVzc2lvbiwgbG9jYXRpb24sIHJpZ2h0XG4gICAgICB9LCB7b3BlcmF0b3I6IHRoaXMubG9jYXRpb24ob3BlcmF0b3IpfSksIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvb3BlcmF0b3JzLmpzXCIpLkFkYXB0ZWRPcGVyYXRpb259ICovIChvcGVyYXRpb24pKSlcbiAgICB9XG4gICAgcmV0dXJuIGV4cHJlc3Npb25cbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBvbmUgZXhwbGljaXRseSB0eXBlZCBpbml0aWFsaXplZCBsb2NhbCBkZWNsYXJhdGlvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIExvY2FsIGRlY2xhcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuTG9jYWxEZWNsYXJhdGlvbn0gU2VtYW50aWMgbG9jYWwuXG4gICAqL1xuICBsb2NhbChub2RlKSB7XG4gICAgY29uc3QgZGVjbGFyYXRpb25QYXJ0cyA9IHRoaXMucGFydHMobm9kZSlcblxuICAgIGlmIChub2RlLnR5cGUgIT0gXCJsb2NhbF92YXJpYWJsZV9kZWNsYXJhdGlvblwiIHx8IGRlY2xhcmF0aW9uUGFydHMubGVuZ3RoICE9IDIgfHxcbiAgICAgIGRlY2xhcmF0aW9uUGFydHNbMF0udHlwZSAhPSBcImluaXRpYWxpemVkX3ZhcmlhYmxlX2RlZmluaXRpb25cIiB8fCBkZWNsYXJhdGlvblBhcnRzWzFdLnRleHQgIT0gXCI7XCIpIHtcbiAgICAgIHRoaXMuZmFpbChub2RlLCBcImxvY2FsIGRlY2xhcmF0aW9uIHNoYXBlXCIpXG4gICAgfVxuICAgIHRoaXMuc2hhcGUobm9kZSwgW2RlY2xhcmF0aW9uUGFydHNbMF0sIFwiO1wiXSlcbiAgICBjb25zdCBkZWZpbml0aW9uID0gZGVjbGFyYXRpb25QYXJ0c1swXVxuICAgIGNvbnN0IHBhcnRzID0gdGhpcy5wYXJ0cyhkZWZpbml0aW9uKVxuXG4gICAgaWYgKHBhcnRzWzBdPy50eXBlID09IFwiaW5mZXJyZWRfdHlwZVwiIHx8IHBhcnRzWzBdPy50eXBlID09IFwiZmluYWxfYnVpbHRpblwiICYmIHBhcnRzWzFdPy50eXBlID09IFwiaWRlbnRpZmllclwiKSB7XG4gICAgICByZXR1cm4gbWlzc2luZ1R5cGUoXCJkYXJ0XCIsIFwiTG9jYWxcIiwgdGhpcy5sb2NhdGlvbihkZWZpbml0aW9uKSlcbiAgICB9XG4gICAgY29uc3QgaW1tdXRhYmxlID0gcGFydHNbMF0/LnR5cGUgPT0gXCJmaW5hbF9idWlsdGluXCJcbiAgICBjb25zdCB0eXBlSW5kZXggPSBpbW11dGFibGUgPyAxIDogMFxuICAgIGNvbnN0IHR5cGVOb2RlID0gcGFydHNbdHlwZUluZGV4XVxuICAgIGNvbnN0IG5hbWVOb2RlID0gcGFydHNbdHlwZUluZGV4ICsgMV1cbiAgICBjb25zdCBlcXVhbHMgPSBwYXJ0c1t0eXBlSW5kZXggKyAyXVxuICAgIGNvbnN0IGV4cHJlc3Npb25QYXJ0cyA9IHBhcnRzLnNsaWNlKHR5cGVJbmRleCArIDMpXG5cbiAgICBpZiAocGFydHMubGVuZ3RoIDwgdHlwZUluZGV4ICsgNCB8fCB0eXBlTm9kZT8udHlwZSAhPSBcInR5cGVfaWRlbnRpZmllclwiIHx8IG5hbWVOb2RlPy50eXBlICE9IFwiaWRlbnRpZmllclwiIHx8XG4gICAgICBlcXVhbHM/LnRleHQgIT0gXCI9XCIgfHwgZXhwcmVzc2lvblBhcnRzLmxlbmd0aCA9PSAwIHx8IGltbXV0YWJsZSAmJiBwYXJ0c1swXS50ZXh0ICE9IFwiZmluYWxcIikge1xuICAgICAgdGhpcy5mYWlsKHBhcnRzWzBdID8/IGRlZmluaXRpb24sIFwiZXhwbGljaXRseSB0eXBlZCBpbml0aWFsaXplZCBsb2NhbCByZXF1aXJlZFwiKVxuICAgIH1cbiAgICB0aGlzLnNoYXBlKGRlZmluaXRpb24sIFsuLi4oaW1tdXRhYmxlID8gW3BhcnRzWzBdXSA6IFtdKSwgdHlwZU5vZGUsIG5hbWVOb2RlLCBcIj1cIiwgLi4uZXhwcmVzc2lvblBhcnRzXSlcbiAgICBpZiAodGhpcy5maWVsZChkZWZpbml0aW9uLCBcIm5hbWVcIikuaWQgIT0gbmFtZU5vZGUuaWQpIHRoaXMuZmFpbChuYW1lTm9kZSwgXCJsb2NhbCBuYW1lIGZpZWxkXCIpXG4gICAgY29uc3QgbmFtZSA9IHRoaXMuaWRlbnRpZmllcihuYW1lTm9kZSlcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGluaXRpYWxpemVyOiB0aGlzLmV4cHJlc3Npb24oZXhwcmVzc2lvblBhcnRzLCBkZWZpbml0aW9uKSxcbiAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkxvY2FsRGVjbGFyYXRpb25cIiksXG4gICAgICBsb2NhdGlvbjogdGhpcy5sb2NhdGlvbihub2RlKSxcbiAgICAgIG11dGFibGU6ICFpbW11dGFibGUsXG4gICAgICBuYW1lLFxuICAgICAgdHlwZTogdGhpcy5zY2FsYXJUeXBlKHR5cGVOb2RlKVxuICAgIH0sIHtuYW1lOiB0aGlzLmxvY2F0aW9uKG5hbWVOb2RlKSwgb3BlcmF0b3I6IHRoaXMubG9jYXRpb24oZXF1YWxzKX0pXG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgb25lIHNpbXBsZSBpZGVudGlmaWVyIGFzc2lnbm1lbnQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSBBc3NpZ25tZW50IGV4cHJlc3Npb24uXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Bc3NpZ25tZW50U3RhdGVtZW50fSBTZW1hbnRpYyBhc3NpZ25tZW50LlxuICAgKi9cbiAgYXNzaWdubWVudChub2RlKSB7XG4gICAgY29uc3QgcGFydHMgPSB0aGlzLnBhcnRzKG5vZGUpXG4gICAgY29uc3QgdGFyZ2V0ID0gcGFydHNbMF1cbiAgICBjb25zdCBvcGVyYXRvciA9IHBhcnRzWzFdXG5cbiAgICBpZiAobm9kZS50eXBlICE9IFwiYXNzaWdubWVudF9leHByZXNzaW9uXCIgfHwgcGFydHMubGVuZ3RoIDwgMyB8fCB0YXJnZXQ/LnR5cGUgIT0gXCJhc3NpZ25hYmxlX2V4cHJlc3Npb25cIiB8fFxuICAgICAgb3BlcmF0b3I/LnR5cGUgIT0gXCJhc3NpZ25tZW50X29wZXJhdG9yXCIgfHwgb3BlcmF0b3IudGV4dCAhPSBcIj1cIikgdGhpcy5mYWlsKG5vZGUsIFwic2ltcGxlIGFzc2lnbm1lbnQgc2hhcGVcIilcbiAgICBjb25zdCB0YXJnZXRQYXJ0cyA9IHRoaXMucGFydHModGFyZ2V0KVxuXG4gICAgaWYgKHRhcmdldFBhcnRzLmxlbmd0aCAhPSAxIHx8IHRhcmdldFBhcnRzWzBdLnR5cGUgIT0gXCJpZGVudGlmaWVyXCIpIHRoaXMuZmFpbCh0YXJnZXQsIFwic2ltcGxlIGFzc2lnbm1lbnQgdGFyZ2V0XCIpXG4gICAgdGhpcy5zaGFwZSh0YXJnZXQsIFt0YXJnZXRQYXJ0c1swXV0pXG4gICAgdGhpcy5vcGVyYXRvclNoYXBlKG9wZXJhdG9yKVxuICAgIHRoaXMuc2hhcGUobm9kZSwgW3RhcmdldCwgXCI9XCIsIC4uLnBhcnRzLnNsaWNlKDIpXSlcbiAgICBjb25zdCBuYW1lID0gdGhpcy5pZGVudGlmaWVyKHRhcmdldFBhcnRzWzBdKVxuICAgIGNvbnN0IHRhcmdldExvY2F0aW9uID0gdGhpcy5sb2NhdGlvbih0YXJnZXRQYXJ0c1swXSlcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGV4cHJlc3Npb246IHRoaXMuZXhwcmVzc2lvbihwYXJ0cy5zbGljZSgyKSwgbm9kZSksXG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJBc3NpZ25tZW50U3RhdGVtZW50XCIpLFxuICAgICAgbG9jYXRpb246IHRoaXMubG9jYXRpb24obm9kZSksXG4gICAgICB0YXJnZXQ6IHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklkZW50aWZpZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbjogdGFyZ2V0TG9jYXRpb24sIG5hbWV9LCB7bmFtZTogdGFyZ2V0TG9jYXRpb259KVxuICAgIH0sIHtvcGVyYXRvcjogdGhpcy5sb2NhdGlvbihvcGVyYXRvcil9KVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIG9uZSBzdXBwb3J0ZWQgRGFydCBzdGF0ZW1lbnQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSBTb3VyY2Ugc3RhdGVtZW50LlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU3RhdGVtZW50fSBTZW1hbnRpYyBzdGF0ZW1lbnQuXG4gICAqL1xuICBzdGF0ZW1lbnQobm9kZSkge1xuICAgIGlmIChub2RlLnR5cGUgPT0gXCJsb2NhbF92YXJpYWJsZV9kZWNsYXJhdGlvblwiKSByZXR1cm4gdGhpcy5sb2NhbChub2RlKVxuICAgIGlmIChub2RlLnR5cGUgPT0gXCJpZl9zdGF0ZW1lbnRcIikgcmV0dXJuIHRoaXMuY29uZGl0aW9uYWwobm9kZSlcbiAgICBpZiAobm9kZS50eXBlID09IFwicmV0dXJuX3N0YXRlbWVudFwiKSB7XG4gICAgICBjb25zdCBwYXJ0cyA9IHRoaXMucGFydHMobm9kZSlcblxuICAgICAgaWYgKHBhcnRzLmxlbmd0aCA8IDIgfHwgcGFydHNbMF0udGV4dCAhPSBcInJldHVyblwiIHx8IHBhcnRzLmF0KC0xKT8udGV4dCAhPSBcIjtcIikgdGhpcy5mYWlsKG5vZGUsIFwicmV0dXJuIHN0YXRlbWVudCBzaGFwZVwiKVxuICAgICAgdGhpcy5zaGFwZShub2RlLCBbXCJyZXR1cm5cIiwgLi4ucGFydHMuc2xpY2UoMSwgLTEpLCBcIjtcIl0pXG4gICAgICBjb25zdCBleHByZXNzaW9uUGFydHMgPSBwYXJ0cy5zbGljZSgxLCAtMSlcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uKGV4cHJlc3Npb25QYXJ0cy5sZW5ndGggPiAwID8ge2V4cHJlc3Npb246IHRoaXMuZXhwcmVzc2lvbihleHByZXNzaW9uUGFydHMsIG5vZGUpfSA6IHt9KSxcbiAgICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUmV0dXJuU3RhdGVtZW50XCIpLFxuICAgICAgICBsb2NhdGlvbjogdGhpcy5sb2NhdGlvbihub2RlKVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAobm9kZS50eXBlID09IFwiZXhwcmVzc2lvbl9zdGF0ZW1lbnRcIikge1xuICAgICAgY29uc3QgcGFydHMgPSB0aGlzLnBhcnRzKG5vZGUpXG5cbiAgICAgIGlmIChwYXJ0cy5sZW5ndGggPCAyIHx8IHBhcnRzLmF0KC0xKT8udGV4dCAhPSBcIjtcIikgdGhpcy5mYWlsKG5vZGUsIFwiZXhwcmVzc2lvbiBzdGF0ZW1lbnQgc2hhcGVcIilcbiAgICAgIHRoaXMuc2hhcGUobm9kZSwgWy4uLnBhcnRzLnNsaWNlKDAsIC0xKSwgXCI7XCJdKVxuICAgICAgaWYgKHBhcnRzLmxlbmd0aCA9PSAyICYmIHBhcnRzWzBdLnR5cGUgPT0gXCJhc3NpZ25tZW50X2V4cHJlc3Npb25cIikgcmV0dXJuIHRoaXMuYXNzaWdubWVudChwYXJ0c1swXSlcbiAgICAgIGNvbnN0IGNhbGxQYXJ0cyA9IHBhcnRzLnNsaWNlKDAsIC0xKVxuICAgICAgY29uc3QgY2FsbENoaWxkcmVuID0gY2FsbFBhcnRzLmxlbmd0aCA9PSAxICYmIGNhbGxQYXJ0c1swXS50eXBlID09IFwibWV0aG9kX2ludm9jYXRpb25cIlxuICAgICAgICA/IHRoaXMucGFydHMoY2FsbFBhcnRzWzBdKSA6IFtdXG4gICAgICBjb25zdCBwcmludCA9IGNhbGxDaGlsZHJlblswXT8udHlwZSA9PSBcImlkZW50aWZpZXJcIiAmJiBjYWxsQ2hpbGRyZW5bMF0udGV4dCA9PSBcInByaW50XCJcbiAgICAgIGNvbnN0IGV4cHJlc3Npb24gPSB0aGlzLmNhbGwoY2FsbFBhcnRzLCBub2RlLCBwcmludClcblxuICAgICAgaWYgKHByaW50KSB7XG4gICAgICAgIGlmIChleHByZXNzaW9uLmtpbmQgIT0gXCJDYWxsRXhwcmVzc2lvblwiIHx8IGV4cHJlc3Npb24uYXJndW1lbnRzLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgICAgdGhpcy5mYWlsKGNhbGxQYXJ0c1swXSwgXCJwcmludCBhcmd1bWVudCBjb3VudFwiKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7ZXhwcmVzc2lvbjogZXhwcmVzc2lvbi5hcmd1bWVudHNbMF0sIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlByaW50U3RhdGVtZW50XCIpLCBsb2NhdGlvbjogdGhpcy5sb2NhdGlvbihub2RlKX1cbiAgICAgIH1cbiAgICAgIGlmIChleHByZXNzaW9uLmtpbmQgIT0gXCJDYWxsRXhwcmVzc2lvblwiKSB0aGlzLmZhaWwoY2FsbFBhcnRzWzBdLCBcImdlbmVyYXRlZCBoZWxwZXIgZXhwcmVzc2lvbiBzdGF0ZW1lbnRcIilcbiAgICAgIHJldHVybiB7ZXhwcmVzc2lvbiwga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiRXhwcmVzc2lvblN0YXRlbWVudFwiKSwgbG9jYXRpb246IHRoaXMubG9jYXRpb24obm9kZSl9XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmZhaWwobm9kZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdW1lcyBvbmUgY29tcGlsZXItb3duZWQgcmVhZCB0aGF0IHByZXZlbnRzIERhcnQgZnJvbSByZWplY3RpbmcgYW4gb3RoZXJ3aXNlIHVucmVhZCBsb2NhbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIENhbmRpZGF0ZSBzb3VyY2Ugc3RhdGVtZW50LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlN0YXRlbWVudCB8IHVuZGVmaW5lZH0gcHJldmlvdXMgUHJldmlvdXMgc2VtYW50aWMgc3RhdGVtZW50LlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgZXhhY3QgYXV0aGVudGljYXRlZCBzdXBwb3J0IHN0YXRlbWVudCB3YXMgY29uc3VtZWQuXG4gICAqL1xuICBnZW5lcmF0ZWRMb2NhbFVzZShub2RlLCBwcmV2aW91cykge1xuICAgIGlmICghdGhpcy5ydW50aW1lIHx8IHByZXZpb3VzPy5raW5kICE9IFwiTG9jYWxEZWNsYXJhdGlvblwiIHx8IG5vZGUudHlwZSAhPSBcImV4cHJlc3Npb25fc3RhdGVtZW50XCIpIHJldHVybiBmYWxzZVxuICAgIGNvbnN0IHN0YXRlbWVudFBhcnRzID0gdGhpcy5wYXJ0cyhub2RlKVxuICAgIGNvbnN0IGludm9jYXRpb24gPSBzdGF0ZW1lbnRQYXJ0c1swXVxuXG4gICAgaWYgKHN0YXRlbWVudFBhcnRzLmxlbmd0aCAhPSAyIHx8IGludm9jYXRpb24/LnR5cGUgIT0gXCJtZXRob2RfaW52b2NhdGlvblwiIHx8IHN0YXRlbWVudFBhcnRzWzFdLnRleHQgIT0gXCI7XCIpIHJldHVybiBmYWxzZVxuICAgIGNvbnN0IGludm9jYXRpb25QYXJ0cyA9IHRoaXMucGFydHMoaW52b2NhdGlvbilcbiAgICBjb25zdCBmdW5jdGlvbk5vZGUgPSB0aGlzLmZpZWxkKGludm9jYXRpb24sIFwiZnVuY3Rpb25cIilcbiAgICBjb25zdCBhcmd1bWVudFBhcnQgPSB0aGlzLmZpZWxkKGludm9jYXRpb24sIFwiYXJndW1lbnRzXCIpXG5cbiAgICBpZiAoaW52b2NhdGlvblBhcnRzLmxlbmd0aCAhPSAyIHx8IGludm9jYXRpb25QYXJ0c1swXS5pZCAhPSBmdW5jdGlvbk5vZGUuaWQgfHwgZnVuY3Rpb25Ob2RlLnR5cGUgIT0gXCJpZGVudGlmaWVyXCIgfHxcbiAgICAgIGZ1bmN0aW9uTm9kZS50ZXh0ICE9IFwiX3NlbWFudGlmb2xkVXNlXCIgfHwgaW52b2NhdGlvblBhcnRzWzFdLmlkICE9IGFyZ3VtZW50UGFydC5pZCB8fCBhcmd1bWVudFBhcnQudHlwZSAhPSBcImFyZ3VtZW50X3BhcnRcIikge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHRoaXMuc2hhcGUobm9kZSwgW2ludm9jYXRpb24sIFwiO1wiXSlcbiAgICB0aGlzLnNoYXBlKGludm9jYXRpb24sIFtmdW5jdGlvbk5vZGUsIGFyZ3VtZW50UGFydF0pXG4gICAgY29uc3QgYXJndW1lbnRzXyA9IHRoaXMuYXJndW1lbnRzKGFyZ3VtZW50UGFydClcblxuICAgIGlmIChhcmd1bWVudHNfLmxlbmd0aCAhPSAxIHx8IGFyZ3VtZW50c19bMF0ubGVuZ3RoICE9IDEgfHwgYXJndW1lbnRzX1swXVswXS50eXBlICE9IFwiaWRlbnRpZmllclwiIHx8XG4gICAgICB0aGlzLmlkZW50aWZpZXIoYXJndW1lbnRzX1swXVswXSkgIT0gcHJldmlvdXMubmFtZSkgdGhpcy5mYWlsKGFyZ3VtZW50UGFydCwgXCJEYXJ0IGFuYWx5emVyIGxvY2FsLXVzZSBzdXBwb3J0IHNoYXBlXCIpXG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGJyYWNlZCBEYXJ0IGJsb2NrLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IG5vZGUgQnJhY2VkIGJsb2NrLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQmxvY2t9IFNlbWFudGljIGJsb2NrLlxuICAgKi9cbiAgYmxvY2sobm9kZSkge1xuICAgIGNvbnN0IHBhcnRzID0gdGhpcy5wYXJ0cyhub2RlKVxuXG4gICAgaWYgKG5vZGUudHlwZSAhPSBcImJsb2NrXCIgfHwgcGFydHMubGVuZ3RoIDwgMiB8fCBwYXJ0c1swXS50ZXh0ICE9IFwie1wiIHx8IHBhcnRzLmF0KC0xKT8udGV4dCAhPSBcIn1cIikge1xuICAgICAgdGhpcy5mYWlsKG5vZGUsIFwiYnJhY2VkIGJsb2NrIHNoYXBlXCIpXG4gICAgfVxuICAgIHRoaXMuc2hhcGUobm9kZSwgW1wie1wiLCAuLi5wYXJ0cy5zbGljZSgxLCAtMSksIFwifVwiXSlcbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlN0YXRlbWVudFtdfSAqL1xuICAgIGNvbnN0IHN0YXRlbWVudHMgPSBbXVxuXG4gICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgcGFydHMuc2xpY2UoMSwgLTEpKSB7XG4gICAgICBpZiAoIXRoaXMuZ2VuZXJhdGVkTG9jYWxVc2Uoc3RhdGVtZW50LCBzdGF0ZW1lbnRzLmF0KC0xKSkpIHN0YXRlbWVudHMucHVzaCh0aGlzLnN0YXRlbWVudChzdGF0ZW1lbnQpKVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQmxvY2tcIiksXG4gICAgICBsb2NhdGlvbjogdGhpcy5sb2NhdGlvbihub2RlKSxcbiAgICAgIHN0YXRlbWVudHNcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVW53cmFwcyBhIHN5bmNocm9ub3VzIGJyYWNlZCBmdW5jdGlvbiBib2R5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IGJvZHkgRnVuY3Rpb24gYm9keSB3cmFwcGVyLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQmxvY2t9IFNlbWFudGljIGJvZHkuXG4gICAqL1xuICBmdW5jdGlvbkJvZHkoYm9keSkge1xuICAgIGNvbnN0IHBhcnRzID0gdGhpcy5wYXJ0cyhib2R5KVxuXG4gICAgaWYgKGJvZHkudHlwZSAhPSBcImZ1bmN0aW9uX2JvZHlcIiB8fCBwYXJ0cy5sZW5ndGggIT0gMSB8fCBwYXJ0c1swXS50eXBlICE9IFwiYmxvY2tcIikge1xuICAgICAgdGhpcy5mYWlsKGJvZHksIFwic3luY2hyb25vdXMgYnJhY2VkIGZ1bmN0aW9uIGJvZHkgcmVxdWlyZWRcIilcbiAgICB9XG4gICAgdGhpcy5zaGFwZShib2R5LCBbcGFydHNbMF1dKVxuICAgIHJldHVybiB0aGlzLmJsb2NrKHBhcnRzWzBdKVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIG9uZSBzdHJpY3QtQm9vbGVhbiBjb25kaXRpb25hbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIFN0cmljdCBCb29sZWFuIGNvbmRpdGlvbmFsLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuSWZTdGF0ZW1lbnR9IFNlbWFudGljIGNvbmRpdGlvbmFsLlxuICAgKi9cbiAgY29uZGl0aW9uYWwobm9kZSkge1xuICAgIGNvbnN0IHBhcnRzID0gdGhpcy5wYXJ0cyhub2RlKVxuICAgIGNvbnN0IGNvbnNlcXVlbmNlID0gdGhpcy5maWVsZChub2RlLCBcImNvbnNlcXVlbmNlXCIpXG4gICAgY29uc3QgY29uc2VxdWVuY2VJbmRleCA9IHBhcnRzLmZpbmRJbmRleCgoe2lkfSkgPT4gaWQgPT0gY29uc2VxdWVuY2UuaWQpXG5cbiAgICBpZiAobm9kZS50eXBlICE9IFwiaWZfc3RhdGVtZW50XCIgfHwgcGFydHNbMF0/LnRleHQgIT0gXCJpZlwiIHx8IHBhcnRzWzFdPy50ZXh0ICE9IFwiKFwiIHx8IGNvbnNlcXVlbmNlLnR5cGUgIT0gXCJibG9ja1wiIHx8XG4gICAgICBjb25zZXF1ZW5jZUluZGV4IDwgNCB8fCBwYXJ0c1tjb25zZXF1ZW5jZUluZGV4IC0gMV0/LnRleHQgIT0gXCIpXCIpIHRoaXMuZmFpbChub2RlLCBcImlmIHN0YXRlbWVudCBzaGFwZVwiKVxuICAgIGNvbnN0IGNvbmRpdGlvblBhcnRzID0gcGFydHMuc2xpY2UoMiwgY29uc2VxdWVuY2VJbmRleCAtIDEpXG5cbiAgICBpZiAoY29uZGl0aW9uUGFydHMubGVuZ3RoID09IDApIHRoaXMuZmFpbChub2RlLCBcImVtcHR5IGlmIGNvbmRpdGlvblwiKVxuICAgIGNvbnN0IHN0YXRlbWVudCA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuSWZTdGF0ZW1lbnR9ICovICh7XG4gICAgICBjb25kaXRpb246IHRoaXMuZXhwcmVzc2lvbihjb25kaXRpb25QYXJ0cywgbm9kZSksXG4gICAgICBjb25zZXF1ZW50OiB0aGlzLmJsb2NrKGNvbnNlcXVlbmNlKSxcbiAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklmU3RhdGVtZW50XCIpLFxuICAgICAgbG9jYXRpb246IHRoaXMubG9jYXRpb24obm9kZSlcbiAgICB9KVxuICAgIGlmIChwYXJ0cy5sZW5ndGggPT0gY29uc2VxdWVuY2VJbmRleCArIDEpIHtcbiAgICAgIHRoaXMuc2hhcGUobm9kZSwgW1wiaWZcIiwgXCIoXCIsIC4uLmNvbmRpdGlvblBhcnRzLCBcIilcIiwgY29uc2VxdWVuY2VdKVxuICAgICAgcmV0dXJuIHN0YXRlbWVudFxuICAgIH1cbiAgICBjb25zdCBhbHRlcm5hdGl2ZSA9IHRoaXMuZmllbGQobm9kZSwgXCJhbHRlcm5hdGl2ZVwiKVxuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCAhPSBjb25zZXF1ZW5jZUluZGV4ICsgMyB8fCBwYXJ0c1tjb25zZXF1ZW5jZUluZGV4ICsgMV0/LnRleHQgIT0gXCJlbHNlXCIgfHxcbiAgICAgIHBhcnRzW2NvbnNlcXVlbmNlSW5kZXggKyAyXT8uaWQgIT0gYWx0ZXJuYXRpdmUuaWQpIHRoaXMuZmFpbChhbHRlcm5hdGl2ZSwgXCJpZiBhbHRlcm5hdGUgc2hhcGVcIilcbiAgICB0aGlzLnNoYXBlKG5vZGUsIFtcImlmXCIsIFwiKFwiLCAuLi5jb25kaXRpb25QYXJ0cywgXCIpXCIsIGNvbnNlcXVlbmNlLCBcImVsc2VcIiwgYWx0ZXJuYXRpdmVdKVxuICAgIGlmIChhbHRlcm5hdGl2ZS50eXBlID09IFwiYmxvY2tcIikgcmV0dXJuIHsuLi5zdGF0ZW1lbnQsIGFsdGVybmF0ZTogdGhpcy5ibG9jayhhbHRlcm5hdGl2ZSl9XG4gICAgaWYgKGFsdGVybmF0aXZlLnR5cGUgPT0gXCJpZl9zdGF0ZW1lbnRcIikge1xuICAgICAgcmV0dXJuIHsuLi5zdGF0ZW1lbnQsIGFsdGVybmF0ZToge1xuICAgICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJCbG9ja1wiKSwgbG9jYXRpb246IHRoaXMubG9jYXRpb24oYWx0ZXJuYXRpdmUpLCBzdGF0ZW1lbnRzOiBbdGhpcy5jb25kaXRpb25hbChhbHRlcm5hdGl2ZSldXG4gICAgICB9fVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5mYWlsKGFsdGVybmF0aXZlLCBcImJyYWNlZCBibG9jayBvciBlbHNlLWlmIHJlcXVpcmVkXCIpXG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgb25lIHJlcXVpcmVkIGV4cGxpY2l0bHkgdHlwZWQgcG9zaXRpb25hbCBwYXJhbWV0ZXIuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSBSZXF1aXJlZCBwb3NpdGlvbmFsIHBhcmFtZXRlci5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlBhcmFtZXRlcn0gU2VtYW50aWMgcGFyYW1ldGVyLlxuICAgKi9cbiAgcGFyYW1ldGVyKG5vZGUpIHtcbiAgICBjb25zdCBwYXJ0cyA9IHRoaXMucGFydHMobm9kZSlcblxuICAgIGlmIChwYXJ0cy5sZW5ndGggPT0gMSAmJiBwYXJ0c1swXS50eXBlID09IFwiaWRlbnRpZmllclwiKSByZXR1cm4gbWlzc2luZ1R5cGUoXCJkYXJ0XCIsIFwiUGFyYW1ldGVyXCIsIHRoaXMubG9jYXRpb24obm9kZSkpXG4gICAgaWYgKG5vZGUudHlwZSAhPSBcImZvcm1hbF9wYXJhbWV0ZXJcIiB8fCBwYXJ0cy5sZW5ndGggIT0gMiB8fCBwYXJ0c1swXS50eXBlICE9IFwidHlwZV9pZGVudGlmaWVyXCIgfHxcbiAgICAgIHBhcnRzWzFdLnR5cGUgIT0gXCJpZGVudGlmaWVyXCIpIHRoaXMuZmFpbChub2RlLCBcInJlcXVpcmVkIGV4cGxpY2l0bHkgdHlwZWQgcG9zaXRpb25hbCBwYXJhbWV0ZXJcIilcbiAgICB0aGlzLnNoYXBlKG5vZGUsIFtwYXJ0c1swXSwgcGFydHNbMV1dKVxuICAgIGlmICh0aGlzLmZpZWxkKG5vZGUsIFwibmFtZVwiKS5pZCAhPSBwYXJ0c1sxXS5pZCkgdGhpcy5mYWlsKHBhcnRzWzFdLCBcInBhcmFtZXRlciBuYW1lIGZpZWxkXCIpXG4gICAgY29uc3QgbmFtZSA9IHRoaXMuaWRlbnRpZmllcihwYXJ0c1sxXSlcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlBhcmFtZXRlclwiKSwgbG9jYXRpb246IHRoaXMubG9jYXRpb24obm9kZSksIG5hbWUsIHR5cGU6IHRoaXMuc2NhbGFyVHlwZShwYXJ0c1swXSlcbiAgICB9LCB7bmFtZTogdGhpcy5sb2NhdGlvbihwYXJ0c1sxXSl9KVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgcmVxdWlyZWQgcG9zaXRpb25hbCBwYXJhbWV0ZXIgbGlzdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIFBhcmFtZXRlciBsaXN0LlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuUGFyYW1ldGVyW119IFNlbWFudGljIHBhcmFtZXRlcnMuXG4gICAqL1xuICBwYXJhbWV0ZXJzKG5vZGUpIHtcbiAgICBjb25zdCBwYXJ0cyA9IHRoaXMucGFydHMobm9kZSlcblxuICAgIGlmIChub2RlLnR5cGUgIT0gXCJmb3JtYWxfcGFyYW1ldGVyX2xpc3RcIiB8fCBwYXJ0cy5sZW5ndGggPCAyIHx8IHBhcnRzWzBdLnRleHQgIT0gXCIoXCIgfHwgcGFydHMuYXQoLTEpPy50ZXh0ICE9IFwiKVwiKSB7XG4gICAgICB0aGlzLmZhaWwobm9kZSwgXCJmb3JtYWwgcGFyYW1ldGVyIGxpc3Qgc2hhcGVcIilcbiAgICB9XG4gICAgY29uc3QgaW50ZXJpb3IgPSBwYXJ0cy5zbGljZSgxLCAtMSlcbiAgICBjb25zdCBoYXNHZW5lcmF0ZWRUcmFpbGluZ0NvbW1hID0gdGhpcy5ydW50aW1lICYmIGludGVyaW9yLmF0KC0xKT8udGV4dCA9PSBcIixcIlxuICAgIGNvbnN0IHBhcmFtZXRlclBhcnRzID0gaGFzR2VuZXJhdGVkVHJhaWxpbmdDb21tYSA/IGludGVyaW9yLnNsaWNlKDAsIC0xKSA6IGludGVyaW9yXG4gICAgY29uc3QgcGFyYW1ldGVycyA9IHBhcmFtZXRlclBhcnRzLmZpbHRlcigoX2NoaWxkLCBpbmRleCkgPT4gaW5kZXggJSAyID09IDApXG5cbiAgICB0aGlzLnNoYXBlKG5vZGUsIFtcIihcIiwgLi4ucGFyYW1ldGVycy5mbGF0TWFwKChwYXJhbWV0ZXIsIGluZGV4KSA9PiBpbmRleCA/IFtcIixcIiwgcGFyYW1ldGVyXSA6IFtwYXJhbWV0ZXJdKSxcbiAgICAgIC4uLihoYXNHZW5lcmF0ZWRUcmFpbGluZ0NvbW1hID8gW1wiLFwiXSA6IFtdKSwgXCIpXCJdKVxuICAgIHJldHVybiBwYXJhbWV0ZXJzLm1hcCgocGFyYW1ldGVyKSA9PiB0aGlzLnBhcmFtZXRlcihwYXJhbWV0ZXIpKVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIG9uZSBvcmRpbmFyeSB0b3AtbGV2ZWwgZnVuY3Rpb24gZGVjbGFyYXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gc2lnbmF0dXJlIEZ1bmN0aW9uIHNpZ25hdHVyZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBib2R5IEZ1bmN0aW9uIGJvZHkuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9ufSBTZW1hbnRpYyBmdW5jdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uKHNpZ25hdHVyZSwgYm9keSkge1xuICAgIGNvbnN0IHBhcnRzID0gdGhpcy5wYXJ0cyhzaWduYXR1cmUpXG5cbiAgICBpZiAoc2lnbmF0dXJlLnR5cGUgIT0gXCJmdW5jdGlvbl9zaWduYXR1cmVcIikgdGhpcy5mYWlsKHNpZ25hdHVyZSwgXCJmdW5jdGlvbiBzaWduYXR1cmVcIilcbiAgICBpZiAocGFydHMubGVuZ3RoID09IDIgJiYgcGFydHNbMF0udHlwZSA9PSBcImlkZW50aWZpZXJcIikgcmV0dXJuIG1pc3NpbmdUeXBlKFwiZGFydFwiLCBcIkZ1bmN0aW9uIHJldHVyblwiLCB0aGlzLmxvY2F0aW9uKHNpZ25hdHVyZSkpXG4gICAgaWYgKHBhcnRzLmxlbmd0aCAhPSAzIHx8ICFbXCJ0eXBlX2lkZW50aWZpZXJcIiwgXCJ2b2lkX3R5cGVcIl0uaW5jbHVkZXMocGFydHNbMF0udHlwZSkgfHwgcGFydHNbMV0udHlwZSAhPSBcImlkZW50aWZpZXJcIiB8fFxuICAgICAgcGFydHNbMl0udHlwZSAhPSBcImZvcm1hbF9wYXJhbWV0ZXJfbGlzdFwiKSB0aGlzLmZhaWwoc2lnbmF0dXJlLCBcImV4cGxpY2l0IHRvcC1sZXZlbCBmdW5jdGlvbiBzaWduYXR1cmVcIilcbiAgICB0aGlzLnNoYXBlKHNpZ25hdHVyZSwgW3BhcnRzWzBdLCBwYXJ0c1sxXSwgcGFydHNbMl1dKVxuICAgIGlmICh0aGlzLmZpZWxkKHNpZ25hdHVyZSwgXCJuYW1lXCIpLmlkICE9IHBhcnRzWzFdLmlkKSB0aGlzLmZhaWwocGFydHNbMV0sIFwiZnVuY3Rpb24gbmFtZSBmaWVsZFwiKVxuICAgIGNvbnN0IG5hbWUgPSB0aGlzLmlkZW50aWZpZXIocGFydHNbMV0pXG4gICAgY29uc3QgbG9jYXRpb24gPSBsb2NhdGlvbkZyb21PZmZzZXRzKHRoaXMuZmlsZW5hbWUsIHRoaXMuc291cmNlLCBiaW5kaW5nSW5kZXhUb1V0ZjE2T2Zmc2V0KHRoaXMuc291cmNlLCBzaWduYXR1cmUuc3RhcnRJbmRleCksXG4gICAgICBiaW5kaW5nSW5kZXhUb1V0ZjE2T2Zmc2V0KHRoaXMuc291cmNlLCBib2R5LmVuZEluZGV4KSlcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGJvZHk6IHRoaXMuZnVuY3Rpb25Cb2R5KGJvZHkpLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiRnVuY3Rpb25EZWNsYXJhdGlvblwiKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgbmFtZSxcbiAgICAgIHBhcmFtZXRlcnM6IHRoaXMucGFyYW1ldGVycyhwYXJ0c1syXSksXG4gICAgICByZXR1cm5UeXBlOiB0aGlzLnJldHVyblR5cGUocGFydHNbMF0pXG4gICAgfSwge25hbWU6IHRoaXMubG9jYXRpb24ocGFydHNbMV0pfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyB0aGUgZXhhY3Qgdm9pZCBtYWluIGVudHJ5IHNoZWxsLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IHNpZ25hdHVyZSBNYWluIHNpZ25hdHVyZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBib2R5IE1haW4gYm9keS5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVudHJ5UG9pbnR9IFNlbWFudGljIGVudHJ5IHBvaW50LlxuICAgKi9cbiAgbWFpbihzaWduYXR1cmUsIGJvZHkpIHtcbiAgICBjb25zdCBwYXJ0cyA9IHRoaXMucGFydHMoc2lnbmF0dXJlKVxuXG4gICAgaWYgKHNpZ25hdHVyZS50eXBlICE9IFwiZnVuY3Rpb25fc2lnbmF0dXJlXCIgfHwgcGFydHMubGVuZ3RoICE9IDMgfHwgcGFydHNbMF0udHlwZSAhPSBcInZvaWRfdHlwZVwiIHx8XG4gICAgICB0aGlzLmlkZW50aWZpZXIocGFydHNbMV0sIHRydWUpICE9IFwibWFpblwiIHx8IHBhcnRzWzJdLnR5cGUgIT0gXCJmb3JtYWxfcGFyYW1ldGVyX2xpc3RcIikge1xuICAgICAgdGhpcy5mYWlsKHNpZ25hdHVyZSwgXCJleGFjdCB2b2lkIG1haW4oKSBzaWduYXR1cmUgcmVxdWlyZWRcIilcbiAgICB9XG4gICAgdGhpcy5zaGFwZShzaWduYXR1cmUsIFtwYXJ0c1swXSwgcGFydHNbMV0sIHBhcnRzWzJdXSlcbiAgICB0aGlzLnNoYXBlKHBhcnRzWzJdLCBbXCIoXCIsIFwiKVwiXSlcbiAgICBjb25zdCBsb2NhdGlvbiA9IGxvY2F0aW9uRnJvbU9mZnNldHModGhpcy5maWxlbmFtZSwgdGhpcy5zb3VyY2UsIGJpbmRpbmdJbmRleFRvVXRmMTZPZmZzZXQodGhpcy5zb3VyY2UsIHNpZ25hdHVyZS5zdGFydEluZGV4KSxcbiAgICAgIGJpbmRpbmdJbmRleFRvVXRmMTZPZmZzZXQodGhpcy5zb3VyY2UsIGJvZHkuZW5kSW5kZXgpKVxuXG4gICAgcmV0dXJuIHtib2R5OiB0aGlzLmZ1bmN0aW9uQm9keShib2R5KSwga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiRW50cnlQb2ludFwiKSwgbG9jYXRpb259XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgb25lIGNvbXBsZXRlIERhcnQgY29tcGlsYXRpb24gdW5pdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSByb290IENvbXBsZXRlIERhcnQgcHJvZ3JhbS5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBTZW1hbnRpYyBtb2R1bGUuXG4gICAqL1xuICBtb2R1bGUocm9vdCkge1xuICAgIHRoaXMudmFsaWRhdGVUcmVlKHJvb3QpXG4gICAgaWYgKHJvb3QudHlwZSAhPSBcInByb2dyYW1cIikgdGhpcy5mYWlsKHJvb3QsIFwicHJvZ3JhbSByb290XCIpXG4gICAgY29uc3QgcGFydHMgPSB0aGlzLnBhcnRzKHJvb3QpXG4gICAgY29uc3Qgc3VwcG9ydFRyZWUgPSBwYXJzZXIucGFyc2UoZGFydFJ1bnRpbWUpXG4gICAgY29uc3Qgc3VwcG9ydCA9IHRoaXMucGFydHMoc3VwcG9ydFRyZWUucm9vdE5vZGUpXG4gICAgbGV0IHN1cHBvcnRJbmRleCA9IDBcblxuICAgIHdoaWxlIChzdXBwb3J0SW5kZXggPCBwYXJ0cy5sZW5ndGggJiYgc3VwcG9ydEluZGV4IDwgc3VwcG9ydC5sZW5ndGggJiZcbiAgICAgIHBhcnRzW3N1cHBvcnRJbmRleF0udHlwZSA9PSBzdXBwb3J0W3N1cHBvcnRJbmRleF0udHlwZSkge1xuICAgICAgdGhpcy5jb21wYXJlVHJlZShwYXJ0c1tzdXBwb3J0SW5kZXhdLCBzdXBwb3J0W3N1cHBvcnRJbmRleF0pXG4gICAgICBzdXBwb3J0SW5kZXggKz0gMVxuICAgIH1cbiAgICBpZiAoc3VwcG9ydEluZGV4ID4gMCAmJiBzdXBwb3J0SW5kZXggIT0gc3VwcG9ydC5sZW5ndGgpIHtcbiAgICAgIHRoaXMuZmFpbChwYXJ0c1tzdXBwb3J0SW5kZXggLSAxXSwgXCJjb21wbGV0ZSBEYXJ0IHN1cHBvcnQgcmVxdWlyZWRcIilcbiAgICB9XG4gICAgdGhpcy5ydW50aW1lID0gc3VwcG9ydEluZGV4ID09IHN1cHBvcnQubGVuZ3RoXG4gICAgY29uc3Qgc2VtYW50aWNQYXJ0cyA9IHBhcnRzLnNsaWNlKHN1cHBvcnRJbmRleClcblxuICAgIGlmIChzZW1hbnRpY1BhcnRzLmxlbmd0aCA9PSAwKSB0aGlzLmZhaWwocm9vdCwgXCJwcm9ncmFtIHdpdGhvdXQgbWFpblwiKVxuICAgIC8qKiBAdHlwZSB7e2JvZHk6IGltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGUsIHNpZ25hdHVyZTogaW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX1bXX0gKi9cbiAgICBjb25zdCBkZWNsYXJhdGlvbnMgPSBbXVxuXG4gICAgZm9yIChjb25zdCBkZWNsYXJhdGlvbiBvZiBzZW1hbnRpY1BhcnRzKSB7XG4gICAgICBpZiAoZGVjbGFyYXRpb24udHlwZSAhPSBcImZ1bmN0aW9uX2RlY2xhcmF0aW9uXCIpIHRoaXMuZmFpbChkZWNsYXJhdGlvbiwgXCJ0b3AtbGV2ZWwgZnVuY3Rpb24gZGVjbGFyYXRpb24gcmVxdWlyZWRcIilcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IHRoaXMuZmllbGQoZGVjbGFyYXRpb24sIFwic2lnbmF0dXJlXCIpXG4gICAgICBjb25zdCBib2R5ID0gdGhpcy5maWVsZChkZWNsYXJhdGlvbiwgXCJib2R5XCIpXG4gICAgICBjb25zdCBkZWNsYXJhdGlvblBhcnRzID0gdGhpcy5wYXJ0cyhkZWNsYXJhdGlvbilcblxuICAgICAgaWYgKGRlY2xhcmF0aW9uUGFydHMubGVuZ3RoICE9IDIgfHwgZGVjbGFyYXRpb25QYXJ0c1swXS5pZCAhPSBzaWduYXR1cmUuaWQgfHwgc2lnbmF0dXJlLnR5cGUgIT0gXCJmdW5jdGlvbl9zaWduYXR1cmVcIiB8fFxuICAgICAgICBkZWNsYXJhdGlvblBhcnRzWzFdLmlkICE9IGJvZHkuaWQgfHwgYm9keS50eXBlICE9IFwiZnVuY3Rpb25fYm9keVwiKSB7XG4gICAgICAgIHRoaXMuZmFpbChkZWNsYXJhdGlvbiwgXCJwYWlyZWQgdG9wLWxldmVsIGZ1bmN0aW9uIHNpZ25hdHVyZSBhbmQgYm9keSByZXF1aXJlZFwiKVxuICAgICAgfVxuICAgICAgdGhpcy5zaGFwZShkZWNsYXJhdGlvbiwgW3NpZ25hdHVyZSwgYm9keV0pXG4gICAgICBkZWNsYXJhdGlvbnMucHVzaCh7Ym9keSwgc2lnbmF0dXJlfSlcbiAgICB9XG4gICAgY29uc3QgbWFpbkluZGV4ZXMgPSBkZWNsYXJhdGlvbnMuZmxhdE1hcCgoe3NpZ25hdHVyZX0sIGluZGV4KSA9PiB0aGlzLnBhcnRzKHNpZ25hdHVyZSlbMV0/LnRleHQgPT0gXCJtYWluXCIgPyBbaW5kZXhdIDogW10pXG5cbiAgICBpZiAobWFpbkluZGV4ZXMubGVuZ3RoICE9IDEpIHRoaXMuZmFpbChyb290LCBcImV4YWN0bHkgb25lIG1haW4gZGVjbGFyYXRpb24gcmVxdWlyZWRcIilcbiAgICBjb25zdCBtYWluSW5kZXggPSBtYWluSW5kZXhlc1swXVxuXG4gICAgdGhpcy5mdW5jdGlvbk5hbWVzID0gbmV3IFNldChkZWNsYXJhdGlvbnMubWFwKCh7c2lnbmF0dXJlfSkgPT4gdGhpcy5wYXJ0cyhzaWduYXR1cmUpWzFdPy50ZXh0KS5maWx0ZXIoQm9vbGVhbikpXG5cbiAgICBpZiAobWFpbkluZGV4ICE9IGRlY2xhcmF0aW9ucy5sZW5ndGggLSAxKSB0aGlzLmZhaWwoZGVjbGFyYXRpb25zW21haW5JbmRleCArIDFdLnNpZ25hdHVyZSwgXCJkZWNsYXJhdGlvbiBhZnRlciBtYWluXCIpXG4gICAgY29uc3QgbWFpbiA9IGRlY2xhcmF0aW9uc1ttYWluSW5kZXhdXG4gICAgY29uc3QgbW9kdWxlID0ge1xuICAgICAgZW50cnlQb2ludDogdGhpcy5tYWluKG1haW4uc2lnbmF0dXJlLCBtYWluLmJvZHkpLFxuICAgICAgZnVuY3Rpb25zOiBkZWNsYXJhdGlvbnMuc2xpY2UoMCwgbWFpbkluZGV4KS5tYXAoKHtib2R5LCBzaWduYXR1cmV9KSA9PiB0aGlzLmZ1bmN0aW9uKHNpZ25hdHVyZSwgYm9keSkpLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiTW9kdWxlXCIpLFxuICAgICAgbG9jYXRpb246IHRoaXMubG9jYXRpb24ocm9vdClcbiAgICB9XG5cbiAgICB2YWxpZGF0ZVBhcnNlZE1vZHVsZShtb2R1bGUsIFwiZGFydFwiKVxuICAgIHJldHVybiBtb2R1bGVcbiAgfVxufVxuXG4vKipcbiAqIFBhcnNlcyB0aGUgc3RyaWN0IFRhc2sgMDI5IERhcnQgVk0vbmF0aXZlIHByb2ZpbGUgdGhyb3VnaCB0aGUgcXVhbGlmaWVkIGdyYW1tYXIuXG4gKiBAcGFyYW0ge3tmaWxlbmFtZTogc3RyaW5nLCBzb3VyY2U6IHN0cmluZ319IGlucHV0IEV4YWN0IHNvdXJjZSByZXF1ZXN0LlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBTZW1hbnRpYyBtb2R1bGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZURhcnQoe2ZpbGVuYW1lLCBzb3VyY2V9KSB7XG4gIGlmICghaGFzT25seVVuaWNvZGVTY2FsYXJzKHNvdXJjZSkpIHtcbiAgICBjb25zdCBvZmZzZXQgPSBmaXJzdExvbmVTdXJyb2dhdGVPZmZzZXQoc291cmNlKVxuXG4gICAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgICBjb2RlOiBcIlBBUlNFX0VSUk9SXCIsIGxhbmd1YWdlOiBcImRhcnRcIiwgbG9jYXRpb246IGxvY2F0aW9uRnJvbU9mZnNldHMoZmlsZW5hbWUsIHNvdXJjZSwgb2Zmc2V0LCBvZmZzZXQgKyAxKSxcbiAgICAgIG1lc3NhZ2U6IFwiRGFydCBzb3VyY2UgY29udGFpbnMgYW4gaW52YWxpZCBsb25lIFVURi0xNiBzdXJyb2dhdGUuXCJcbiAgICB9KVxuICB9XG4gIGxldCB0cmVlXG5cbiAgdHJ5IHtcbiAgICB0cmVlID0gcGFyc2VyLnBhcnNlKHNvdXJjZSlcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtcbiAgICAgIGNhdXNlOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiB1bmRlZmluZWQsXG4gICAgICBjb2RlOiBcIlBBUlNFX0VSUk9SXCIsXG4gICAgICBsYW5ndWFnZTogXCJkYXJ0XCIsXG4gICAgICBsb2NhdGlvbjogbW9kdWxlTG9jYXRpb24oZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBtZXNzYWdlOiBcIlRoZSBxdWFsaWZpZWQgRGFydCBwYXJzZXIgY291bGQgbm90IHByb2R1Y2UgYSBjb21wbGV0ZSBDU1QuXCJcbiAgICB9KVxuICB9XG4gIHJldHVybiBuZXcgRGFydFJlYWRlcihmaWxlbmFtZSwgc291cmNlKS5tb2R1bGUodHJlZS5yb290Tm9kZSlcbn1cbiJdfQ==
|