semantifold 0.1.1 → 0.3.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 +42 -10
- package/build/index.d.ts +32 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +99 -4
- package/build/src/acceptance.d.ts +32 -0
- package/build/src/acceptance.d.ts.map +1 -0
- package/build/src/acceptance.js +358 -0
- package/build/src/array.d.ts +7 -0
- package/build/src/array.d.ts.map +1 -0
- package/build/src/array.js +18 -0
- package/build/src/artifact-path.d.ts +13 -0
- package/build/src/artifact-path.d.ts.map +1 -0
- package/build/src/artifact-path.js +30 -0
- package/build/src/artifacts.d.ts +7 -0
- package/build/src/artifacts.d.ts.map +1 -0
- package/build/src/artifacts.js +389 -0
- package/build/src/backends/c-runtime.d.ts +3 -0
- package/build/src/backends/c-runtime.d.ts.map +1 -0
- package/build/src/backends/c-runtime.js +151 -0
- package/build/src/backends/c-validation.d.ts +12 -0
- package/build/src/backends/c-validation.d.ts.map +1 -0
- package/build/src/backends/c-validation.js +85 -0
- package/build/src/backends/c.d.ts +31 -0
- package/build/src/backends/c.d.ts.map +1 -0
- package/build/src/backends/c.js +308 -0
- package/build/src/backends/cpp-runtime.d.ts +3 -0
- package/build/src/backends/cpp-runtime.d.ts.map +1 -0
- package/build/src/backends/cpp-runtime.js +99 -0
- package/build/src/backends/cpp-validation.d.ts +9 -0
- package/build/src/backends/cpp-validation.d.ts.map +1 -0
- package/build/src/backends/cpp-validation.js +74 -0
- package/build/src/backends/cpp.d.ts +16 -0
- package/build/src/backends/cpp.d.ts.map +1 -0
- package/build/src/backends/cpp.js +285 -0
- package/build/src/backends/csharp.d.ts +20 -0
- package/build/src/backends/csharp.d.ts.map +1 -0
- package/build/src/backends/csharp.js +259 -0
- package/build/src/backends/go.d.ts +20 -0
- package/build/src/backends/go.d.ts.map +1 -0
- package/build/src/backends/go.js +374 -0
- package/build/src/backends/identifiers.d.ts +12 -0
- package/build/src/backends/identifiers.d.ts.map +1 -1
- package/build/src/backends/identifiers.js +79 -2
- package/build/src/backends/index.d.ts.map +1 -1
- package/build/src/backends/index.js +27 -37
- package/build/src/backends/native-validation.d.ts +9 -0
- package/build/src/backends/native-validation.d.ts.map +1 -0
- package/build/src/backends/native-validation.js +59 -0
- package/build/src/backends/ordered-expressions.d.ts +74 -0
- package/build/src/backends/ordered-expressions.d.ts.map +1 -0
- package/build/src/backends/ordered-expressions.js +159 -0
- package/build/src/backends/python.d.ts +8 -0
- package/build/src/backends/python.d.ts.map +1 -0
- package/build/src/backends/python.js +162 -0
- package/build/src/backends/scalars.d.ts.map +1 -1
- package/build/src/backends/scalars.js +8 -2
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +67 -19
- package/build/src/binary-mapping.d.ts +32 -0
- package/build/src/binary-mapping.d.ts.map +1 -0
- package/build/src/binary-mapping.js +285 -0
- package/build/src/diagnostic.d.ts +36 -4
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +42 -3
- package/build/src/frontends/c-parser.d.ts +20 -0
- package/build/src/frontends/c-parser.d.ts.map +1 -0
- package/build/src/frontends/c-parser.js +14 -0
- package/build/src/frontends/c.d.ts +220 -0
- package/build/src/frontends/c.d.ts.map +1 -0
- package/build/src/frontends/c.js +750 -0
- package/build/src/frontends/cpp-parser.d.ts +11 -0
- package/build/src/frontends/cpp-parser.d.ts.map +1 -0
- package/build/src/frontends/cpp-parser.js +15 -0
- package/build/src/frontends/cpp.d.ts +227 -0
- package/build/src/frontends/cpp.d.ts.map +1 -0
- package/build/src/frontends/cpp.js +784 -0
- package/build/src/frontends/csharp.d.ts +14 -0
- package/build/src/frontends/csharp.d.ts.map +1 -0
- package/build/src/frontends/csharp.js +708 -0
- package/build/src/frontends/go.d.ts +15 -0
- package/build/src/frontends/go.d.ts.map +1 -0
- package/build/src/frontends/go.js +712 -0
- package/build/src/frontends/index.d.ts.map +1 -1
- package/build/src/frontends/index.js +5 -23
- package/build/src/frontends/python.d.ts +14 -0
- package/build/src/frontends/python.d.ts.map +1 -0
- package/build/src/frontends/python.js +615 -0
- package/build/src/frontends/scalars.d.ts.map +1 -1
- package/build/src/frontends/scalars.js +21 -1
- package/build/src/language-registry.d.ts +113 -0
- package/build/src/language-registry.d.ts.map +1 -0
- package/build/src/language-registry.js +421 -0
- package/build/src/mapping.js +3 -2
- package/build/src/semantic/location.d.ts +7 -0
- package/build/src/semantic/location.d.ts.map +1 -1
- package/build/src/semantic/location.js +10 -1
- package/build/src/semantic/provenance.js +3 -3
- package/build/src/semantic/types.d.ts +399 -2
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +110 -2
- package/build/src/subprocess.d.ts +38 -0
- package/build/src/subprocess.d.ts.map +1 -0
- package/build/src/subprocess.js +233 -0
- package/build/src/timeout.d.ts +8 -0
- package/build/src/timeout.d.ts.map +1 -0
- package/build/src/timeout.js +11 -0
- package/build/src/toolchains.d.ts +107 -0
- package/build/src/toolchains.d.ts.map +1 -0
- package/build/src/toolchains.js +417 -0
- package/docs/architecture.md +23 -5
- package/docs/c.md +60 -0
- package/docs/cpp.md +61 -0
- package/docs/goals.md +4 -2
- package/docs/language-support.md +46 -6
- package/docs/parser-qualification.md +219 -0
- package/docs/plans/2026-09-05-standard-library-portability.md +46 -0
- package/docs/source-maps.md +38 -5
- package/docs/standard-library-portability.md +190 -0
- package/docs/testing.md +131 -3
- package/index.js +109 -4
- package/node_modules/node-addon-api/LICENSE.md +9 -0
- package/node_modules/node-addon-api/README.md +95 -0
- package/node_modules/node-addon-api/common.gypi +21 -0
- package/node_modules/node-addon-api/except.gypi +25 -0
- package/node_modules/node-addon-api/index.js +14 -0
- package/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
- package/node_modules/node-addon-api/napi-inl.h +7250 -0
- package/node_modules/node-addon-api/napi.h +3463 -0
- package/node_modules/node-addon-api/node_addon_api.gyp +42 -0
- package/node_modules/node-addon-api/node_api.gyp +9 -0
- package/node_modules/node-addon-api/noexcept.gypi +26 -0
- package/node_modules/node-addon-api/nothing.c +0 -0
- package/node_modules/node-addon-api/package-support.json +21 -0
- package/node_modules/node-addon-api/package.json +481 -0
- package/node_modules/node-addon-api/tools/README.md +73 -0
- package/node_modules/node-addon-api/tools/check-napi.js +99 -0
- package/node_modules/node-addon-api/tools/clang-format.js +71 -0
- package/node_modules/node-addon-api/tools/conversion.js +301 -0
- package/node_modules/node-gyp-build/LICENSE +21 -0
- package/node_modules/node-gyp-build/README.md +58 -0
- package/node_modules/node-gyp-build/SECURITY.md +5 -0
- package/node_modules/node-gyp-build/bin.js +84 -0
- package/node_modules/node-gyp-build/build-test.js +19 -0
- package/node_modules/node-gyp-build/index.js +6 -0
- package/node_modules/node-gyp-build/node-gyp-build.js +207 -0
- package/node_modules/node-gyp-build/optional.js +7 -0
- package/node_modules/node-gyp-build/package.json +43 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/LICENSE +15 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +7 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/README.md +90 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/binding.gyp +79 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/index.js +895 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/package.json +62 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/prebuilds/darwin-arm64/tree-sitter.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/prebuilds/darwin-x64/tree-sitter.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/prebuilds/linux-x64/tree-sitter.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/prebuilds/win32-x64/tree-sitter.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/addon_data.h +47 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/binding.cc +35 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/conversions.cc +140 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/conversions.h +22 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/language.cc +106 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/language.h +17 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/logger.cc +70 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/logger.h +19 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/lookaheaditerator.cc +122 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/lookaheaditerator.h +33 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/node.cc +1056 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/node.h +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/parser.cc +298 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/parser.h +35 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/query.cc +383 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/query.h +39 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/tree.cc +307 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/tree.h +45 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/tree_cursor.cc +213 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/tree_cursor.h +52 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/tree-sitter.d.ts +211 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/include/tree_sitter/api.h +1266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.c +48 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.h +41 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/atomic.h +68 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/clock.h +146 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/error_costs.h +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.c +501 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.h +36 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/host.h +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.c +221 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.h +299 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/length.h +52 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.c +419 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.h +49 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lib.c +14 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/node.c +774 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.c +2151 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.h +230 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/point.h +62 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/query.c +4134 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reduce_action.h +34 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reusable_node.h +95 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.c +899 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.h +133 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.c +1060 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.h +382 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.c +165 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.h +31 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.c +714 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.h +48 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ICU_SHA +1 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/LICENSE +414 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/README.md +29 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ptypes.h +1 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/umachine.h +448 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/urename.h +1 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf.h +1 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf16.h +733 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf8.h +881 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode.h +50 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib-symbols.txt +23 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib.c +109 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/wasm-stdlib.h +1294 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.c +1823 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.h +31 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/README.md +18 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/binding.gyp +29 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/grammar.js +1470 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/package.json +60 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/darwin-arm64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/darwin-x64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/linux-arm64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/linux-x64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/win32-arm64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/win32-x64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/queries/highlights.scm +81 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/queries/tags.scm +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/grammar.json +9735 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/node-types.json +4614 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/parser.c +119615 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/tree-sitter-c.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/tree-sitter.json +43 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/README.md +22 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/binding.gyp +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/grammar.js +1436 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/package.json +61 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/darwin-arm64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/darwin-x64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/linux-arm64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/linux-x64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/win32-arm64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/win32-x64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/queries/highlights.scm +70 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/queries/injections.scm +3 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/queries/tags.scm +15 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/grammar.json +17084 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/node-types.json +7997 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/parser.c +530368 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/scanner.c +148 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/tree-sitter-cpp.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/tree-sitter.json +55 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +22 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +152 -0
- package/node_modules/tree-sitter/LICENSE +21 -0
- package/node_modules/tree-sitter/README.md +128 -0
- package/node_modules/tree-sitter/binding.gyp +88 -0
- package/node_modules/tree-sitter/index.js +950 -0
- package/node_modules/tree-sitter/package.json +76 -0
- package/node_modules/tree-sitter/prebuilds/darwin-arm64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/darwin-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/linux-arm64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/linux-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/win32-arm64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/win32-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/src/addon_data.h +47 -0
- package/node_modules/tree-sitter/src/binding.cc +35 -0
- package/node_modules/tree-sitter/src/conversions.cc +140 -0
- package/node_modules/tree-sitter/src/conversions.h +22 -0
- package/node_modules/tree-sitter/src/language.cc +105 -0
- package/node_modules/tree-sitter/src/language.h +17 -0
- package/node_modules/tree-sitter/src/logger.cc +70 -0
- package/node_modules/tree-sitter/src/logger.h +19 -0
- package/node_modules/tree-sitter/src/lookaheaditerator.cc +122 -0
- package/node_modules/tree-sitter/src/lookaheaditerator.h +33 -0
- package/node_modules/tree-sitter/src/node.cc +1088 -0
- package/node_modules/tree-sitter/src/node.h +30 -0
- package/node_modules/tree-sitter/src/parser.cc +332 -0
- package/node_modules/tree-sitter/src/parser.h +35 -0
- package/node_modules/tree-sitter/src/query.cc +425 -0
- package/node_modules/tree-sitter/src/query.h +40 -0
- package/node_modules/tree-sitter/src/tree.cc +316 -0
- package/node_modules/tree-sitter/src/tree.h +45 -0
- package/node_modules/tree-sitter/src/tree_cursor.cc +213 -0
- package/node_modules/tree-sitter/src/tree_cursor.h +52 -0
- package/node_modules/tree-sitter/tree-sitter.d.ts +1083 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/include/tree_sitter/api.h +1478 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.c +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.h +41 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/array.h +291 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/atomic.h +68 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/clock.h +146 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/error_costs.h +11 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.c +523 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.h +36 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/host.h +21 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.c +293 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.h +293 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/length.h +52 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.c +483 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.h +54 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lib.c +12 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/node.c +875 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.c +2297 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.h +286 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/point.h +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/portable/endian.h +241 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/query.c +4347 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reduce_action.h +34 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reusable_node.h +95 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.c +912 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.h +133 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.c +1034 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.h +399 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.c +170 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.h +31 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.c +716 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.h +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/ts_assert.h +11 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ICU_SHA +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/LICENSE +414 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/README.md +29 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ptypes.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/umachine.h +448 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/urename.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf16.h +733 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf8.h +881 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode.h +75 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib-symbols.txt +24 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib.c +137 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/wasm-stdlib.h +1314 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.c +1937 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.h +31 -0
- package/package.json +24 -6
- package/src/acceptance.js +380 -0
- package/src/array.js +19 -0
- package/src/artifact-path.js +34 -0
- package/src/artifacts.js +420 -0
- package/src/backends/c-runtime.js +151 -0
- package/src/backends/c-validation.js +83 -0
- package/src/backends/c.js +308 -0
- package/src/backends/cpp-runtime.js +99 -0
- package/src/backends/cpp-validation.js +70 -0
- package/src/backends/cpp.js +285 -0
- package/src/backends/csharp.js +270 -0
- package/src/backends/go.js +383 -0
- package/src/backends/identifiers.js +80 -1
- package/src/backends/index.js +23 -32
- package/src/backends/native-validation.js +64 -0
- package/src/backends/ordered-expressions.js +161 -0
- package/src/backends/python.js +175 -0
- package/src/backends/scalars.js +8 -1
- package/src/backends/shared.js +64 -17
- package/src/binary-mapping.js +305 -0
- package/src/diagnostic.js +34 -2
- package/src/frontends/c-parser.js +17 -0
- package/src/frontends/c.js +780 -0
- package/src/frontends/cpp-parser.js +18 -0
- package/src/frontends/cpp.js +816 -0
- package/src/frontends/csharp.js +759 -0
- package/src/frontends/go.js +770 -0
- package/src/frontends/index.js +5 -20
- package/src/frontends/python.js +689 -0
- package/src/frontends/scalars.js +20 -0
- package/src/language-registry.js +454 -0
- package/src/mapping.js +2 -1
- package/src/semantic/location.js +10 -0
- package/src/semantic/provenance.js +2 -2
- package/src/semantic/types.js +124 -1
- package/src/subprocess.js +232 -0
- package/src/timeout.js +12 -0
- package/src/toolchains.js +448 -0
- package/tsconfig.json +1 -0
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import Parser from "tree-sitter";
|
|
3
|
+
import CSharpLanguage from "tree-sitter-c-sharp/bindings/node/index.js";
|
|
4
|
+
import { missingType, parseFailure, SemantifoldDiagnostic, unsupportedSyntax } from "../diagnostic.js";
|
|
5
|
+
import { locationFromOffsets, moduleLocation, utf8ByteOffsetToUtf16Offset } from "../semantic/location.js";
|
|
6
|
+
import { withAdaptedOperation } from "../semantic/operators.js";
|
|
7
|
+
import { withParserRanges } from "../semantic/provenance.js";
|
|
8
|
+
import { hasOnlyUnicodeScalars } from "../semantic/scalars.js";
|
|
9
|
+
import { validateParsedModule } from "../semantic/validate.js";
|
|
10
|
+
import { sourceScalarType } from "./scalars.js";
|
|
11
|
+
const parser = new Parser();
|
|
12
|
+
parser.setLanguage(/** @type {import("tree-sitter").Language} */ ( /** @type {unknown} */(CSharpLanguage)));
|
|
13
|
+
const immutableMarker = "// @semantifold-immutable";
|
|
14
|
+
const checkedArithmetic = new WeakSet();
|
|
15
|
+
const csharpReservedIdentifiers = new Set([
|
|
16
|
+
"abstract", "add", "alias", "allows", "and", "as", "ascending", "async", "await", "base", "bool", "break",
|
|
17
|
+
"by", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default",
|
|
18
|
+
"delegate", "descending", "do", "double", "dynamic", "else", "enum", "equals", "event", "explicit", "extension", "extern",
|
|
19
|
+
"false", "field", "file", "finally", "fixed", "float", "for", "foreach", "from", "get", "global", "goto",
|
|
20
|
+
"group", "if", "implicit", "in", "init", "int", "interface", "internal", "into", "is", "join", "let", "lock",
|
|
21
|
+
"long", "managed", "nameof", "namespace", "new", "nint", "not", "notnull", "null", "nuint", "object", "on",
|
|
22
|
+
"operator", "or", "orderby", "out", "override", "params", "partial", "private", "protected", "public", "readonly",
|
|
23
|
+
"record", "ref", "remove", "required", "return", "sbyte", "scoped", "sealed", "select", "set", "short", "sizeof",
|
|
24
|
+
"stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong",
|
|
25
|
+
"unchecked", "unmanaged", "unsafe", "ushort", "using", "value", "var", "virtual", "void", "volatile", "when",
|
|
26
|
+
"where", "while", "with", "yield"
|
|
27
|
+
]);
|
|
28
|
+
const binaryOperations = new Map([
|
|
29
|
+
["+", "Add"], ["-", "Subtract"], ["*", "Multiply"], ["==", "Equal"], ["!=", "NotEqual"],
|
|
30
|
+
["<", "LessThan"], ["<=", "LessThanOrEqual"], [">", "GreaterThan"], [">=", "GreaterThanOrEqual"],
|
|
31
|
+
["&&", "And"], ["||", "Or"]
|
|
32
|
+
]);
|
|
33
|
+
/** @typedef {{comments: import("tree-sitter").SyntaxNode[], usedImmutableMarkers: Set<import("tree-sitter").SyntaxNode>}} CSharpContext */
|
|
34
|
+
/**
|
|
35
|
+
* Verifies one Tree-sitter binding index through the shared byte converter.
|
|
36
|
+
* @param {string} source - Complete source text.
|
|
37
|
+
* @param {number} index - Binding-reported UTF-16 index.
|
|
38
|
+
* @returns {number} Verified UTF-16 offset.
|
|
39
|
+
*/
|
|
40
|
+
function bindingIndexToUtf16Offset(source, index) {
|
|
41
|
+
if (!Number.isInteger(index) || index < 0 || index > source.length ||
|
|
42
|
+
index > 0 && index < source.length && /[\uD800-\uDBFF]/u.test(source[index - 1]) && /[\uDC00-\uDFFF]/u.test(source[index])) {
|
|
43
|
+
throw new RangeError(`Invalid Tree-sitter source index: ${index}`);
|
|
44
|
+
}
|
|
45
|
+
return utf8ByteOffsetToUtf16Offset(source, new TextEncoder().encode(source.slice(0, index)).length);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Finds the first unpaired UTF-16 surrogate.
|
|
49
|
+
* @param {string} source - Complete source text.
|
|
50
|
+
* @returns {number} Invalid offset, or -1.
|
|
51
|
+
*/
|
|
52
|
+
function firstLoneSurrogateOffset(source) {
|
|
53
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
54
|
+
const unit = source.charCodeAt(index);
|
|
55
|
+
if (unit >= 0xD800 && unit <= 0xDBFF) {
|
|
56
|
+
const next = source.charCodeAt(index + 1);
|
|
57
|
+
if (next >= 0xDC00 && next <= 0xDFFF)
|
|
58
|
+
index += 1;
|
|
59
|
+
else
|
|
60
|
+
return index;
|
|
61
|
+
}
|
|
62
|
+
else if (unit >= 0xDC00 && unit <= 0xDFFF)
|
|
63
|
+
return index;
|
|
64
|
+
}
|
|
65
|
+
return -1;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Converts one binding range to a semantic source location.
|
|
69
|
+
* @param {import("tree-sitter").SyntaxNode} node - Parser node.
|
|
70
|
+
* @param {string} filename - Source filename.
|
|
71
|
+
* @param {string} source - Complete source text.
|
|
72
|
+
* @returns {import("../semantic/types.js").SourceLocation} Exact location.
|
|
73
|
+
*/
|
|
74
|
+
function nodeLocation(node, filename, source) {
|
|
75
|
+
return locationFromOffsets(filename, source, bindingIndexToUtf16Offset(source, node.startIndex), bindingIndexToUtf16Offset(source, node.endIndex));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Requires one named grammar field.
|
|
79
|
+
* @param {import("tree-sitter").SyntaxNode} node - Field owner.
|
|
80
|
+
* @param {string} field - Grammar field name.
|
|
81
|
+
* @param {string} filename - Source filename.
|
|
82
|
+
* @param {string} source - Complete source text.
|
|
83
|
+
* @returns {import("tree-sitter").SyntaxNode} Required child.
|
|
84
|
+
*/
|
|
85
|
+
function requiredField(node, field, filename, source) {
|
|
86
|
+
const child = node.childForFieldName(field);
|
|
87
|
+
if (!child)
|
|
88
|
+
return unsupportedSyntax("csharp", `${node.type} without ${field}`, nodeLocation(node, filename, source));
|
|
89
|
+
return child;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Traverses every parser child and rejects explicit or propagated recovery.
|
|
93
|
+
* @param {import("tree-sitter").SyntaxNode} node - Current parser node.
|
|
94
|
+
* @param {string} filename - Source filename.
|
|
95
|
+
* @param {string} source - Complete source text.
|
|
96
|
+
* @returns {void}
|
|
97
|
+
*/
|
|
98
|
+
function validateParserTree(node, filename, source) {
|
|
99
|
+
if (node.hasError || node.isError || node.isMissing) {
|
|
100
|
+
throw new SemantifoldDiagnostic({
|
|
101
|
+
code: "PARSE_ERROR",
|
|
102
|
+
language: "csharp",
|
|
103
|
+
location: nodeLocation(node, filename, source),
|
|
104
|
+
message: `Tree-sitter exposed recovery at '${node.type}'.`
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
for (let index = 0; index < node.childCount; index += 1) {
|
|
108
|
+
const child = node.child(index);
|
|
109
|
+
if (!child)
|
|
110
|
+
throw new Error(`Tree-sitter omitted child ${index} of ${node.type}.`);
|
|
111
|
+
validateParserTree(child, filename, source);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Selects named semantic children while retaining comments in the parser tree.
|
|
116
|
+
* @param {import("tree-sitter").SyntaxNode} node - Parent parser node.
|
|
117
|
+
* @returns {import("tree-sitter").SyntaxNode[]} Non-comment named children.
|
|
118
|
+
*/
|
|
119
|
+
function semanticChildren(node) {
|
|
120
|
+
return node.namedChildren.filter((child) => child.type != "comment");
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Validates one identifier against the exact C# source profile.
|
|
124
|
+
* @param {import("tree-sitter").SyntaxNode} node - Identifier node.
|
|
125
|
+
* @param {string} role - Diagnostic role.
|
|
126
|
+
* @param {string} filename - Source filename.
|
|
127
|
+
* @param {string} source - Complete source text.
|
|
128
|
+
* @returns {string} Accepted identifier.
|
|
129
|
+
*/
|
|
130
|
+
function identifier(node, role, filename, source) {
|
|
131
|
+
const name = node.text;
|
|
132
|
+
if (node.type != "identifier" || !/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name) || csharpReservedIdentifiers.has(name)) {
|
|
133
|
+
return unsupportedSyntax("csharp", `${role} identifier '${name}'`, nodeLocation(node, filename, source));
|
|
134
|
+
}
|
|
135
|
+
return name;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Converts one exact supported scalar type.
|
|
139
|
+
* @param {import("tree-sitter").SyntaxNode | null} node - Type node, if present.
|
|
140
|
+
* @param {string} subject - Typed subject for diagnostics.
|
|
141
|
+
* @param {import("../semantic/types.js").SourceLocation} ownerLocation - Owning declaration location.
|
|
142
|
+
* @param {string} filename - Source filename.
|
|
143
|
+
* @param {string} source - Complete source text.
|
|
144
|
+
* @param {boolean} [allowVar] - Whether inferred `var` produces MISSING_TYPE.
|
|
145
|
+
* @returns {import("../semantic/types.js").TypeReference} Semantic scalar type.
|
|
146
|
+
*/
|
|
147
|
+
function convertType(node, subject, ownerLocation, filename, source, allowVar = false) {
|
|
148
|
+
if (!node)
|
|
149
|
+
return missingType("csharp", subject, ownerLocation);
|
|
150
|
+
const location = nodeLocation(node, filename, source);
|
|
151
|
+
if (allowVar && node.text == "var")
|
|
152
|
+
return missingType("csharp", subject, ownerLocation);
|
|
153
|
+
const type = sourceScalarType("csharp", node.text, location);
|
|
154
|
+
if (!type || !["predefined_type", "qualified_name"].includes(node.type)) {
|
|
155
|
+
return unsupportedSyntax("csharp", `unsupported scalar type '${node.text}'`, location);
|
|
156
|
+
}
|
|
157
|
+
return type;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Finds exactly one accepted operator token owned by a parser node.
|
|
161
|
+
* @param {import("tree-sitter").SyntaxNode} node - Operation node.
|
|
162
|
+
* @param {Set<string>} spellings - Accepted operator spellings.
|
|
163
|
+
* @param {string} filename - Source filename.
|
|
164
|
+
* @param {string} source - Complete source text.
|
|
165
|
+
* @returns {import("tree-sitter").SyntaxNode} Operator token.
|
|
166
|
+
*/
|
|
167
|
+
function operatorToken(node, spellings, filename, source) {
|
|
168
|
+
const field = node.childForFieldName("operator");
|
|
169
|
+
const candidates = field ? [field] : node.children.filter((child) => !child.isNamed && spellings.has(child.type));
|
|
170
|
+
if (candidates.length != 1 || !spellings.has(candidates[0].type)) {
|
|
171
|
+
return unsupportedSyntax("csharp", `${node.type} operator`, nodeLocation(node, filename, source));
|
|
172
|
+
}
|
|
173
|
+
return candidates[0];
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Converts one expression and records exact checked-wrapper ownership.
|
|
177
|
+
* @param {import("tree-sitter").SyntaxNode} node - Expression node.
|
|
178
|
+
* @param {string} filename - Source filename.
|
|
179
|
+
* @param {string} source - Complete source text.
|
|
180
|
+
* @param {boolean} [checkedRoot] - Whether the node is the direct checked-expression operand.
|
|
181
|
+
* @returns {import("../semantic/types.js").Expression} Semantic expression.
|
|
182
|
+
*/
|
|
183
|
+
function convertExpression(node, filename, source, checkedRoot = false) {
|
|
184
|
+
const location = nodeLocation(node, filename, source);
|
|
185
|
+
if (node.type == "parenthesized_expression") {
|
|
186
|
+
const children = semanticChildren(node);
|
|
187
|
+
if (children.length != 1)
|
|
188
|
+
return unsupportedSyntax("csharp", node.type, location);
|
|
189
|
+
return convertExpression(children[0], filename, source);
|
|
190
|
+
}
|
|
191
|
+
if (node.type == "checked_expression") {
|
|
192
|
+
const children = semanticChildren(node);
|
|
193
|
+
const checkedTokens = node.children.filter((child) => !child.isNamed && child.type == "checked");
|
|
194
|
+
if (checkedTokens.length != 1 || children.length != 1 ||
|
|
195
|
+
!["binary_expression", "prefix_unary_expression"].includes(children[0].type)) {
|
|
196
|
+
return unsupportedSyntax("csharp", "checked expression shape", location);
|
|
197
|
+
}
|
|
198
|
+
const expression = convertExpression(children[0], filename, source, true);
|
|
199
|
+
checkedArithmetic.add(expression);
|
|
200
|
+
expression.location = location;
|
|
201
|
+
return expression;
|
|
202
|
+
}
|
|
203
|
+
if (node.type == "identifier") {
|
|
204
|
+
const name = identifier(node, "reference", filename, source);
|
|
205
|
+
return withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location, name }, { name: location });
|
|
206
|
+
}
|
|
207
|
+
if (node.type == "integer_literal") {
|
|
208
|
+
if (!/^(?:0|[1-9][0-9]*)L$/u.test(node.text))
|
|
209
|
+
return unsupportedSyntax("csharp", "noncanonical long literal", location);
|
|
210
|
+
const value = Number(BigInt(node.text.slice(0, -1)));
|
|
211
|
+
if (!Number.isSafeInteger(value))
|
|
212
|
+
return unsupportedSyntax("csharp", "non-safe integer literal", location);
|
|
213
|
+
return withParserRanges({ kind: /** @type {const} */ ("IntegerLiteral"), location, value }, { literal: location });
|
|
214
|
+
}
|
|
215
|
+
if (node.type == "boolean_literal") {
|
|
216
|
+
if (node.text != "true" && node.text != "false")
|
|
217
|
+
return unsupportedSyntax("csharp", "boolean literal", location);
|
|
218
|
+
return withParserRanges({ kind: /** @type {const} */ ("BooleanLiteral"), location, value: node.text == "true" }, { literal: location });
|
|
219
|
+
}
|
|
220
|
+
if (node.type == "string_literal") {
|
|
221
|
+
return withParserRanges({ kind: /** @type {const} */ ("StringLiteral"), location, value: decodeString(node, filename, source) }, {
|
|
222
|
+
literal: location
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
if (node.type == "prefix_unary_expression") {
|
|
226
|
+
const children = semanticChildren(node);
|
|
227
|
+
const operator = operatorToken(node, new Set(["!", "-"]), filename, source);
|
|
228
|
+
if (children.length != 1 || operator.type == "-" && !checkedRoot) {
|
|
229
|
+
return unsupportedSyntax("csharp", "unwrapped or malformed unary expression", location);
|
|
230
|
+
}
|
|
231
|
+
const expression = /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(withAdaptedOperation(withParserRanges({
|
|
232
|
+
kind: "UnaryExpression",
|
|
233
|
+
location,
|
|
234
|
+
operand: convertExpression(children[0], filename, source)
|
|
235
|
+
}, { operator: nodeLocation(operator, filename, source) }), operator.type == "!" ? "Not" : "Negate")));
|
|
236
|
+
if (checkedRoot)
|
|
237
|
+
checkedArithmetic.add(expression);
|
|
238
|
+
return expression;
|
|
239
|
+
}
|
|
240
|
+
if (node.type == "binary_expression") {
|
|
241
|
+
const leftNode = requiredField(node, "left", filename, source);
|
|
242
|
+
const rightNode = requiredField(node, "right", filename, source);
|
|
243
|
+
const operator = operatorToken(node, new Set(binaryOperations.keys()), filename, source);
|
|
244
|
+
const adapted = binaryOperations.get(operator.type);
|
|
245
|
+
if (!adapted || semanticChildren(node).length != 2 || ["-", "*"].includes(operator.type) && !checkedRoot) {
|
|
246
|
+
return unsupportedSyntax("csharp", "unwrapped or unsupported binary expression", location);
|
|
247
|
+
}
|
|
248
|
+
const expression = /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(withAdaptedOperation(withParserRanges({
|
|
249
|
+
kind: "BinaryExpression",
|
|
250
|
+
left: convertExpression(leftNode, filename, source),
|
|
251
|
+
location,
|
|
252
|
+
right: convertExpression(rightNode, filename, source)
|
|
253
|
+
}, { operator: nodeLocation(operator, filename, source) }), /** @type {import("../semantic/operators.js").AdaptedOperation} */ (adapted))));
|
|
254
|
+
if (checkedRoot)
|
|
255
|
+
checkedArithmetic.add(expression);
|
|
256
|
+
return expression;
|
|
257
|
+
}
|
|
258
|
+
if (node.type == "invocation_expression") {
|
|
259
|
+
const calleeNode = requiredField(node, "function", filename, source);
|
|
260
|
+
const argumentsNode = requiredField(node, "arguments", filename, source);
|
|
261
|
+
if (calleeNode.type != "identifier" || argumentsNode.type != "argument_list") {
|
|
262
|
+
return unsupportedSyntax("csharp", "qualified or dynamic call", location);
|
|
263
|
+
}
|
|
264
|
+
const arguments_ = /** @type {import("../semantic/types.js").Expression[]} */ (semanticChildren(argumentsNode).map((argument) => convertArgument(argument, filename, source)));
|
|
265
|
+
const callee = identifier(calleeNode, "callee", filename, source);
|
|
266
|
+
return withParserRanges({ arguments: arguments_, callee, kind: /** @type {const} */ ("CallExpression"), location }, {
|
|
267
|
+
callee: nodeLocation(calleeNode, filename, source)
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
return unsupportedSyntax("csharp", node.type, location);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Converts one positional argument.
|
|
274
|
+
* @param {import("tree-sitter").SyntaxNode} node - Argument node.
|
|
275
|
+
* @param {string} filename - Source filename.
|
|
276
|
+
* @param {string} source - Complete source text.
|
|
277
|
+
* @returns {import("../semantic/types.js").Expression} Semantic argument expression.
|
|
278
|
+
*/
|
|
279
|
+
function convertArgument(node, filename, source) {
|
|
280
|
+
const children = semanticChildren(node);
|
|
281
|
+
if (node.type != "argument" || children.length != 1 || node.children.some((child) => !child.isNamed && child.type == ":")) {
|
|
282
|
+
return unsupportedSyntax("csharp", "non-positional argument", nodeLocation(node, filename, source));
|
|
283
|
+
}
|
|
284
|
+
return convertExpression(children[0], filename, source);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Decodes one ordinary C# string literal without interpolation or raw forms.
|
|
288
|
+
* @param {import("tree-sitter").SyntaxNode} node - String literal node.
|
|
289
|
+
* @param {string} filename - Source filename.
|
|
290
|
+
* @param {string} source - Complete source text.
|
|
291
|
+
* @returns {string} Decoded Unicode scalar string.
|
|
292
|
+
*/
|
|
293
|
+
function decodeString(node, filename, source) {
|
|
294
|
+
const location = nodeLocation(node, filename, source);
|
|
295
|
+
const text = node.text;
|
|
296
|
+
if (!text.startsWith("\"") || !text.endsWith("\"") || text.startsWith("\"\"\"") || /[\r\n]/u.test(text)) {
|
|
297
|
+
return unsupportedSyntax("csharp", "noncanonical string literal", location);
|
|
298
|
+
}
|
|
299
|
+
let decoded = "";
|
|
300
|
+
const simple = new Map([["\"", "\""], ["\\", "\\"], ["0", "\0"], ["a", "\u0007"], ["b", "\b"], ["f", "\f"],
|
|
301
|
+
["n", "\n"], ["r", "\r"], ["t", "\t"], ["v", "\v"]]);
|
|
302
|
+
for (let index = 1; index < text.length - 1; index += 1) {
|
|
303
|
+
const character = text[index];
|
|
304
|
+
if (character != "\\") {
|
|
305
|
+
decoded += character;
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const escape = text[++index];
|
|
309
|
+
if (escape === undefined)
|
|
310
|
+
return unsupportedSyntax("csharp", "invalid string escape", location);
|
|
311
|
+
if (simple.has(escape)) {
|
|
312
|
+
decoded += simple.get(escape);
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
const width = escape == "u" ? 4 : escape == "U" ? 8 : 0;
|
|
316
|
+
const digits = text.slice(index + 1, index + 1 + width);
|
|
317
|
+
if (!width || digits.length != width || !/^[0-9A-Fa-f]+$/u.test(digits)) {
|
|
318
|
+
return unsupportedSyntax("csharp", "unsupported string escape", location);
|
|
319
|
+
}
|
|
320
|
+
index += width;
|
|
321
|
+
const value = Number.parseInt(digits, 16);
|
|
322
|
+
if (escape == "U" && (value > 0x10FFFF || value >= 0xD800 && value <= 0xDFFF)) {
|
|
323
|
+
return unsupportedSyntax("csharp", "invalid Unicode string escape", location);
|
|
324
|
+
}
|
|
325
|
+
decoded += escape == "U" ? String.fromCodePoint(value) : String.fromCharCode(value);
|
|
326
|
+
}
|
|
327
|
+
if (!hasOnlyUnicodeScalars(decoded))
|
|
328
|
+
return unsupportedSyntax("csharp", "invalid Unicode string literal", location);
|
|
329
|
+
return decoded;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Converts one exact initialized local declaration.
|
|
333
|
+
* @param {import("tree-sitter").SyntaxNode} node - Local statement node.
|
|
334
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
335
|
+
* @param {string} filename - Source filename.
|
|
336
|
+
* @param {string} source - Complete source text.
|
|
337
|
+
* @returns {import("../semantic/types.js").LocalDeclaration} Semantic declaration.
|
|
338
|
+
*/
|
|
339
|
+
function convertLocal(node, context, filename, source) {
|
|
340
|
+
const location = nodeLocation(node, filename, source);
|
|
341
|
+
const declaration = semanticChildren(node)[0];
|
|
342
|
+
if (semanticChildren(node).length != 1 || declaration?.type != "variable_declaration") {
|
|
343
|
+
return unsupportedSyntax("csharp", node.type, location);
|
|
344
|
+
}
|
|
345
|
+
const typeNode = declaration.childForFieldName("type");
|
|
346
|
+
const declarators = semanticChildren(declaration).filter((child) => child.type == "variable_declarator");
|
|
347
|
+
if (declarators.length != 1 || semanticChildren(declaration).length != 2) {
|
|
348
|
+
return unsupportedSyntax("csharp", "local declaration shape", location);
|
|
349
|
+
}
|
|
350
|
+
const declarator = declarators[0];
|
|
351
|
+
const nameNode = requiredField(declarator, "name", filename, source);
|
|
352
|
+
const values = semanticChildren(declarator).filter((child) => child.id != nameNode.id);
|
|
353
|
+
if (values.length != 1)
|
|
354
|
+
return unsupportedSyntax("csharp", "local without one initializer", location);
|
|
355
|
+
const name = identifier(nameNode, "local", filename, source);
|
|
356
|
+
if (name == "System")
|
|
357
|
+
return unsupportedSyntax("csharp", "local captures System", nodeLocation(nameNode, filename, source));
|
|
358
|
+
const operator = operatorToken(declarator, new Set(["="]), filename, source);
|
|
359
|
+
const mutable = !takeImmutableMarker(node, context);
|
|
360
|
+
return withParserRanges({
|
|
361
|
+
initializer: convertExpression(values[0], filename, source),
|
|
362
|
+
kind: /** @type {const} */ ("LocalDeclaration"),
|
|
363
|
+
location,
|
|
364
|
+
mutable,
|
|
365
|
+
name,
|
|
366
|
+
type: convertType(typeNode, `Local '${name}'`, location, filename, source, true)
|
|
367
|
+
}, { name: nodeLocation(nameNode, filename, source), operator: nodeLocation(operator, filename, source) });
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Claims an exactly adjacent immutable-local carrier if present.
|
|
371
|
+
* @param {import("tree-sitter").SyntaxNode} node - Local declaration node.
|
|
372
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
373
|
+
* @returns {boolean} Whether the local is immutable.
|
|
374
|
+
*/
|
|
375
|
+
function takeImmutableMarker(node, context) {
|
|
376
|
+
const marker = context.comments.find((comment) => comment.text == immutableMarker &&
|
|
377
|
+
comment.endPosition.row + 1 == node.startPosition.row && comment.startPosition.column == node.startPosition.column);
|
|
378
|
+
if (!marker)
|
|
379
|
+
return false;
|
|
380
|
+
context.usedImmutableMarkers.add(marker);
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Converts one supported C# statement.
|
|
385
|
+
* @param {import("tree-sitter").SyntaxNode} node - Statement node.
|
|
386
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
387
|
+
* @param {string} filename - Source filename.
|
|
388
|
+
* @param {string} source - Complete source text.
|
|
389
|
+
* @returns {import("../semantic/types.js").Statement} Semantic statement.
|
|
390
|
+
*/
|
|
391
|
+
function convertStatement(node, context, filename, source) {
|
|
392
|
+
const location = nodeLocation(node, filename, source);
|
|
393
|
+
if (node.type == "local_declaration_statement")
|
|
394
|
+
return convertLocal(node, context, filename, source);
|
|
395
|
+
if (node.type == "return_statement") {
|
|
396
|
+
const children = semanticChildren(node);
|
|
397
|
+
if (children.length != 1)
|
|
398
|
+
return unsupportedSyntax("csharp", "return without one expression", location);
|
|
399
|
+
return { expression: convertExpression(children[0], filename, source), kind: /** @type {const} */ ("ReturnStatement"), location };
|
|
400
|
+
}
|
|
401
|
+
if (node.type == "if_statement")
|
|
402
|
+
return convertIf(node, context, filename, source);
|
|
403
|
+
if (node.type == "expression_statement") {
|
|
404
|
+
const children = semanticChildren(node);
|
|
405
|
+
if (children.length != 1)
|
|
406
|
+
return unsupportedSyntax("csharp", node.type, location);
|
|
407
|
+
if (children[0].type == "assignment_expression")
|
|
408
|
+
return convertAssignment(children[0], filename, source, location);
|
|
409
|
+
return convertPrint(children[0], filename, source, location);
|
|
410
|
+
}
|
|
411
|
+
return unsupportedSyntax("csharp", node.type, location);
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Converts one plain identifier assignment.
|
|
415
|
+
* @param {import("tree-sitter").SyntaxNode} node - Assignment expression node.
|
|
416
|
+
* @param {string} filename - Source filename.
|
|
417
|
+
* @param {string} source - Complete source text.
|
|
418
|
+
* @param {import("../semantic/types.js").SourceLocation} location - Owning statement location.
|
|
419
|
+
* @returns {import("../semantic/types.js").AssignmentStatement} Semantic assignment.
|
|
420
|
+
*/
|
|
421
|
+
function convertAssignment(node, filename, source, location) {
|
|
422
|
+
const left = requiredField(node, "left", filename, source);
|
|
423
|
+
const right = requiredField(node, "right", filename, source);
|
|
424
|
+
const operator = operatorToken(node, new Set(["="]), filename, source);
|
|
425
|
+
if (left.type != "identifier")
|
|
426
|
+
return unsupportedSyntax("csharp", "assignment target", nodeLocation(left, filename, source));
|
|
427
|
+
const name = identifier(left, "assignment target", filename, source);
|
|
428
|
+
const nameLocation = nodeLocation(left, filename, source);
|
|
429
|
+
return withParserRanges({
|
|
430
|
+
expression: convertExpression(right, filename, source),
|
|
431
|
+
kind: /** @type {const} */ ("AssignmentStatement"),
|
|
432
|
+
location,
|
|
433
|
+
target: withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location: nameLocation, name }, { name: nameLocation })
|
|
434
|
+
}, { operator: nodeLocation(operator, filename, source) });
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Converts the exact System.Console.WriteLine print scaffold.
|
|
438
|
+
* @param {import("tree-sitter").SyntaxNode} node - Invocation node.
|
|
439
|
+
* @param {string} filename - Source filename.
|
|
440
|
+
* @param {string} source - Complete source text.
|
|
441
|
+
* @param {import("../semantic/types.js").SourceLocation} location - Owning statement location.
|
|
442
|
+
* @returns {import("../semantic/types.js").PrintStatement} Semantic print statement.
|
|
443
|
+
*/
|
|
444
|
+
function convertPrint(node, filename, source, location) {
|
|
445
|
+
if (node.type != "invocation_expression")
|
|
446
|
+
return unsupportedSyntax("csharp", "expression statement other than print", nodeLocation(node, filename, source));
|
|
447
|
+
const callee = requiredField(node, "function", filename, source);
|
|
448
|
+
const argumentsNode = requiredField(node, "arguments", filename, source);
|
|
449
|
+
const arguments_ = semanticChildren(argumentsNode);
|
|
450
|
+
if (!isPrintReceiver(callee) || argumentsNode.type != "argument_list" || arguments_.length != 1) {
|
|
451
|
+
return unsupportedSyntax("csharp", "print call shape", nodeLocation(node, filename, source));
|
|
452
|
+
}
|
|
453
|
+
return { expression: convertArgument(arguments_[0], filename, source), kind: /** @type {const} */ ("PrintStatement"), location };
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Recognizes only the fully qualified print receiver.
|
|
457
|
+
* @param {import("tree-sitter").SyntaxNode} node - Candidate callee.
|
|
458
|
+
* @returns {boolean} Whether the callee is the exact print receiver.
|
|
459
|
+
*/
|
|
460
|
+
function isPrintReceiver(node) {
|
|
461
|
+
if (node.type != "member_access_expression")
|
|
462
|
+
return false;
|
|
463
|
+
const outerExpression = node.childForFieldName("expression");
|
|
464
|
+
const outerName = node.childForFieldName("name");
|
|
465
|
+
if (outerName?.text != "WriteLine" || outerExpression?.type != "member_access_expression")
|
|
466
|
+
return false;
|
|
467
|
+
return outerExpression.childForFieldName("expression")?.type == "identifier" &&
|
|
468
|
+
outerExpression.childForFieldName("expression")?.text == "System" && outerExpression.childForFieldName("name")?.text == "Console";
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Converts one braced conditional and optional alternate.
|
|
472
|
+
* @param {import("tree-sitter").SyntaxNode} node - If-statement node.
|
|
473
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
474
|
+
* @param {string} filename - Source filename.
|
|
475
|
+
* @param {string} source - Complete source text.
|
|
476
|
+
* @returns {import("../semantic/types.js").IfStatement} Semantic conditional.
|
|
477
|
+
*/
|
|
478
|
+
function convertIf(node, context, filename, source) {
|
|
479
|
+
const location = nodeLocation(node, filename, source);
|
|
480
|
+
const condition = requiredField(node, "condition", filename, source);
|
|
481
|
+
const consequence = requiredField(node, "consequence", filename, source);
|
|
482
|
+
const alternative = node.childForFieldName("alternative");
|
|
483
|
+
return {
|
|
484
|
+
...(alternative ? { alternate: alternative.type == "if_statement"
|
|
485
|
+
? { kind: /** @type {const} */ ("Block"), location: nodeLocation(alternative, filename, source),
|
|
486
|
+
statements: [convertIf(alternative, context, filename, source)] }
|
|
487
|
+
: convertBlock(alternative, context, filename, source) } : {}),
|
|
488
|
+
condition: convertExpression(condition, filename, source),
|
|
489
|
+
consequent: convertBlock(consequence, context, filename, source),
|
|
490
|
+
kind: /** @type {const} */ ("IfStatement"),
|
|
491
|
+
location
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Converts one lexical C# block.
|
|
496
|
+
* @param {import("tree-sitter").SyntaxNode} node - Block node.
|
|
497
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
498
|
+
* @param {string} filename - Source filename.
|
|
499
|
+
* @param {string} source - Complete source text.
|
|
500
|
+
* @returns {import("../semantic/types.js").Block} Semantic block.
|
|
501
|
+
*/
|
|
502
|
+
function convertBlock(node, context, filename, source) {
|
|
503
|
+
const location = nodeLocation(node, filename, source);
|
|
504
|
+
if (node.type != "block")
|
|
505
|
+
return unsupportedSyntax("csharp", node.type, location);
|
|
506
|
+
return { kind: /** @type {const} */ ("Block"), location,
|
|
507
|
+
statements: semanticChildren(node).map((statement) => convertStatement(statement, context, filename, source)) };
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Converts one exact private static semantic method.
|
|
511
|
+
* @param {import("tree-sitter").SyntaxNode} node - Method node.
|
|
512
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
513
|
+
* @param {string} filename - Source filename.
|
|
514
|
+
* @param {string} source - Complete source text.
|
|
515
|
+
* @returns {import("../semantic/types.js").FunctionDeclaration} Semantic function.
|
|
516
|
+
*/
|
|
517
|
+
function convertFunction(node, context, filename, source) {
|
|
518
|
+
const location = nodeLocation(node, filename, source);
|
|
519
|
+
const children = semanticChildren(node);
|
|
520
|
+
const modifiers = children.filter((child) => child.type == "modifier");
|
|
521
|
+
if (node.type != "method_declaration" || modifiers.map(({ text }) => text).join(" ") != "private static" ||
|
|
522
|
+
children.length != 6 || node.childForFieldName("type_parameters") || node.childForFieldName("constraints") ||
|
|
523
|
+
!node.childForFieldName("body")) {
|
|
524
|
+
return unsupportedSyntax("csharp", "method scaffolding", location);
|
|
525
|
+
}
|
|
526
|
+
const nameNode = requiredField(node, "name", filename, source);
|
|
527
|
+
const parametersNode = requiredField(node, "parameters", filename, source);
|
|
528
|
+
const returnNode = requiredField(node, "returns", filename, source);
|
|
529
|
+
const bodyNode = requiredField(node, "body", filename, source);
|
|
530
|
+
const name = identifier(nameNode, "function", filename, source);
|
|
531
|
+
if (["Main", "Program", "System"].includes(name)) {
|
|
532
|
+
return unsupportedSyntax("csharp", `reserved semantic method '${name}'`, nodeLocation(nameNode, filename, source));
|
|
533
|
+
}
|
|
534
|
+
const parameterNodes = semanticChildren(parametersNode);
|
|
535
|
+
if (parameterNodes.length != 2 || parameterNodes.some((parameter) => parameter.type != "parameter")) {
|
|
536
|
+
return unsupportedSyntax("csharp", "function parameter count or shape", nodeLocation(parametersNode, filename, source));
|
|
537
|
+
}
|
|
538
|
+
const parameters = parameterNodes.map((parameterNode) => convertParameter(parameterNode, filename, source));
|
|
539
|
+
return withParserRanges({
|
|
540
|
+
body: convertBlock(bodyNode, context, filename, source),
|
|
541
|
+
kind: /** @type {const} */ ("FunctionDeclaration"),
|
|
542
|
+
location,
|
|
543
|
+
name,
|
|
544
|
+
parameters,
|
|
545
|
+
returnType: convertType(returnNode, `Function '${name}' return`, location, filename, source)
|
|
546
|
+
}, { name: nodeLocation(nameNode, filename, source) });
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Converts one explicitly typed unmodified parameter.
|
|
550
|
+
* @param {import("tree-sitter").SyntaxNode} node - Parameter node.
|
|
551
|
+
* @param {string} filename - Source filename.
|
|
552
|
+
* @param {string} source - Complete source text.
|
|
553
|
+
* @returns {import("../semantic/types.js").Parameter} Semantic parameter.
|
|
554
|
+
*/
|
|
555
|
+
function convertParameter(node, filename, source) {
|
|
556
|
+
const location = nodeLocation(node, filename, source);
|
|
557
|
+
const nameNode = requiredField(node, "name", filename, source);
|
|
558
|
+
const typeNode = node.childForFieldName("type");
|
|
559
|
+
if (semanticChildren(node).length != 2)
|
|
560
|
+
return unsupportedSyntax("csharp", "parameter modifiers or defaults", location);
|
|
561
|
+
const name = identifier(nameNode, "parameter", filename, source);
|
|
562
|
+
if (name == "System")
|
|
563
|
+
return unsupportedSyntax("csharp", "parameter captures System", nodeLocation(nameNode, filename, source));
|
|
564
|
+
return withParserRanges({
|
|
565
|
+
kind: /** @type {const} */ ("Parameter"), location, name,
|
|
566
|
+
type: convertType(typeNode, `Parameter '${name}'`, location, filename, source)
|
|
567
|
+
}, { name: nodeLocation(nameNode, filename, source) });
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Converts the exact final zero-argument Main method.
|
|
571
|
+
* @param {import("tree-sitter").SyntaxNode} node - Main method node.
|
|
572
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
573
|
+
* @param {string} filename - Source filename.
|
|
574
|
+
* @param {string} source - Complete source text.
|
|
575
|
+
* @returns {import("../semantic/types.js").EntryPoint} Semantic entry point.
|
|
576
|
+
*/
|
|
577
|
+
function convertMain(node, context, filename, source) {
|
|
578
|
+
const location = nodeLocation(node, filename, source);
|
|
579
|
+
const children = semanticChildren(node);
|
|
580
|
+
const modifiers = children.filter((child) => child.type == "modifier");
|
|
581
|
+
const name = requiredField(node, "name", filename, source);
|
|
582
|
+
const returns = requiredField(node, "returns", filename, source);
|
|
583
|
+
const parameters = requiredField(node, "parameters", filename, source);
|
|
584
|
+
const body = requiredField(node, "body", filename, source);
|
|
585
|
+
if (children.length != 6 || modifiers.map(({ text }) => text).join(" ") != "private static" || name.text != "Main" || returns.text != "void" ||
|
|
586
|
+
semanticChildren(parameters).length != 0)
|
|
587
|
+
return unsupportedSyntax("csharp", "Main scaffolding", location);
|
|
588
|
+
return { body: convertBlock(body, context, filename, source), kind: /** @type {const} */ ("EntryPoint"), location };
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Requires exactly one checked wrapper around every integer arithmetic root.
|
|
592
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Resolved semantic module.
|
|
593
|
+
* @returns {void}
|
|
594
|
+
*/
|
|
595
|
+
function validateCheckedArithmetic(module) {
|
|
596
|
+
/** @type {import("../semantic/types.js").Expression[]} */
|
|
597
|
+
const expressions = [];
|
|
598
|
+
/**
|
|
599
|
+
* Collects expressions recursively.
|
|
600
|
+
* @param {import("../semantic/types.js").Expression} expression - Current expression.
|
|
601
|
+
* @returns {void}
|
|
602
|
+
*/
|
|
603
|
+
const visitExpression = (expression) => {
|
|
604
|
+
expressions.push(expression);
|
|
605
|
+
if (expression.kind == "UnaryExpression")
|
|
606
|
+
visitExpression(expression.operand);
|
|
607
|
+
else if (expression.kind == "BinaryExpression") {
|
|
608
|
+
visitExpression(expression.left);
|
|
609
|
+
visitExpression(expression.right);
|
|
610
|
+
}
|
|
611
|
+
else if (expression.kind == "CallExpression")
|
|
612
|
+
expression.arguments.forEach(visitExpression);
|
|
613
|
+
};
|
|
614
|
+
/**
|
|
615
|
+
* Collects expressions from a semantic block.
|
|
616
|
+
* @param {import("../semantic/types.js").Block} block - Current block.
|
|
617
|
+
* @returns {void}
|
|
618
|
+
*/
|
|
619
|
+
const visitBlock = (block) => block.statements.forEach((statement) => {
|
|
620
|
+
if (statement.kind == "LocalDeclaration")
|
|
621
|
+
visitExpression(statement.initializer);
|
|
622
|
+
else if (statement.kind == "AssignmentStatement" || statement.kind == "PrintStatement" || statement.kind == "ReturnStatement") {
|
|
623
|
+
visitExpression(statement.expression);
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
visitExpression(statement.condition);
|
|
627
|
+
visitBlock(statement.consequent);
|
|
628
|
+
if (statement.alternate)
|
|
629
|
+
visitBlock(statement.alternate);
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
module.functions.forEach((declaration) => visitBlock(declaration.body));
|
|
633
|
+
visitBlock(module.entryPoint.body);
|
|
634
|
+
for (const expression of expressions) {
|
|
635
|
+
const arithmetic = expression.kind == "UnaryExpression" && expression.operation == "IntegerNegate" ||
|
|
636
|
+
expression.kind == "BinaryExpression" && ["IntegerAdd", "IntegerSubtract", "IntegerMultiply"].includes(expression.operation);
|
|
637
|
+
if (arithmetic != checkedArithmetic.has(expression)) {
|
|
638
|
+
return unsupportedSyntax("csharp", arithmetic ? "integer arithmetic without exact checked wrapper" : "checked non-integer expression", expression.location);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Parses the strict Task 017 C# profile.
|
|
644
|
+
* @param {{filename: string, source: string}} input - Parser input.
|
|
645
|
+
* @returns {import("../semantic/types.js").SemanticModule} Semantic module.
|
|
646
|
+
*/
|
|
647
|
+
export function parseCSharp({ filename, source }) {
|
|
648
|
+
if (!hasOnlyUnicodeScalars(source)) {
|
|
649
|
+
const invalidOffset = firstLoneSurrogateOffset(source);
|
|
650
|
+
throw new SemantifoldDiagnostic({ code: "PARSE_ERROR", language: "csharp",
|
|
651
|
+
location: locationFromOffsets(filename, source, invalidOffset, invalidOffset + 1),
|
|
652
|
+
message: "C# source contains an invalid lone UTF-16 surrogate." });
|
|
653
|
+
}
|
|
654
|
+
let tree;
|
|
655
|
+
try {
|
|
656
|
+
tree = parser.parse(source);
|
|
657
|
+
}
|
|
658
|
+
catch (error) {
|
|
659
|
+
return parseFailure("csharp", error);
|
|
660
|
+
}
|
|
661
|
+
const root = tree.rootNode;
|
|
662
|
+
validateParserTree(root, filename, source);
|
|
663
|
+
if (root.type != "compilation_unit")
|
|
664
|
+
throw new Error(`Tree-sitter returned C# root '${root.type}'.`);
|
|
665
|
+
const children = semanticChildren(root);
|
|
666
|
+
const location = moduleLocation(filename, source);
|
|
667
|
+
if (children.length != 3 || children[0].type != "preproc_nullable" ||
|
|
668
|
+
!/^#nullable enable(?:(?:\r\n|\n|\r))+$/u.test(children[0].text) ||
|
|
669
|
+
children[1].type != "file_scoped_namespace_declaration" || children[2].type != "class_declaration") {
|
|
670
|
+
return unsupportedSyntax("csharp", "compilation-unit scaffolding", location);
|
|
671
|
+
}
|
|
672
|
+
const namespaceName = requiredField(children[1], "name", filename, source);
|
|
673
|
+
if (namespaceName.text != "Semantifold.Generated") {
|
|
674
|
+
return unsupportedSyntax("csharp", "namespace scaffolding", nodeLocation(children[1], filename, source));
|
|
675
|
+
}
|
|
676
|
+
const classNode = children[2];
|
|
677
|
+
const className = requiredField(classNode, "name", filename, source);
|
|
678
|
+
const classBody = requiredField(classNode, "body", filename, source);
|
|
679
|
+
const classChildren = semanticChildren(classNode);
|
|
680
|
+
const classModifiers = classChildren.filter((child) => child.type == "modifier");
|
|
681
|
+
if (classChildren.length != 4 || className.text != "Program" ||
|
|
682
|
+
classModifiers.map(({ text }) => text).join(" ") != "internal static") {
|
|
683
|
+
return unsupportedSyntax("csharp", "Program class scaffolding", nodeLocation(classNode, filename, source));
|
|
684
|
+
}
|
|
685
|
+
const members = semanticChildren(classBody);
|
|
686
|
+
if (members.length < 2 || members.some((member) => member.type != "method_declaration")) {
|
|
687
|
+
return unsupportedSyntax("csharp", "Program members", nodeLocation(classBody, filename, source));
|
|
688
|
+
}
|
|
689
|
+
const mainNodes = members.filter((member) => member.childForFieldName("name")?.text == "Main");
|
|
690
|
+
if (mainNodes.length != 1 || members.at(-1)?.id != mainNodes[0].id) {
|
|
691
|
+
return unsupportedSyntax("csharp", "Main ordering", nodeLocation(classBody, filename, source));
|
|
692
|
+
}
|
|
693
|
+
const comments = root.descendantsOfType("comment");
|
|
694
|
+
const context = { comments, usedImmutableMarkers: new Set() };
|
|
695
|
+
const module = {
|
|
696
|
+
entryPoint: convertMain(mainNodes[0], context, filename, source),
|
|
697
|
+
functions: members.slice(0, -1).map((member) => convertFunction(member, context, filename, source)),
|
|
698
|
+
kind: /** @type {const} */ ("Module"),
|
|
699
|
+
location
|
|
700
|
+
};
|
|
701
|
+
const unusedMarker = comments.find((comment) => comment.text == immutableMarker && !context.usedImmutableMarkers.has(comment));
|
|
702
|
+
if (unusedMarker)
|
|
703
|
+
return unsupportedSyntax("csharp", "unattached immutable marker", nodeLocation(unusedMarker, filename, source));
|
|
704
|
+
validateParsedModule(module, "csharp");
|
|
705
|
+
validateCheckedArithmetic(module);
|
|
706
|
+
return module;
|
|
707
|
+
}
|
|
708
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3NoYXJwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2Zyb250ZW5kcy9jc2hhcnAuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sTUFBTSxNQUFNLGFBQWEsQ0FBQTtBQUNoQyxPQUFPLGNBQWMsTUFBTSw0Q0FBNEMsQ0FBQTtBQUN2RSxPQUFPLEVBQUMsV0FBVyxFQUFFLFlBQVksRUFBRSxxQkFBcUIsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLGtCQUFrQixDQUFBO0FBQ3BHLE9BQU8sRUFBQyxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsMkJBQTJCLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQTtBQUN4RyxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQTtBQUM3RCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQTtBQUMxRCxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQTtBQUM1RCxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQTtBQUM1RCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFFN0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxNQUFNLEVBQUUsQ0FBQTtBQUUzQixNQUFNLENBQUMsV0FBVyxDQUFDLDZDQUE2QyxDQUFDLEVBQUMsc0JBQXVCLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFBO0FBRTNHLE1BQU0sZUFBZSxHQUFHLDJCQUEyQixDQUFBO0FBQ25ELE1BQU0saUJBQWlCLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQTtBQUN2QyxNQUFNLHlCQUF5QixHQUFHLElBQUksR0FBRyxDQUFDO0lBQ3hDLFVBQVUsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxN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Q0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUM7UUFDeEcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBRXRELEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDeEQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBRTdCLElBQUksU0FBUyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3RCLE9BQU8sSUFBSSxTQUFTLENBQUE7WUFDcEIsU0FBUTtRQUNWLENBQUM7UUFDRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQTtRQUU1QixJQUFJLE1BQU0sS0FBSyxTQUFTO1lBQUUsT0FBTyxpQkFBaUIsQ0FBQyxRQUFRLEVBQUUsdUJBQXVCLEVBQUUsUUFBUSxDQUFDLENBQUE7UUFDL0YsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDdkIsT0FBTyxJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDN0IsU0FBUTtRQUNWLENBQUM7UUFDRCxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxD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QUFJLEdBQUcsRUFBRSxFQUFDLENBQUE7SUFDM0QsTUFBTSxNQUFNLEdBQUc7UUFDYixVQUFVLEVBQUUsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQztRQUNoRSxTQUFTLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNuRyxJQUFJLEVBQUUsb0JBQW9CLENBQUMsQ0FBQyxRQUFRLENBQUM7UUFDckMsUUFBUTtLQUNULENBQUE7SUFDRCxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxJQUFJLGVBQWUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQTtJQUU5SCxJQUFJLFlBQVk7UUFBRSxPQUFPLGlCQUFpQixDQUFDLFFBQVEsRUFBRSw2QkFBNkIsRUFBRSxZQUFZLENBQUMsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFBO0lBQ2pJLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQTtJQUN0Qyx5QkFBeUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUNqQyxPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IFBhcnNlciBmcm9tIFwidHJlZS1zaXR0ZXJcIlxuaW1wb3J0IENTaGFycExhbmd1YWdlIGZyb20gXCJ0cmVlLXNpdHRlci1jLXNoYXJwL2JpbmRpbmdzL25vZGUvaW5kZXguanNcIlxuaW1wb3J0IHttaXNzaW5nVHlwZSwgcGFyc2VGYWlsdXJlLCBTZW1hbnRpZm9sZERpYWdub3N0aWMsIHVuc3VwcG9ydGVkU3ludGF4fSBmcm9tIFwiLi4vZGlhZ25vc3RpYy5qc1wiXG5pbXBvcnQge2xvY2F0aW9uRnJvbU9mZnNldHMsIG1vZHVsZUxvY2F0aW9uLCB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXR9IGZyb20gXCIuLi9zZW1hbnRpYy9sb2NhdGlvbi5qc1wiXG5pbXBvcnQge3dpdGhBZGFwdGVkT3BlcmF0aW9ufSBmcm9tIFwiLi4vc2VtYW50aWMvb3BlcmF0b3JzLmpzXCJcbmltcG9ydCB7d2l0aFBhcnNlclJhbmdlc30gZnJvbSBcIi4uL3NlbWFudGljL3Byb3ZlbmFuY2UuanNcIlxuaW1wb3J0IHtoYXNPbmx5VW5pY29kZVNjYWxhcnN9IGZyb20gXCIuLi9zZW1hbnRpYy9zY2FsYXJzLmpzXCJcbmltcG9ydCB7dmFsaWRhdGVQYXJzZWRNb2R1bGV9IGZyb20gXCIuLi9zZW1hbnRpYy92YWxpZGF0ZS5qc1wiXG5pbXBvcnQge3NvdXJjZVNjYWxhclR5cGV9IGZyb20gXCIuL3NjYWxhcnMuanNcIlxuXG5jb25zdCBwYXJzZXIgPSBuZXcgUGFyc2VyKClcblxucGFyc2VyLnNldExhbmd1YWdlKC8qKiBAdHlwZSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuTGFuZ3VhZ2V9ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChDU2hhcnBMYW5ndWFnZSkpKVxuXG5jb25zdCBpbW11dGFibGVNYXJrZXIgPSBcIi8vIEBzZW1hbnRpZm9sZC1pbW11dGFibGVcIlxuY29uc3QgY2hlY2tlZEFyaXRobWV0aWMgPSBuZXcgV2Vha1NldCgpXG5jb25zdCBjc2hhcnBSZXNlcnZlZElkZW50aWZpZXJzID0gbmV3IFNldChbXG4gIFwiYWJzdHJhY3RcIiwgXCJhZGRcIiwgXCJhbGlhc1wiLCBcImFsbG93c1wiLCBcImFuZFwiLCBcImFzXCIsIFwiYXNjZW5kaW5nXCIsIFwiYXN5bmNcIiwgXCJhd2FpdFwiLCBcImJhc2VcIiwgXCJib29sXCIsIFwiYnJlYWtcIixcbiAgXCJieVwiLCBcImJ5dGVcIiwgXCJjYXNlXCIsIFwiY2F0Y2hcIiwgXCJjaGFyXCIsIFwiY2hlY2tlZFwiLCBcImNsYXNzXCIsIFwiY29uc3RcIiwgXCJjb250aW51ZVwiLCBcImRlY2ltYWxcIiwgXCJkZWZhdWx0XCIsXG4gIFwiZGVsZWdhdGVcIiwgXCJkZXNjZW5kaW5nXCIsIFwiZG9cIiwgXCJkb3VibGVcIiwgXCJkeW5hbWljXCIsIFwiZWxzZVwiLCBcImVudW1cIiwgXCJlcXVhbHNcIiwgXCJldmVudFwiLCBcImV4cGxpY2l0XCIsIFwiZXh0ZW5zaW9uXCIsIFwiZXh0ZXJuXCIsXG4gIFwiZmFsc2VcIiwgXCJmaWVsZFwiLCBcImZpbGVcIiwgXCJmaW5hbGx5XCIsIFwiZml4ZWRcIiwgXCJmbG9hdFwiLCBcImZvclwiLCBcImZvcmVhY2hcIiwgXCJmcm9tXCIsIFwiZ2V0XCIsIFwiZ2xvYmFsXCIsIFwiZ290b1wiLFxuICBcImdyb3VwXCIsIFwiaWZcIiwgXCJpbXBsaWNpdFwiLCBcImluXCIsIFwiaW5pdFwiLCBcImludFwiLCBcImludGVyZmFjZVwiLCBcImludGVybmFsXCIsIFwiaW50b1wiLCBcImlzXCIsIFwiam9pblwiLCBcImxldFwiLCBcImxvY2tcIixcbiAgXCJsb25nXCIsIFwibWFuYWdlZFwiLCBcIm5hbWVvZlwiLCBcIm5hbWVzcGFjZVwiLCBcIm5ld1wiLCBcIm5pbnRcIiwgXCJub3RcIiwgXCJub3RudWxsXCIsIFwibnVsbFwiLCBcIm51aW50XCIsIFwib2JqZWN0XCIsIFwib25cIixcbiAgXCJvcGVyYXRvclwiLCBcIm9yXCIsIFwib3JkZXJieVwiLCBcIm91dFwiLCBcIm92ZXJyaWRlXCIsIFwicGFyYW1zXCIsIFwicGFydGlhbFwiLCBcInByaXZhdGVcIiwgXCJwcm90ZWN0ZWRcIiwgXCJwdWJsaWNcIiwgXCJyZWFkb25seVwiLFxuICBcInJlY29yZFwiLCBcInJlZlwiLCBcInJlbW92ZVwiLCBcInJlcXVpcmVkXCIsIFwicmV0dXJuXCIsIFwic2J5dGVcIiwgXCJzY29wZWRcIiwgXCJzZWFsZWRcIiwgXCJzZWxlY3RcIiwgXCJzZXRcIiwgXCJzaG9ydFwiLCBcInNpemVvZlwiLFxuICBcInN0YWNrYWxsb2NcIiwgXCJzdGF0aWNcIiwgXCJzdHJpbmdcIiwgXCJzdHJ1Y3RcIiwgXCJzd2l0Y2hcIiwgXCJ0aGlzXCIsIFwidGhyb3dcIiwgXCJ0cnVlXCIsIFwidHJ5XCIsIFwidHlwZW9mXCIsIFwidWludFwiLCBcInVsb25nXCIsXG4gIFwidW5jaGVja2VkXCIsIFwidW5tYW5hZ2VkXCIsIFwidW5zYWZlXCIsIFwidXNob3J0XCIsIFwidXNpbmdcIiwgXCJ2YWx1ZVwiLCBcInZhclwiLCBcInZpcnR1YWxcIiwgXCJ2b2lkXCIsIFwidm9sYXRpbGVcIiwgXCJ3aGVuXCIsXG4gIFwid2hlcmVcIiwgXCJ3aGlsZVwiLCBcIndpdGhcIiwgXCJ5aWVsZFwiXG5dKVxuY29uc3QgYmluYXJ5T3BlcmF0aW9ucyA9IG5ldyBNYXAoW1xuICBbXCIrXCIsIFwiQWRkXCJdLCBbXCItXCIsIFwiU3VidHJhY3RcIl0sIFtcIipcIiwgXCJNdWx0aXBseVwiXSwgW1wiPT1cIiwgXCJFcXVhbFwiXSwgW1wiIT1cIiwgXCJOb3RFcXVhbFwiXSxcbiAgW1wiPFwiLCBcIkxlc3NUaGFuXCJdLCBbXCI8PVwiLCBcIkxlc3NUaGFuT3JFcXVhbFwiXSwgW1wiPlwiLCBcIkdyZWF0ZXJUaGFuXCJdLCBbXCI+PVwiLCBcIkdyZWF0ZXJUaGFuT3JFcXVhbFwiXSxcbiAgW1wiJiZcIiwgXCJBbmRcIl0sIFtcInx8XCIsIFwiT3JcIl1cbl0pXG5cbi8qKiBAdHlwZWRlZiB7e2NvbW1lbnRzOiBpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlW10sIHVzZWRJbW11dGFibGVNYXJrZXJzOiBTZXQ8aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZT59fSBDU2hhcnBDb250ZXh0ICovXG5cbi8qKlxuICogVmVyaWZpZXMgb25lIFRyZWUtc2l0dGVyIGJpbmRpbmcgaW5kZXggdGhyb3VnaCB0aGUgc2hhcmVkIGJ5dGUgY29udmVydGVyLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZSB0ZXh0LlxuICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IC0gQmluZGluZy1yZXBvcnRlZCBVVEYtMTYgaW5kZXguXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBWZXJpZmllZCBVVEYtMTYgb2Zmc2V0LlxuICovXG5mdW5jdGlvbiBiaW5kaW5nSW5kZXhUb1V0ZjE2T2Zmc2V0KHNvdXJjZSwgaW5kZXgpIHtcbiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGluZGV4KSB8fCBpbmRleCA8IDAgfHwgaW5kZXggPiBzb3VyY2UubGVuZ3RoIHx8XG4gICAgaW5kZXggPiAwICYmIGluZGV4IDwgc291cmNlLmxlbmd0aCAmJiAvW1xcdUQ4MDAtXFx1REJGRl0vdS50ZXN0KHNvdXJjZVtpbmRleCAtIDFdKSAmJiAvW1xcdURDMDAtXFx1REZGRl0vdS50ZXN0KHNvdXJjZVtpbmRleF0pKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYEludmFsaWQgVHJlZS1zaXR0ZXIgc291cmNlIGluZGV4OiAke2luZGV4fWApXG4gIH1cbiAgcmV0dXJuIHV0ZjhCeXRlT2Zmc2V0VG9VdGYxNk9mZnNldChzb3VyY2UsIG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzb3VyY2Uuc2xpY2UoMCwgaW5kZXgpKS5sZW5ndGgpXG59XG5cbi8qKlxuICogRmluZHMgdGhlIGZpcnN0IHVucGFpcmVkIFVURi0xNiBzdXJyb2dhdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBJbnZhbGlkIG9mZnNldCwgb3IgLTEuXG4gKi9cbmZ1bmN0aW9uIGZpcnN0TG9uZVN1cnJvZ2F0ZU9mZnNldChzb3VyY2UpIHtcbiAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHNvdXJjZS5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICBjb25zdCB1bml0ID0gc291cmNlLmNoYXJDb2RlQXQoaW5kZXgpXG5cbiAgICBpZiAodW5pdCA+PSAweEQ4MDAgJiYgdW5pdCA8PSAweERCRkYpIHtcbiAgICAgIGNvbnN0IG5leHQgPSBzb3VyY2UuY2hhckNvZGVBdChpbmRleCArIDEpXG5cbiAgICAgIGlmIChuZXh0ID49IDB4REMwMCAmJiBuZXh0IDw9IDB4REZGRikgaW5kZXggKz0gMVxuICAgICAgZWxzZSByZXR1cm4gaW5kZXhcbiAgICB9IGVsc2UgaWYgKHVuaXQgPj0gMHhEQzAwICYmIHVuaXQgPD0gMHhERkZGKSByZXR1cm4gaW5kZXhcbiAgfVxuICByZXR1cm4gLTFcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgYmluZGluZyByYW5nZSB0byBhIHNlbWFudGljIHNvdXJjZSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSAtIFBhcnNlciBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZSB0ZXh0LlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBFeGFjdCBsb2NhdGlvbi5cbiAqL1xuZnVuY3Rpb24gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgcmV0dXJuIGxvY2F0aW9uRnJvbU9mZnNldHMoZmlsZW5hbWUsIHNvdXJjZSwgYmluZGluZ0luZGV4VG9VdGYxNk9mZnNldChzb3VyY2UsIG5vZGUuc3RhcnRJbmRleCksXG4gICAgYmluZGluZ0luZGV4VG9VdGYxNk9mZnNldChzb3VyY2UsIG5vZGUuZW5kSW5kZXgpKVxufVxuXG4vKipcbiAqIFJlcXVpcmVzIG9uZSBuYW1lZCBncmFtbWFyIGZpZWxkLlxuICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIC0gRmllbGQgb3duZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmllbGQgLSBHcmFtbWFyIGZpZWxkIG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gUmVxdWlyZWQgY2hpbGQuXG4gKi9cbmZ1bmN0aW9uIHJlcXVpcmVkRmllbGQobm9kZSwgZmllbGQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgY2hpbGQgPSBub2RlLmNoaWxkRm9yRmllbGROYW1lKGZpZWxkKVxuXG4gIGlmICghY2hpbGQpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBgJHtub2RlLnR5cGV9IHdpdGhvdXQgJHtmaWVsZH1gLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIHJldHVybiBjaGlsZFxufVxuXG4vKipcbiAqIFRyYXZlcnNlcyBldmVyeSBwYXJzZXIgY2hpbGQgYW5kIHJlamVjdHMgZXhwbGljaXQgb3IgcHJvcGFnYXRlZCByZWNvdmVyeS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSAtIEN1cnJlbnQgcGFyc2VyIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVQYXJzZXJUcmVlKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgaWYgKG5vZGUuaGFzRXJyb3IgfHwgbm9kZS5pc0Vycm9yIHx8IG5vZGUuaXNNaXNzaW5nKSB7XG4gICAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgICBjb2RlOiBcIlBBUlNFX0VSUk9SXCIsXG4gICAgICBsYW5ndWFnZTogXCJjc2hhcnBcIixcbiAgICAgIGxvY2F0aW9uOiBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBtZXNzYWdlOiBgVHJlZS1zaXR0ZXIgZXhwb3NlZCByZWNvdmVyeSBhdCAnJHtub2RlLnR5cGV9Jy5gXG4gICAgfSlcbiAgfVxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgbm9kZS5jaGlsZENvdW50OyBpbmRleCArPSAxKSB7XG4gICAgY29uc3QgY2hpbGQgPSBub2RlLmNoaWxkKGluZGV4KVxuXG4gICAgaWYgKCFjaGlsZCkgdGhyb3cgbmV3IEVycm9yKGBUcmVlLXNpdHRlciBvbWl0dGVkIGNoaWxkICR7aW5kZXh9IG9mICR7bm9kZS50eXBlfS5gKVxuICAgIHZhbGlkYXRlUGFyc2VyVHJlZShjaGlsZCwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfVxufVxuXG4vKipcbiAqIFNlbGVjdHMgbmFtZWQgc2VtYW50aWMgY2hpbGRyZW4gd2hpbGUgcmV0YWluaW5nIGNvbW1lbnRzIGluIHRoZSBwYXJzZXIgdHJlZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSAtIFBhcmVudCBwYXJzZXIgbm9kZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlW119IE5vbi1jb21tZW50IG5hbWVkIGNoaWxkcmVuLlxuICovXG5mdW5jdGlvbiBzZW1hbnRpY0NoaWxkcmVuKG5vZGUpIHtcbiAgcmV0dXJuIG5vZGUubmFtZWRDaGlsZHJlbi5maWx0ZXIoKGNoaWxkKSA9PiBjaGlsZC50eXBlICE9IFwiY29tbWVudFwiKVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBvbmUgaWRlbnRpZmllciBhZ2FpbnN0IHRoZSBleGFjdCBDIyBzb3VyY2UgcHJvZmlsZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSAtIElkZW50aWZpZXIgbm9kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSByb2xlIC0gRGlhZ25vc3RpYyByb2xlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZSB0ZXh0LlxuICogQHJldHVybnMge3N0cmluZ30gQWNjZXB0ZWQgaWRlbnRpZmllci5cbiAqL1xuZnVuY3Rpb24gaWRlbnRpZmllcihub2RlLCByb2xlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IG5hbWUgPSBub2RlLnRleHRcblxuICBpZiAobm9kZS50eXBlICE9IFwiaWRlbnRpZmllclwiIHx8ICEvXltBLVphLXpfXVtBLVphLXowLTlfXSokL3UudGVzdChuYW1lKSB8fCBjc2hhcnBSZXNlcnZlZElkZW50aWZpZXJzLmhhcyhuYW1lKSkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBgJHtyb2xlfSBpZGVudGlmaWVyICcke25hbWV9J2AsIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICByZXR1cm4gbmFtZVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBleGFjdCBzdXBwb3J0ZWQgc2NhbGFyIHR5cGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGUgfCBudWxsfSBub2RlIC0gVHlwZSBub2RlLCBpZiBwcmVzZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IHN1YmplY3QgLSBUeXBlZCBzdWJqZWN0IGZvciBkaWFnbm9zdGljcy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IG93bmVyTG9jYXRpb24gLSBPd25pbmcgZGVjbGFyYXRpb24gbG9jYXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFthbGxvd1Zhcl0gLSBXaGV0aGVyIGluZmVycmVkIGB2YXJgIHByb2R1Y2VzIE1JU1NJTkdfVFlQRS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UeXBlUmVmZXJlbmNlfSBTZW1hbnRpYyBzY2FsYXIgdHlwZS5cbiAqL1xuZnVuY3Rpb24gY29udmVydFR5cGUobm9kZSwgc3ViamVjdCwgb3duZXJMb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSwgYWxsb3dWYXIgPSBmYWxzZSkge1xuICBpZiAoIW5vZGUpIHJldHVybiBtaXNzaW5nVHlwZShcImNzaGFycFwiLCBzdWJqZWN0LCBvd25lckxvY2F0aW9uKVxuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChhbGxvd1ZhciAmJiBub2RlLnRleHQgPT0gXCJ2YXJcIikgcmV0dXJuIG1pc3NpbmdUeXBlKFwiY3NoYXJwXCIsIHN1YmplY3QsIG93bmVyTG9jYXRpb24pXG4gIGNvbnN0IHR5cGUgPSBzb3VyY2VTY2FsYXJUeXBlKFwiY3NoYXJwXCIsIG5vZGUudGV4dCwgbG9jYXRpb24pXG5cbiAgaWYgKCF0eXBlIHx8ICFbXCJwcmVkZWZpbmVkX3R5cGVcIiwgXCJxdWFsaWZpZWRfbmFtZVwiXS5pbmNsdWRlcyhub2RlLnR5cGUpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIGB1bnN1cHBvcnRlZCBzY2FsYXIgdHlwZSAnJHtub2RlLnRleHR9J2AsIGxvY2F0aW9uKVxuICB9XG4gIHJldHVybiB0eXBlXG59XG5cbi8qKlxuICogRmluZHMgZXhhY3RseSBvbmUgYWNjZXB0ZWQgb3BlcmF0b3IgdG9rZW4gb3duZWQgYnkgYSBwYXJzZXIgbm9kZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSAtIE9wZXJhdGlvbiBub2RlLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gc3BlbGxpbmdzIC0gQWNjZXB0ZWQgb3BlcmF0b3Igc3BlbGxpbmdzLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZSB0ZXh0LlxuICogQHJldHVybnMge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IE9wZXJhdG9yIHRva2VuLlxuICovXG5mdW5jdGlvbiBvcGVyYXRvclRva2VuKG5vZGUsIHNwZWxsaW5ncywgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBmaWVsZCA9IG5vZGUuY2hpbGRGb3JGaWVsZE5hbWUoXCJvcGVyYXRvclwiKVxuICBjb25zdCBjYW5kaWRhdGVzID0gZmllbGQgPyBbZmllbGRdIDogbm9kZS5jaGlsZHJlbi5maWx0ZXIoKGNoaWxkKSA9PiAhY2hpbGQuaXNOYW1lZCAmJiBzcGVsbGluZ3MuaGFzKGNoaWxkLnR5cGUpKVxuXG4gIGlmIChjYW5kaWRhdGVzLmxlbmd0aCAhPSAxIHx8ICFzcGVsbGluZ3MuaGFzKGNhbmRpZGF0ZXNbMF0udHlwZSkpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgYCR7bm9kZS50eXBlfSBvcGVyYXRvcmAsIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICByZXR1cm4gY2FuZGlkYXRlc1swXVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBleHByZXNzaW9uIGFuZCByZWNvcmRzIGV4YWN0IGNoZWNrZWQtd3JhcHBlciBvd25lcnNoaXAuXG4gKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBFeHByZXNzaW9uIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtjaGVja2VkUm9vdF0gLSBXaGV0aGVyIHRoZSBub2RlIGlzIHRoZSBkaXJlY3QgY2hlY2tlZC1leHByZXNzaW9uIG9wZXJhbmQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gU2VtYW50aWMgZXhwcmVzc2lvbi5cbiAqL1xuZnVuY3Rpb24gY29udmVydEV4cHJlc3Npb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSwgY2hlY2tlZFJvb3QgPSBmYWxzZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChub2RlLnR5cGUgPT0gXCJwYXJlbnRoZXNpemVkX2V4cHJlc3Npb25cIikge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gc2VtYW50aWNDaGlsZHJlbihub2RlKVxuXG4gICAgaWYgKGNoaWxkcmVuLmxlbmd0aCAhPSAxKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgbm9kZS50eXBlLCBsb2NhdGlvbilcbiAgICByZXR1cm4gY29udmVydEV4cHJlc3Npb24oY2hpbGRyZW5bMF0sIGZpbGVuYW1lLCBzb3VyY2UpXG4gIH1cbiAgaWYgKG5vZGUudHlwZSA9PSBcImNoZWNrZWRfZXhwcmVzc2lvblwiKSB7XG4gICAgY29uc3QgY2hpbGRyZW4gPSBzZW1hbnRpY0NoaWxkcmVuKG5vZGUpXG4gICAgY29uc3QgY2hlY2tlZFRva2VucyA9IG5vZGUuY2hpbGRyZW4uZmlsdGVyKChjaGlsZCkgPT4gIWNoaWxkLmlzTmFtZWQgJiYgY2hpbGQudHlwZSA9PSBcImNoZWNrZWRcIilcblxuICAgIGlmIChjaGVja2VkVG9rZW5zLmxlbmd0aCAhPSAxIHx8IGNoaWxkcmVuLmxlbmd0aCAhPSAxIHx8XG4gICAgICAhW1wiYmluYXJ5X2V4cHJlc3Npb25cIiwgXCJwcmVmaXhfdW5hcnlfZXhwcmVzc2lvblwiXS5pbmNsdWRlcyhjaGlsZHJlblswXS50eXBlKSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwiY2hlY2tlZCBleHByZXNzaW9uIHNoYXBlXCIsIGxvY2F0aW9uKVxuICAgIH1cbiAgICBjb25zdCBleHByZXNzaW9uID0gY29udmVydEV4cHJlc3Npb24oY2hpbGRyZW5bMF0sIGZpbGVuYW1lLCBzb3VyY2UsIHRydWUpXG5cbiAgICBjaGVja2VkQXJpdGhtZXRpYy5hZGQoZXhwcmVzc2lvbilcbiAgICBleHByZXNzaW9uLmxvY2F0aW9uID0gbG9jYXRpb25cbiAgICByZXR1cm4gZXhwcmVzc2lvblxuICB9XG4gIGlmIChub2RlLnR5cGUgPT0gXCJpZGVudGlmaWVyXCIpIHtcbiAgICBjb25zdCBuYW1lID0gaWRlbnRpZmllcihub2RlLCBcInJlZmVyZW5jZVwiLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklkZW50aWZpZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbiwgbmFtZX0sIHtuYW1lOiBsb2NhdGlvbn0pXG4gIH1cbiAgaWYgKG5vZGUudHlwZSA9PSBcImludGVnZXJfbGl0ZXJhbFwiKSB7XG4gICAgaWYgKCEvXig/OjB8WzEtOV1bMC05XSopTCQvdS50ZXN0KG5vZGUudGV4dCkpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcIm5vbmNhbm9uaWNhbCBsb25nIGxpdGVyYWxcIiwgbG9jYXRpb24pXG4gICAgY29uc3QgdmFsdWUgPSBOdW1iZXIoQmlnSW50KG5vZGUudGV4dC5zbGljZSgwLCAtMSkpKVxuXG4gICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcih2YWx1ZSkpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcIm5vbi1zYWZlIGludGVnZXIgbGl0ZXJhbFwiLCBsb2NhdGlvbilcbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSW50ZWdlckxpdGVyYWxcIiksIGxvY2F0aW9uLCB2YWx1ZX0sIHtsaXRlcmFsOiBsb2NhdGlvbn0pXG4gIH1cbiAgaWYgKG5vZGUudHlwZSA9PSBcImJvb2xlYW5fbGl0ZXJhbFwiKSB7XG4gICAgaWYgKG5vZGUudGV4dCAhPSBcInRydWVcIiAmJiBub2RlLnRleHQgIT0gXCJmYWxzZVwiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgXCJib29sZWFuIGxpdGVyYWxcIiwgbG9jYXRpb24pXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkJvb2xlYW5MaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IG5vZGUudGV4dCA9PSBcInRydWVcIn0sIHtsaXRlcmFsOiBsb2NhdGlvbn0pXG4gIH1cbiAgaWYgKG5vZGUudHlwZSA9PSBcInN0cmluZ19saXRlcmFsXCIpIHtcbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiU3RyaW5nTGl0ZXJhbFwiKSwgbG9jYXRpb24sIHZhbHVlOiBkZWNvZGVTdHJpbmcobm9kZSwgZmlsZW5hbWUsIHNvdXJjZSl9LCB7XG4gICAgICBsaXRlcmFsOiBsb2NhdGlvblxuICAgIH0pXG4gIH1cbiAgaWYgKG5vZGUudHlwZSA9PSBcInByZWZpeF91bmFyeV9leHByZXNzaW9uXCIpIHtcbiAgICBjb25zdCBjaGlsZHJlbiA9IHNlbWFudGljQ2hpbGRyZW4obm9kZSlcbiAgICBjb25zdCBvcGVyYXRvciA9IG9wZXJhdG9yVG9rZW4obm9kZSwgbmV3IFNldChbXCIhXCIsIFwiLVwiXSksIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoICE9IDEgfHwgb3BlcmF0b3IudHlwZSA9PSBcIi1cIiAmJiAhY2hlY2tlZFJvb3QpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcInVud3JhcHBlZCBvciBtYWxmb3JtZWQgdW5hcnkgZXhwcmVzc2lvblwiLCBsb2NhdGlvbilcbiAgICB9XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gKi8gKC8qKiBAdHlwZSB7dW5rbm93bn0gKi8gKHdpdGhBZGFwdGVkT3BlcmF0aW9uKHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogXCJVbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgb3BlcmFuZDogY29udmVydEV4cHJlc3Npb24oY2hpbGRyZW5bMF0sIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSwge29wZXJhdG9yOiBub2RlTG9jYXRpb24ob3BlcmF0b3IsIGZpbGVuYW1lLCBzb3VyY2UpfSksIG9wZXJhdG9yLnR5cGUgPT0gXCIhXCIgPyBcIk5vdFwiIDogXCJOZWdhdGVcIikpKVxuXG4gICAgaWYgKGNoZWNrZWRSb290KSBjaGVja2VkQXJpdGhtZXRpYy5hZGQoZXhwcmVzc2lvbilcbiAgICByZXR1cm4gZXhwcmVzc2lvblxuICB9XG4gIGlmIChub2RlLnR5cGUgPT0gXCJiaW5hcnlfZXhwcmVzc2lvblwiKSB7XG4gICAgY29uc3QgbGVmdE5vZGUgPSByZXF1aXJlZEZpZWxkKG5vZGUsIFwibGVmdFwiLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGNvbnN0IHJpZ2h0Tm9kZSA9IHJlcXVpcmVkRmllbGQobm9kZSwgXCJyaWdodFwiLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGNvbnN0IG9wZXJhdG9yID0gb3BlcmF0b3JUb2tlbihub2RlLCBuZXcgU2V0KGJpbmFyeU9wZXJhdGlvbnMua2V5cygpKSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBjb25zdCBhZGFwdGVkID0gYmluYXJ5T3BlcmF0aW9ucy5nZXQob3BlcmF0b3IudHlwZSlcblxuICAgIGlmICghYWRhcHRlZCB8fCBzZW1hbnRpY0NoaWxkcmVuKG5vZGUpLmxlbmd0aCAhPSAyIHx8IFtcIi1cIiwgXCIqXCJdLmluY2x1ZGVzKG9wZXJhdG9yLnR5cGUpICYmICFjaGVja2VkUm9vdCkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwidW53cmFwcGVkIG9yIHVuc3VwcG9ydGVkIGJpbmFyeSBleHByZXNzaW9uXCIsIGxvY2F0aW9uKVxuICAgIH1cbiAgICBjb25zdCBleHByZXNzaW9uID0gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAod2l0aEFkYXB0ZWRPcGVyYXRpb24od2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBraW5kOiBcIkJpbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxlZnQ6IGNvbnZlcnRFeHByZXNzaW9uKGxlZnROb2RlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgcmlnaHQ6IGNvbnZlcnRFeHByZXNzaW9uKHJpZ2h0Tm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9LCB7b3BlcmF0b3I6IG5vZGVMb2NhdGlvbihvcGVyYXRvciwgZmlsZW5hbWUsIHNvdXJjZSl9KSwgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy9vcGVyYXRvcnMuanNcIikuQWRhcHRlZE9wZXJhdGlvbn0gKi8gKGFkYXB0ZWQpKSkpXG5cbiAgICBpZiAoY2hlY2tlZFJvb3QpIGNoZWNrZWRBcml0aG1ldGljLmFkZChleHByZXNzaW9uKVxuICAgIHJldHVybiBleHByZXNzaW9uXG4gIH1cbiAgaWYgKG5vZGUudHlwZSA9PSBcImludm9jYXRpb25fZXhwcmVzc2lvblwiKSB7XG4gICAgY29uc3QgY2FsbGVlTm9kZSA9IHJlcXVpcmVkRmllbGQobm9kZSwgXCJmdW5jdGlvblwiLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGNvbnN0IGFyZ3VtZW50c05vZGUgPSByZXF1aXJlZEZpZWxkKG5vZGUsIFwiYXJndW1lbnRzXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICBpZiAoY2FsbGVlTm9kZS50eXBlICE9IFwiaWRlbnRpZmllclwiIHx8IGFyZ3VtZW50c05vZGUudHlwZSAhPSBcImFyZ3VtZW50X2xpc3RcIikge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwicXVhbGlmaWVkIG9yIGR5bmFtaWMgY2FsbFwiLCBsb2NhdGlvbilcbiAgICB9XG4gICAgY29uc3QgYXJndW1lbnRzXyA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbltdfSAqLyAoXG4gICAgICBzZW1hbnRpY0NoaWxkcmVuKGFyZ3VtZW50c05vZGUpLm1hcCgoYXJndW1lbnQpID0+IGNvbnZlcnRBcmd1bWVudChhcmd1bWVudCwgZmlsZW5hbWUsIHNvdXJjZSkpKVxuICAgIGNvbnN0IGNhbGxlZSA9IGlkZW50aWZpZXIoY2FsbGVlTm9kZSwgXCJjYWxsZWVcIiwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHthcmd1bWVudHM6IGFyZ3VtZW50c18sIGNhbGxlZSwga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQ2FsbEV4cHJlc3Npb25cIiksIGxvY2F0aW9ufSwge1xuICAgICAgY2FsbGVlOiBub2RlTG9jYXRpb24oY2FsbGVlTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9KVxuICB9XG4gIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBub2RlLnR5cGUsIGxvY2F0aW9uKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBwb3NpdGlvbmFsIGFyZ3VtZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIC0gQXJndW1lbnQgbm9kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UgdGV4dC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSBTZW1hbnRpYyBhcmd1bWVudCBleHByZXNzaW9uLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0QXJndW1lbnQobm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBjaGlsZHJlbiA9IHNlbWFudGljQ2hpbGRyZW4obm9kZSlcblxuICBpZiAobm9kZS50eXBlICE9IFwiYXJndW1lbnRcIiB8fCBjaGlsZHJlbi5sZW5ndGggIT0gMSB8fCBub2RlLmNoaWxkcmVuLnNvbWUoKGNoaWxkKSA9PiAhY2hpbGQuaXNOYW1lZCAmJiBjaGlsZC50eXBlID09IFwiOlwiKSkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcIm5vbi1wb3NpdGlvbmFsIGFyZ3VtZW50XCIsIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICByZXR1cm4gY29udmVydEV4cHJlc3Npb24oY2hpbGRyZW5bMF0sIGZpbGVuYW1lLCBzb3VyY2UpXG59XG5cbi8qKlxuICogRGVjb2RlcyBvbmUgb3JkaW5hcnkgQyMgc3RyaW5nIGxpdGVyYWwgd2l0aG91dCBpbnRlcnBvbGF0aW9uIG9yIHJhdyBmb3Jtcy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSAtIFN0cmluZyBsaXRlcmFsIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBEZWNvZGVkIFVuaWNvZGUgc2NhbGFyIHN0cmluZy5cbiAqL1xuZnVuY3Rpb24gZGVjb2RlU3RyaW5nKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgdGV4dCA9IG5vZGUudGV4dFxuXG4gIGlmICghdGV4dC5zdGFydHNXaXRoKFwiXFxcIlwiKSB8fCAhdGV4dC5lbmRzV2l0aChcIlxcXCJcIikgfHwgdGV4dC5zdGFydHNXaXRoKFwiXFxcIlxcXCJcXFwiXCIpIHx8IC9bXFxyXFxuXS91LnRlc3QodGV4dCkpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgXCJub25jYW5vbmljYWwgc3RyaW5nIGxpdGVyYWxcIiwgbG9jYXRpb24pXG4gIH1cbiAgbGV0IGRlY29kZWQgPSBcIlwiXG4gIGNvbnN0IHNpbXBsZSA9IG5ldyBNYXAoW1tcIlxcXCJcIiwgXCJcXFwiXCJdLCBbXCJcXFxcXCIsIFwiXFxcXFwiXSwgW1wiMFwiLCBcIlxcMFwiXSwgW1wiYVwiLCBcIlxcdTAwMDdcIl0sIFtcImJcIiwgXCJcXGJcIl0sIFtcImZcIiwgXCJcXGZcIl0sXG4gICAgW1wiblwiLCBcIlxcblwiXSwgW1wiclwiLCBcIlxcclwiXSwgW1widFwiLCBcIlxcdFwiXSwgW1widlwiLCBcIlxcdlwiXV0pXG5cbiAgZm9yIChsZXQgaW5kZXggPSAxOyBpbmRleCA8IHRleHQubGVuZ3RoIC0gMTsgaW5kZXggKz0gMSkge1xuICAgIGNvbnN0IGNoYXJhY3RlciA9IHRleHRbaW5kZXhdXG5cbiAgICBpZiAoY2hhcmFjdGVyICE9IFwiXFxcXFwiKSB7XG4gICAgICBkZWNvZGVkICs9IGNoYXJhY3RlclxuICAgICAgY29udGludWVcbiAgICB9XG4gICAgY29uc3QgZXNjYXBlID0gdGV4dFsrK2luZGV4XVxuXG4gICAgaWYgKGVzY2FwZSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgXCJpbnZhbGlkIHN0cmluZyBlc2NhcGVcIiwgbG9jYXRpb24pXG4gICAgaWYgKHNpbXBsZS5oYXMoZXNjYXBlKSkge1xuICAgICAgZGVjb2RlZCArPSBzaW1wbGUuZ2V0KGVzY2FwZSlcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGNvbnN0IHdpZHRoID0gZXNjYXBlID09IFwidVwiID8gNCA6IGVzY2FwZSA9PSBcIlVcIiA/IDggOiAwXG4gICAgY29uc3QgZGlnaXRzID0gdGV4dC5zbGljZShpbmRleCArIDEsIGluZGV4ICsgMSArIHdpZHRoKVxuXG4gICAgaWYgKCF3aWR0aCB8fCBkaWdpdHMubGVuZ3RoICE9IHdpZHRoIHx8ICEvXlswLTlBLUZhLWZdKyQvdS50ZXN0KGRpZ2l0cykpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcInVuc3VwcG9ydGVkIHN0cmluZyBlc2NhcGVcIiwgbG9jYXRpb24pXG4gICAgfVxuICAgIGluZGV4ICs9IHdpZHRoXG4gICAgY29uc3QgdmFsdWUgPSBOdW1iZXIucGFyc2VJbnQoZGlnaXRzLCAxNilcblxuICAgIGlmIChlc2NhcGUgPT0gXCJVXCIgJiYgKHZhbHVlID4gMHgxMEZGRkYgfHwgdmFsdWUgPj0gMHhEODAwICYmIHZhbHVlIDw9IDB4REZGRikpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcImludmFsaWQgVW5pY29kZSBzdHJpbmcgZXNjYXBlXCIsIGxvY2F0aW9uKVxuICAgIH1cbiAgICBkZWNvZGVkICs9IGVzY2FwZSA9PSBcIlVcIiA/IFN0cmluZy5mcm9tQ29kZVBvaW50KHZhbHVlKSA6IFN0cmluZy5mcm9tQ2hhckNvZGUodmFsdWUpXG4gIH1cbiAgaWYgKCFoYXNPbmx5VW5pY29kZVNjYWxhcnMoZGVjb2RlZCkpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcImludmFsaWQgVW5pY29kZSBzdHJpbmcgbGl0ZXJhbFwiLCBsb2NhdGlvbilcbiAgcmV0dXJuIGRlY29kZWRcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgZXhhY3QgaW5pdGlhbGl6ZWQgbG9jYWwgZGVjbGFyYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBMb2NhbCBzdGF0ZW1lbnQgbm9kZS5cbiAqIEBwYXJhbSB7Q1NoYXJwQ29udGV4dH0gY29udGV4dCAtIENvbW1lbnQtY2FycmllciBzdGF0ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UgdGV4dC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Mb2NhbERlY2xhcmF0aW9ufSBTZW1hbnRpYyBkZWNsYXJhdGlvbi5cbiAqL1xuZnVuY3Rpb24gY29udmVydExvY2FsKG5vZGUsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgZGVjbGFyYXRpb24gPSBzZW1hbnRpY0NoaWxkcmVuKG5vZGUpWzBdXG5cbiAgaWYgKHNlbWFudGljQ2hpbGRyZW4obm9kZSkubGVuZ3RoICE9IDEgfHwgZGVjbGFyYXRpb24/LnR5cGUgIT0gXCJ2YXJpYWJsZV9kZWNsYXJhdGlvblwiKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIG5vZGUudHlwZSwgbG9jYXRpb24pXG4gIH1cbiAgY29uc3QgdHlwZU5vZGUgPSBkZWNsYXJhdGlvbi5jaGlsZEZvckZpZWxkTmFtZShcInR5cGVcIilcbiAgY29uc3QgZGVjbGFyYXRvcnMgPSBzZW1hbnRpY0NoaWxkcmVuKGRlY2xhcmF0aW9uKS5maWx0ZXIoKGNoaWxkKSA9PiBjaGlsZC50eXBlID09IFwidmFyaWFibGVfZGVjbGFyYXRvclwiKVxuXG4gIGlmIChkZWNsYXJhdG9ycy5sZW5ndGggIT0gMSB8fCBzZW1hbnRpY0NoaWxkcmVuKGRlY2xhcmF0aW9uKS5sZW5ndGggIT0gMikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcImxvY2FsIGRlY2xhcmF0aW9uIHNoYXBlXCIsIGxvY2F0aW9uKVxuICB9XG4gIGNvbnN0IGRlY2xhcmF0b3IgPSBkZWNsYXJhdG9yc1swXVxuICBjb25zdCBuYW1lTm9kZSA9IHJlcXVpcmVkRmllbGQoZGVjbGFyYXRvciwgXCJuYW1lXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IHZhbHVlcyA9IHNlbWFudGljQ2hpbGRyZW4oZGVjbGFyYXRvcikuZmlsdGVyKChjaGlsZCkgPT4gY2hpbGQuaWQgIT0gbmFtZU5vZGUuaWQpXG5cbiAgaWYgKHZhbHVlcy5sZW5ndGggIT0gMSkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwibG9jYWwgd2l0aG91dCBvbmUgaW5pdGlhbGl6ZXJcIiwgbG9jYXRpb24pXG4gIGNvbnN0IG5hbWUgPSBpZGVudGlmaWVyKG5hbWVOb2RlLCBcImxvY2FsXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKG5hbWUgPT0gXCJTeXN0ZW1cIikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwibG9jYWwgY2FwdHVyZXMgU3lzdGVtXCIsIG5vZGVMb2NhdGlvbihuYW1lTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIGNvbnN0IG9wZXJhdG9yID0gb3BlcmF0b3JUb2tlbihkZWNsYXJhdG9yLCBuZXcgU2V0KFtcIj1cIl0pLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBtdXRhYmxlID0gIXRha2VJbW11dGFibGVNYXJrZXIobm9kZSwgY29udGV4dClcblxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgaW5pdGlhbGl6ZXI6IGNvbnZlcnRFeHByZXNzaW9uKHZhbHVlc1swXSwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiTG9jYWxEZWNsYXJhdGlvblwiKSxcbiAgICBsb2NhdGlvbixcbiAgICBtdXRhYmxlLFxuICAgIG5hbWUsXG4gICAgdHlwZTogY29udmVydFR5cGUodHlwZU5vZGUsIGBMb2NhbCAnJHtuYW1lfSdgLCBsb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSwgdHJ1ZSlcbiAgfSwge25hbWU6IG5vZGVMb2NhdGlvbihuYW1lTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSksIG9wZXJhdG9yOiBub2RlTG9jYXRpb24ob3BlcmF0b3IsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbn1cblxuLyoqXG4gKiBDbGFpbXMgYW4gZXhhY3RseSBhZGphY2VudCBpbW11dGFibGUtbG9jYWwgY2FycmllciBpZiBwcmVzZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIC0gTG9jYWwgZGVjbGFyYXRpb24gbm9kZS5cbiAqIEBwYXJhbSB7Q1NoYXJwQ29udGV4dH0gY29udGV4dCAtIENvbW1lbnQtY2FycmllciBzdGF0ZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBsb2NhbCBpcyBpbW11dGFibGUuXG4gKi9cbmZ1bmN0aW9uIHRha2VJbW11dGFibGVNYXJrZXIobm9kZSwgY29udGV4dCkge1xuICBjb25zdCBtYXJrZXIgPSBjb250ZXh0LmNvbW1lbnRzLmZpbmQoKGNvbW1lbnQpID0+IGNvbW1lbnQudGV4dCA9PSBpbW11dGFibGVNYXJrZXIgJiZcbiAgICBjb21tZW50LmVuZFBvc2l0aW9uLnJvdyArIDEgPT0gbm9kZS5zdGFydFBvc2l0aW9uLnJvdyAmJiBjb21tZW50LnN0YXJ0UG9zaXRpb24uY29sdW1uID09IG5vZGUuc3RhcnRQb3NpdGlvbi5jb2x1bW4pXG5cbiAgaWYgKCFtYXJrZXIpIHJldHVybiBmYWxzZVxuICBjb250ZXh0LnVzZWRJbW11dGFibGVNYXJrZXJzLmFkZChtYXJrZXIpXG4gIHJldHVybiB0cnVlXG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIHN1cHBvcnRlZCBDIyBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcInRyZWUtc2l0dGVyXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBTdGF0ZW1lbnQgbm9kZS5cbiAqIEBwYXJhbSB7Q1NoYXJwQ29udGV4dH0gY29udGV4dCAtIENvbW1lbnQtY2FycmllciBzdGF0ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UgdGV4dC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TdGF0ZW1lbnR9IFNlbWFudGljIHN0YXRlbWVudC5cbiAqL1xuZnVuY3Rpb24gY29udmVydFN0YXRlbWVudChub2RlLCBjb250ZXh0LCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKG5vZGUudHlwZSA9PSBcImxvY2FsX2RlY2xhcmF0aW9uX3N0YXRlbWVudFwiKSByZXR1cm4gY29udmVydExvY2FsKG5vZGUsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGlmIChub2RlLnR5cGUgPT0gXCJyZXR1cm5fc3RhdGVtZW50XCIpIHtcbiAgICBjb25zdCBjaGlsZHJlbiA9IHNlbWFudGljQ2hpbGRyZW4obm9kZSlcblxuICAgIGlmIChjaGlsZHJlbi5sZW5ndGggIT0gMSkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwicmV0dXJuIHdpdGhvdXQgb25lIGV4cHJlc3Npb25cIiwgbG9jYXRpb24pXG4gICAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihjaGlsZHJlblswXSwgZmlsZW5hbWUsIHNvdXJjZSksIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlJldHVyblN0YXRlbWVudFwiKSwgbG9jYXRpb259XG4gIH1cbiAgaWYgKG5vZGUudHlwZSA9PSBcImlmX3N0YXRlbWVudFwiKSByZXR1cm4gY29udmVydElmKG5vZGUsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGlmIChub2RlLnR5cGUgPT0gXCJleHByZXNzaW9uX3N0YXRlbWVudFwiKSB7XG4gICAgY29uc3QgY2hpbGRyZW4gPSBzZW1hbnRpY0NoaWxkcmVuKG5vZGUpXG5cbiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoICE9IDEpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBub2RlLnR5cGUsIGxvY2F0aW9uKVxuICAgIGlmIChjaGlsZHJlblswXS50eXBlID09IFwiYXNzaWdubWVudF9leHByZXNzaW9uXCIpIHJldHVybiBjb252ZXJ0QXNzaWdubWVudChjaGlsZHJlblswXSwgZmlsZW5hbWUsIHNvdXJjZSwgbG9jYXRpb24pXG4gICAgcmV0dXJuIGNvbnZlcnRQcmludChjaGlsZHJlblswXSwgZmlsZW5hbWUsIHNvdXJjZSwgbG9jYXRpb24pXG4gIH1cbiAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIG5vZGUudHlwZSwgbG9jYXRpb24pXG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIHBsYWluIGlkZW50aWZpZXIgYXNzaWdubWVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSAtIEFzc2lnbm1lbnQgZXhwcmVzc2lvbiBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZSB0ZXh0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbG9jYXRpb24gLSBPd25pbmcgc3RhdGVtZW50IGxvY2F0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkFzc2lnbm1lbnRTdGF0ZW1lbnR9IFNlbWFudGljIGFzc2lnbm1lbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRBc3NpZ25tZW50KG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UsIGxvY2F0aW9uKSB7XG4gIGNvbnN0IGxlZnQgPSByZXF1aXJlZEZpZWxkKG5vZGUsIFwibGVmdFwiLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCByaWdodCA9IHJlcXVpcmVkRmllbGQobm9kZSwgXCJyaWdodFwiLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBvcGVyYXRvciA9IG9wZXJhdG9yVG9rZW4obm9kZSwgbmV3IFNldChbXCI9XCJdKSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobGVmdC50eXBlICE9IFwiaWRlbnRpZmllclwiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgXCJhc3NpZ25tZW50IHRhcmdldFwiLCBub2RlTG9jYXRpb24obGVmdCwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIGNvbnN0IG5hbWUgPSBpZGVudGlmaWVyKGxlZnQsIFwiYXNzaWdubWVudCB0YXJnZXRcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgbmFtZUxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKGxlZnQsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgIGV4cHJlc3Npb246IGNvbnZlcnRFeHByZXNzaW9uKHJpZ2h0LCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJBc3NpZ25tZW50U3RhdGVtZW50XCIpLFxuICAgIGxvY2F0aW9uLFxuICAgIHRhcmdldDogd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSWRlbnRpZmllckV4cHJlc3Npb25cIiksIGxvY2F0aW9uOiBuYW1lTG9jYXRpb24sIG5hbWV9LCB7bmFtZTogbmFtZUxvY2F0aW9ufSlcbiAgfSwge29wZXJhdG9yOiBub2RlTG9jYXRpb24ob3BlcmF0b3IsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZXhhY3QgU3lzdGVtLkNvbnNvbGUuV3JpdGVMaW5lIHByaW50IHNjYWZmb2xkLlxuICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIC0gSW52b2NhdGlvbiBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZSB0ZXh0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbG9jYXRpb24gLSBPd25pbmcgc3RhdGVtZW50IGxvY2F0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlByaW50U3RhdGVtZW50fSBTZW1hbnRpYyBwcmludCBzdGF0ZW1lbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRQcmludChub2RlLCBmaWxlbmFtZSwgc291cmNlLCBsb2NhdGlvbikge1xuICBpZiAobm9kZS50eXBlICE9IFwiaW52b2NhdGlvbl9leHByZXNzaW9uXCIpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcImV4cHJlc3Npb24gc3RhdGVtZW50IG90aGVyIHRoYW4gcHJpbnRcIiwgbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICBjb25zdCBjYWxsZWUgPSByZXF1aXJlZEZpZWxkKG5vZGUsIFwiZnVuY3Rpb25cIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYXJndW1lbnRzTm9kZSA9IHJlcXVpcmVkRmllbGQobm9kZSwgXCJhcmd1bWVudHNcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYXJndW1lbnRzXyA9IHNlbWFudGljQ2hpbGRyZW4oYXJndW1lbnRzTm9kZSlcblxuICBpZiAoIWlzUHJpbnRSZWNlaXZlcihjYWxsZWUpIHx8IGFyZ3VtZW50c05vZGUudHlwZSAhPSBcImFyZ3VtZW50X2xpc3RcIiB8fCBhcmd1bWVudHNfLmxlbmd0aCAhPSAxKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwicHJpbnQgY2FsbCBzaGFwZVwiLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cbiAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0QXJndW1lbnQoYXJndW1lbnRzX1swXSwgZmlsZW5hbWUsIHNvdXJjZSksIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlByaW50U3RhdGVtZW50XCIpLCBsb2NhdGlvbn1cbn1cblxuLyoqXG4gKiBSZWNvZ25pemVzIG9ubHkgdGhlIGZ1bGx5IHF1YWxpZmllZCBwcmludCByZWNlaXZlci5cbiAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSAtIENhbmRpZGF0ZSBjYWxsZWUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgY2FsbGVlIGlzIHRoZSBleGFjdCBwcmludCByZWNlaXZlci5cbiAqL1xuZnVuY3Rpb24gaXNQcmludFJlY2VpdmVyKG5vZGUpIHtcbiAgaWYgKG5vZGUudHlwZSAhPSBcIm1lbWJlcl9hY2Nlc3NfZXhwcmVzc2lvblwiKSByZXR1cm4gZmFsc2VcbiAgY29uc3Qgb3V0ZXJFeHByZXNzaW9uID0gbm9kZS5jaGlsZEZvckZpZWxkTmFtZShcImV4cHJlc3Npb25cIilcbiAgY29uc3Qgb3V0ZXJOYW1lID0gbm9kZS5jaGlsZEZvckZpZWxkTmFtZShcIm5hbWVcIilcblxuICBpZiAob3V0ZXJOYW1lPy50ZXh0ICE9IFwiV3JpdGVMaW5lXCIgfHwgb3V0ZXJFeHByZXNzaW9uPy50eXBlICE9IFwibWVtYmVyX2FjY2Vzc19leHByZXNzaW9uXCIpIHJldHVybiBmYWxzZVxuICByZXR1cm4gb3V0ZXJFeHByZXNzaW9uLmNoaWxkRm9yRmllbGROYW1lKFwiZXhwcmVzc2lvblwiKT8udHlwZSA9PSBcImlkZW50aWZpZXJcIiAmJlxuICAgIG91dGVyRXhwcmVzc2lvbi5jaGlsZEZvckZpZWxkTmFtZShcImV4cHJlc3Npb25cIik/LnRleHQgPT0gXCJTeXN0ZW1cIiAmJiBvdXRlckV4cHJlc3Npb24uY2hpbGRGb3JGaWVsZE5hbWUoXCJuYW1lXCIpPy50ZXh0ID09IFwiQ29uc29sZVwiXG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIGJyYWNlZCBjb25kaXRpb25hbCBhbmQgb3B0aW9uYWwgYWx0ZXJuYXRlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIC0gSWYtc3RhdGVtZW50IG5vZGUuXG4gKiBAcGFyYW0ge0NTaGFycENvbnRleHR9IGNvbnRleHQgLSBDb21tZW50LWNhcnJpZXIgc3RhdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuSWZTdGF0ZW1lbnR9IFNlbWFudGljIGNvbmRpdGlvbmFsLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0SWYobm9kZSwgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBjb25kaXRpb24gPSByZXF1aXJlZEZpZWxkKG5vZGUsIFwiY29uZGl0aW9uXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGNvbnNlcXVlbmNlID0gcmVxdWlyZWRGaWVsZChub2RlLCBcImNvbnNlcXVlbmNlXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGFsdGVybmF0aXZlID0gbm9kZS5jaGlsZEZvckZpZWxkTmFtZShcImFsdGVybmF0aXZlXCIpXG5cbiAgcmV0dXJuIHtcbiAgICAuLi4oYWx0ZXJuYXRpdmUgPyB7YWx0ZXJuYXRlOiBhbHRlcm5hdGl2ZS50eXBlID09IFwiaWZfc3RhdGVtZW50XCJcbiAgICAgID8ge2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkJsb2NrXCIpLCBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKGFsdGVybmF0aXZlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgICAgICBzdGF0ZW1lbnRzOiBbY29udmVydElmKGFsdGVybmF0aXZlLCBjb250ZXh0LCBmaWxlbmFtZSwgc291cmNlKV19XG4gICAgICA6IGNvbnZlcnRCbG9jayhhbHRlcm5hdGl2ZSwgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSl9IDoge30pLFxuICAgIGNvbmRpdGlvbjogY29udmVydEV4cHJlc3Npb24oY29uZGl0aW9uLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBjb25zZXF1ZW50OiBjb252ZXJ0QmxvY2soY29uc2VxdWVuY2UsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklmU3RhdGVtZW50XCIpLFxuICAgIGxvY2F0aW9uXG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgbGV4aWNhbCBDIyBibG9jay5cbiAqIEBwYXJhbSB7aW1wb3J0KFwidHJlZS1zaXR0ZXJcIikuU3ludGF4Tm9kZX0gbm9kZSAtIEJsb2NrIG5vZGUuXG4gKiBAcGFyYW0ge0NTaGFycENvbnRleHR9IGNvbnRleHQgLSBDb21tZW50LWNhcnJpZXIgc3RhdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQmxvY2t9IFNlbWFudGljIGJsb2NrLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0QmxvY2sobm9kZSwgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChub2RlLnR5cGUgIT0gXCJibG9ja1wiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgbm9kZS50eXBlLCBsb2NhdGlvbilcbiAgcmV0dXJuIHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJCbG9ja1wiKSwgbG9jYXRpb24sXG4gICAgc3RhdGVtZW50czogc2VtYW50aWNDaGlsZHJlbihub2RlKS5tYXAoKHN0YXRlbWVudCkgPT4gY29udmVydFN0YXRlbWVudChzdGF0ZW1lbnQsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpKX1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgZXhhY3QgcHJpdmF0ZSBzdGF0aWMgc2VtYW50aWMgbWV0aG9kLlxuICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIC0gTWV0aG9kIG5vZGUuXG4gKiBAcGFyYW0ge0NTaGFycENvbnRleHR9IGNvbnRleHQgLSBDb21tZW50LWNhcnJpZXIgc3RhdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRnVuY3Rpb25EZWNsYXJhdGlvbn0gU2VtYW50aWMgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRGdW5jdGlvbihub2RlLCBjb250ZXh0LCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGNoaWxkcmVuID0gc2VtYW50aWNDaGlsZHJlbihub2RlKVxuICBjb25zdCBtb2RpZmllcnMgPSBjaGlsZHJlbi5maWx0ZXIoKGNoaWxkKSA9PiBjaGlsZC50eXBlID09IFwibW9kaWZpZXJcIilcblxuICBpZiAobm9kZS50eXBlICE9IFwibWV0aG9kX2RlY2xhcmF0aW9uXCIgfHwgbW9kaWZpZXJzLm1hcCgoe3RleHR9KSA9PiB0ZXh0KS5qb2luKFwiIFwiKSAhPSBcInByaXZhdGUgc3RhdGljXCIgfHxcbiAgICBjaGlsZHJlbi5sZW5ndGggIT0gNiB8fCBub2RlLmNoaWxkRm9yRmllbGROYW1lKFwidHlwZV9wYXJhbWV0ZXJzXCIpIHx8IG5vZGUuY2hpbGRGb3JGaWVsZE5hbWUoXCJjb25zdHJhaW50c1wiKSB8fFxuICAgICFub2RlLmNoaWxkRm9yRmllbGROYW1lKFwiYm9keVwiKSkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcIm1ldGhvZCBzY2FmZm9sZGluZ1wiLCBsb2NhdGlvbilcbiAgfVxuICBjb25zdCBuYW1lTm9kZSA9IHJlcXVpcmVkRmllbGQobm9kZSwgXCJuYW1lXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IHBhcmFtZXRlcnNOb2RlID0gcmVxdWlyZWRGaWVsZChub2RlLCBcInBhcmFtZXRlcnNcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgcmV0dXJuTm9kZSA9IHJlcXVpcmVkRmllbGQobm9kZSwgXCJyZXR1cm5zXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGJvZHlOb2RlID0gcmVxdWlyZWRGaWVsZChub2RlLCBcImJvZHlcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgbmFtZSA9IGlkZW50aWZpZXIobmFtZU5vZGUsIFwiZnVuY3Rpb25cIiwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoW1wiTWFpblwiLCBcIlByb2dyYW1cIiwgXCJTeXN0ZW1cIl0uaW5jbHVkZXMobmFtZSkpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgYHJlc2VydmVkIHNlbWFudGljIG1ldGhvZCAnJHtuYW1lfSdgLCBub2RlTG9jYXRpb24obmFtZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG4gIGNvbnN0IHBhcmFtZXRlck5vZGVzID0gc2VtYW50aWNDaGlsZHJlbihwYXJhbWV0ZXJzTm9kZSlcblxuICBpZiAocGFyYW1ldGVyTm9kZXMubGVuZ3RoICE9IDIgfHwgcGFyYW1ldGVyTm9kZXMuc29tZSgocGFyYW1ldGVyKSA9PiBwYXJhbWV0ZXIudHlwZSAhPSBcInBhcmFtZXRlclwiKSkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcImZ1bmN0aW9uIHBhcmFtZXRlciBjb3VudCBvciBzaGFwZVwiLCBub2RlTG9jYXRpb24ocGFyYW1ldGVyc05vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG4gIGNvbnN0IHBhcmFtZXRlcnMgPSBwYXJhbWV0ZXJOb2Rlcy5tYXAoKHBhcmFtZXRlck5vZGUpID0+IGNvbnZlcnRQYXJhbWV0ZXIocGFyYW1ldGVyTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgIGJvZHk6IGNvbnZlcnRCbG9jayhib2R5Tm9kZSwgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiRnVuY3Rpb25EZWNsYXJhdGlvblwiKSxcbiAgICBsb2NhdGlvbixcbiAgICBuYW1lLFxuICAgIHBhcmFtZXRlcnMsXG4gICAgcmV0dXJuVHlwZTogY29udmVydFR5cGUocmV0dXJuTm9kZSwgYEZ1bmN0aW9uICcke25hbWV9JyByZXR1cm5gLCBsb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfSwge25hbWU6IG5vZGVMb2NhdGlvbihuYW1lTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSl9KVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBleHBsaWNpdGx5IHR5cGVkIHVubW9kaWZpZWQgcGFyYW1ldGVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIC0gUGFyYW1ldGVyIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlIHRleHQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuUGFyYW1ldGVyfSBTZW1hbnRpYyBwYXJhbWV0ZXIuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRQYXJhbWV0ZXIobm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBuYW1lTm9kZSA9IHJlcXVpcmVkRmllbGQobm9kZSwgXCJuYW1lXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IHR5cGVOb2RlID0gbm9kZS5jaGlsZEZvckZpZWxkTmFtZShcInR5cGVcIilcblxuICBpZiAoc2VtYW50aWNDaGlsZHJlbihub2RlKS5sZW5ndGggIT0gMikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwicGFyYW1ldGVyIG1vZGlmaWVycyBvciBkZWZhdWx0c1wiLCBsb2NhdGlvbilcbiAgY29uc3QgbmFtZSA9IGlkZW50aWZpZXIobmFtZU5vZGUsIFwicGFyYW1ldGVyXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKG5hbWUgPT0gXCJTeXN0ZW1cIikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwicGFyYW1ldGVyIGNhcHR1cmVzIFN5c3RlbVwiLCBub2RlTG9jYXRpb24obmFtZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUGFyYW1ldGVyXCIpLCBsb2NhdGlvbiwgbmFtZSxcbiAgICB0eXBlOiBjb252ZXJ0VHlwZSh0eXBlTm9kZSwgYFBhcmFtZXRlciAnJHtuYW1lfSdgLCBsb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfSwge25hbWU6IG5vZGVMb2NhdGlvbihuYW1lTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSl9KVxufVxuXG4vKipcbiAqIENvbnZlcnRzIHRoZSBleGFjdCBmaW5hbCB6ZXJvLWFyZ3VtZW50IE1haW4gbWV0aG9kLlxuICogQHBhcmFtIHtpbXBvcnQoXCJ0cmVlLXNpdHRlclwiKS5TeW50YXhOb2RlfSBub2RlIC0gTWFpbiBtZXRob2Qgbm9kZS5cbiAqIEBwYXJhbSB7Q1NoYXJwQ29udGV4dH0gY29udGV4dCAtIENvbW1lbnQtY2FycmllciBzdGF0ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UgdGV4dC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FbnRyeVBvaW50fSBTZW1hbnRpYyBlbnRyeSBwb2ludC5cbiAqL1xuZnVuY3Rpb24gY29udmVydE1haW4obm9kZSwgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBjaGlsZHJlbiA9IHNlbWFudGljQ2hpbGRyZW4obm9kZSlcbiAgY29uc3QgbW9kaWZpZXJzID0gY2hpbGRyZW4uZmlsdGVyKChjaGlsZCkgPT4gY2hpbGQudHlwZSA9PSBcIm1vZGlmaWVyXCIpXG4gIGNvbnN0IG5hbWUgPSByZXF1aXJlZEZpZWxkKG5vZGUsIFwibmFtZVwiLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCByZXR1cm5zID0gcmVxdWlyZWRGaWVsZChub2RlLCBcInJldHVybnNcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgcGFyYW1ldGVycyA9IHJlcXVpcmVkRmllbGQobm9kZSwgXCJwYXJhbWV0ZXJzXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGJvZHkgPSByZXF1aXJlZEZpZWxkKG5vZGUsIFwiYm9keVwiLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChjaGlsZHJlbi5sZW5ndGggIT0gNiB8fCBtb2RpZmllcnMubWFwKCh7dGV4dH0pID0+IHRleHQpLmpvaW4oXCIgXCIpICE9IFwicHJpdmF0ZSBzdGF0aWNcIiB8fCBuYW1lLnRleHQgIT0gXCJNYWluXCIgfHwgcmV0dXJucy50ZXh0ICE9IFwidm9pZFwiIHx8XG4gICAgc2VtYW50aWNDaGlsZHJlbihwYXJhbWV0ZXJzKS5sZW5ndGggIT0gMCkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwiTWFpbiBzY2FmZm9sZGluZ1wiLCBsb2NhdGlvbilcbiAgcmV0dXJuIHtib2R5OiBjb252ZXJ0QmxvY2soYm9keSwgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSksIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkVudHJ5UG9pbnRcIiksIGxvY2F0aW9ufVxufVxuXG4vKipcbiAqIFJlcXVpcmVzIGV4YWN0bHkgb25lIGNoZWNrZWQgd3JhcHBlciBhcm91bmQgZXZlcnkgaW50ZWdlciBhcml0aG1ldGljIHJvb3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBtb2R1bGUgLSBSZXNvbHZlZCBzZW1hbnRpYyBtb2R1bGUuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVDaGVja2VkQXJpdGhtZXRpYyhtb2R1bGUpIHtcbiAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9uW119ICovXG4gIGNvbnN0IGV4cHJlc3Npb25zID0gW11cbiAgLyoqXG4gICAqIENvbGxlY3RzIGV4cHJlc3Npb25zIHJlY3Vyc2l2ZWx5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259IGV4cHJlc3Npb24gLSBDdXJyZW50IGV4cHJlc3Npb24uXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgY29uc3QgdmlzaXRFeHByZXNzaW9uID0gKGV4cHJlc3Npb24pID0+IHtcbiAgICBleHByZXNzaW9ucy5wdXNoKGV4cHJlc3Npb24pXG4gICAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIlVuYXJ5RXhwcmVzc2lvblwiKSB2aXNpdEV4cHJlc3Npb24oZXhwcmVzc2lvbi5vcGVyYW5kKVxuICAgIGVsc2UgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkJpbmFyeUV4cHJlc3Npb25cIikge1xuICAgICAgdmlzaXRFeHByZXNzaW9uKGV4cHJlc3Npb24ubGVmdClcbiAgICAgIHZpc2l0RXhwcmVzc2lvbihleHByZXNzaW9uLnJpZ2h0KVxuICAgIH0gZWxzZSBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiQ2FsbEV4cHJlc3Npb25cIikgZXhwcmVzc2lvbi5hcmd1bWVudHMuZm9yRWFjaCh2aXNpdEV4cHJlc3Npb24pXG4gIH1cbiAgLyoqXG4gICAqIENvbGxlY3RzIGV4cHJlc3Npb25zIGZyb20gYSBzZW1hbnRpYyBibG9jay5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5CbG9ja30gYmxvY2sgLSBDdXJyZW50IGJsb2NrLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGNvbnN0IHZpc2l0QmxvY2sgPSAoYmxvY2spID0+IGJsb2NrLnN0YXRlbWVudHMuZm9yRWFjaCgoc3RhdGVtZW50KSA9PiB7XG4gICAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiTG9jYWxEZWNsYXJhdGlvblwiKSB2aXNpdEV4cHJlc3Npb24oc3RhdGVtZW50LmluaXRpYWxpemVyKVxuICAgIGVsc2UgaWYgKHN0YXRlbWVudC5raW5kID09IFwiQXNzaWdubWVudFN0YXRlbWVudFwiIHx8IHN0YXRlbWVudC5raW5kID09IFwiUHJpbnRTdGF0ZW1lbnRcIiB8fCBzdGF0ZW1lbnQua2luZCA9PSBcIlJldHVyblN0YXRlbWVudFwiKSB7XG4gICAgICB2aXNpdEV4cHJlc3Npb24oc3RhdGVtZW50LmV4cHJlc3Npb24pXG4gICAgfSBlbHNlIHtcbiAgICAgIHZpc2l0RXhwcmVzc2lvbihzdGF0ZW1lbnQuY29uZGl0aW9uKVxuICAgICAgdmlzaXRCbG9jayhzdGF0ZW1lbnQuY29uc2VxdWVudClcbiAgICAgIGlmIChzdGF0ZW1lbnQuYWx0ZXJuYXRlKSB2aXNpdEJsb2NrKHN0YXRlbWVudC5hbHRlcm5hdGUpXG4gICAgfVxuICB9KVxuXG4gIG1vZHVsZS5mdW5jdGlvbnMuZm9yRWFjaCgoZGVjbGFyYXRpb24pID0+IHZpc2l0QmxvY2soZGVjbGFyYXRpb24uYm9keSkpXG4gIHZpc2l0QmxvY2sobW9kdWxlLmVudHJ5UG9pbnQuYm9keSlcbiAgZm9yIChjb25zdCBleHByZXNzaW9uIG9mIGV4cHJlc3Npb25zKSB7XG4gICAgY29uc3QgYXJpdGhtZXRpYyA9IGV4cHJlc3Npb24ua2luZCA9PSBcIlVuYXJ5RXhwcmVzc2lvblwiICYmIGV4cHJlc3Npb24ub3BlcmF0aW9uID09IFwiSW50ZWdlck5lZ2F0ZVwiIHx8XG4gICAgICBleHByZXNzaW9uLmtpbmQgPT0gXCJCaW5hcnlFeHByZXNzaW9uXCIgJiYgW1wiSW50ZWdlckFkZFwiLCBcIkludGVnZXJTdWJ0cmFjdFwiLCBcIkludGVnZXJNdWx0aXBseVwiXS5pbmNsdWRlcyhleHByZXNzaW9uLm9wZXJhdGlvbilcblxuICAgIGlmIChhcml0aG1ldGljICE9IGNoZWNrZWRBcml0aG1ldGljLmhhcyhleHByZXNzaW9uKSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIGFyaXRobWV0aWMgPyBcImludGVnZXIgYXJpdGhtZXRpYyB3aXRob3V0IGV4YWN0IGNoZWNrZWQgd3JhcHBlclwiIDogXCJjaGVja2VkIG5vbi1pbnRlZ2VyIGV4cHJlc3Npb25cIixcbiAgICAgICAgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBQYXJzZXMgdGhlIHN0cmljdCBUYXNrIDAxNyBDIyBwcm9maWxlLlxuICogQHBhcmFtIHt7ZmlsZW5hbWU6IHN0cmluZywgc291cmNlOiBzdHJpbmd9fSBpbnB1dCAtIFBhcnNlciBpbnB1dC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gU2VtYW50aWMgbW9kdWxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VDU2hhcnAoe2ZpbGVuYW1lLCBzb3VyY2V9KSB7XG4gIGlmICghaGFzT25seVVuaWNvZGVTY2FsYXJzKHNvdXJjZSkpIHtcbiAgICBjb25zdCBpbnZhbGlkT2Zmc2V0ID0gZmlyc3RMb25lU3Vycm9nYXRlT2Zmc2V0KHNvdXJjZSlcblxuICAgIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe2NvZGU6IFwiUEFSU0VfRVJST1JcIiwgbGFuZ3VhZ2U6IFwiY3NoYXJwXCIsXG4gICAgICBsb2NhdGlvbjogbG9jYXRpb25Gcm9tT2Zmc2V0cyhmaWxlbmFtZSwgc291cmNlLCBpbnZhbGlkT2Zmc2V0LCBpbnZhbGlkT2Zmc2V0ICsgMSksXG4gICAgICBtZXNzYWdlOiBcIkMjIHNvdXJjZSBjb250YWlucyBhbiBpbnZhbGlkIGxvbmUgVVRGLTE2IHN1cnJvZ2F0ZS5cIn0pXG4gIH1cbiAgbGV0IHRyZWVcblxuICB0cnkge1xuICAgIHRyZWUgPSBwYXJzZXIucGFyc2Uoc291cmNlKVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJldHVybiBwYXJzZUZhaWx1cmUoXCJjc2hhcnBcIiwgZXJyb3IpXG4gIH1cbiAgY29uc3Qgcm9vdCA9IHRyZWUucm9vdE5vZGVcblxuICB2YWxpZGF0ZVBhcnNlclRyZWUocm9vdCwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgaWYgKHJvb3QudHlwZSAhPSBcImNvbXBpbGF0aW9uX3VuaXRcIikgdGhyb3cgbmV3IEVycm9yKGBUcmVlLXNpdHRlciByZXR1cm5lZCBDIyByb290ICcke3Jvb3QudHlwZX0nLmApXG4gIGNvbnN0IGNoaWxkcmVuID0gc2VtYW50aWNDaGlsZHJlbihyb290KVxuICBjb25zdCBsb2NhdGlvbiA9IG1vZHVsZUxvY2F0aW9uKGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKGNoaWxkcmVuLmxlbmd0aCAhPSAzIHx8IGNoaWxkcmVuWzBdLnR5cGUgIT0gXCJwcmVwcm9jX251bGxhYmxlXCIgfHxcbiAgICAhL14jbnVsbGFibGUgZW5hYmxlKD86KD86XFxyXFxufFxcbnxcXHIpKSskL3UudGVzdChjaGlsZHJlblswXS50ZXh0KSB8fFxuICAgIGNoaWxkcmVuWzFdLnR5cGUgIT0gXCJmaWxlX3Njb3BlZF9uYW1lc3BhY2VfZGVjbGFyYXRpb25cIiB8fCBjaGlsZHJlblsyXS50eXBlICE9IFwiY2xhc3NfZGVjbGFyYXRpb25cIikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcImNvbXBpbGF0aW9uLXVuaXQgc2NhZmZvbGRpbmdcIiwgbG9jYXRpb24pXG4gIH1cbiAgY29uc3QgbmFtZXNwYWNlTmFtZSA9IHJlcXVpcmVkRmllbGQoY2hpbGRyZW5bMV0sIFwibmFtZVwiLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChuYW1lc3BhY2VOYW1lLnRleHQgIT0gXCJTZW1hbnRpZm9sZC5HZW5lcmF0ZWRcIikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcIm5hbWVzcGFjZSBzY2FmZm9sZGluZ1wiLCBub2RlTG9jYXRpb24oY2hpbGRyZW5bMV0sIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG4gIGNvbnN0IGNsYXNzTm9kZSA9IGNoaWxkcmVuWzJdXG4gIGNvbnN0IGNsYXNzTmFtZSA9IHJlcXVpcmVkRmllbGQoY2xhc3NOb2RlLCBcIm5hbWVcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgY2xhc3NCb2R5ID0gcmVxdWlyZWRGaWVsZChjbGFzc05vZGUsIFwiYm9keVwiLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBjbGFzc0NoaWxkcmVuID0gc2VtYW50aWNDaGlsZHJlbihjbGFzc05vZGUpXG4gIGNvbnN0IGNsYXNzTW9kaWZpZXJzID0gY2xhc3NDaGlsZHJlbi5maWx0ZXIoKGNoaWxkKSA9PiBjaGlsZC50eXBlID09IFwibW9kaWZpZXJcIilcblxuICBpZiAoY2xhc3NDaGlsZHJlbi5sZW5ndGggIT0gNCB8fCBjbGFzc05hbWUudGV4dCAhPSBcIlByb2dyYW1cIiB8fFxuICAgIGNsYXNzTW9kaWZpZXJzLm1hcCgoe3RleHR9KSA9PiB0ZXh0KS5qb2luKFwiIFwiKSAhPSBcImludGVybmFsIHN0YXRpY1wiKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiY3NoYXJwXCIsIFwiUHJvZ3JhbSBjbGFzcyBzY2FmZm9sZGluZ1wiLCBub2RlTG9jYXRpb24oY2xhc3NOb2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICBjb25zdCBtZW1iZXJzID0gc2VtYW50aWNDaGlsZHJlbihjbGFzc0JvZHkpXG5cbiAgaWYgKG1lbWJlcnMubGVuZ3RoIDwgMiB8fCBtZW1iZXJzLnNvbWUoKG1lbWJlcikgPT4gbWVtYmVyLnR5cGUgIT0gXCJtZXRob2RfZGVjbGFyYXRpb25cIikpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgXCJQcm9ncmFtIG1lbWJlcnNcIiwgbm9kZUxvY2F0aW9uKGNsYXNzQm9keSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cbiAgY29uc3QgbWFpbk5vZGVzID0gbWVtYmVycy5maWx0ZXIoKG1lbWJlcikgPT4gbWVtYmVyLmNoaWxkRm9yRmllbGROYW1lKFwibmFtZVwiKT8udGV4dCA9PSBcIk1haW5cIilcblxuICBpZiAobWFpbk5vZGVzLmxlbmd0aCAhPSAxIHx8IG1lbWJlcnMuYXQoLTEpPy5pZCAhPSBtYWluTm9kZXNbMF0uaWQpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJjc2hhcnBcIiwgXCJNYWluIG9yZGVyaW5nXCIsIG5vZGVMb2NhdGlvbihjbGFzc0JvZHksIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG4gIGNvbnN0IGNvbW1lbnRzID0gcm9vdC5kZXNjZW5kYW50c09mVHlwZShcImNvbW1lbnRcIilcbiAgY29uc3QgY29udGV4dCA9IHtjb21tZW50cywgdXNlZEltbXV0YWJsZU1hcmtlcnM6IG5ldyBTZXQoKX1cbiAgY29uc3QgbW9kdWxlID0ge1xuICAgIGVudHJ5UG9pbnQ6IGNvbnZlcnRNYWluKG1haW5Ob2Rlc1swXSwgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgZnVuY3Rpb25zOiBtZW1iZXJzLnNsaWNlKDAsIC0xKS5tYXAoKG1lbWJlcikgPT4gY29udmVydEZ1bmN0aW9uKG1lbWJlciwgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSkpLFxuICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIk1vZHVsZVwiKSxcbiAgICBsb2NhdGlvblxuICB9XG4gIGNvbnN0IHVudXNlZE1hcmtlciA9IGNvbW1lbnRzLmZpbmQoKGNvbW1lbnQpID0+IGNvbW1lbnQudGV4dCA9PSBpbW11dGFibGVNYXJrZXIgJiYgIWNvbnRleHQudXNlZEltbXV0YWJsZU1hcmtlcnMuaGFzKGNvbW1lbnQpKVxuXG4gIGlmICh1bnVzZWRNYXJrZXIpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImNzaGFycFwiLCBcInVuYXR0YWNoZWQgaW1tdXRhYmxlIG1hcmtlclwiLCBub2RlTG9jYXRpb24odW51c2VkTWFya2VyLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgdmFsaWRhdGVQYXJzZWRNb2R1bGUobW9kdWxlLCBcImNzaGFycFwiKVxuICB2YWxpZGF0ZUNoZWNrZWRBcml0aG1ldGljKG1vZHVsZSlcbiAgcmV0dXJuIG1vZHVsZVxufVxuIl19
|