1 | /**
|
2 | * @license
|
3 | * Copyright Google LLC All Rights Reserved.
|
4 | *
|
5 | * Use of this source code is governed by an MIT-style license that can be
|
6 | * found in the LICENSE file at https://angular.io/license
|
7 | */
|
8 | (function (factory) {
|
9 | if (typeof module === "object" && typeof module.exports === "object") {
|
10 | var v = factory(require, exports);
|
11 | if (v !== undefined) module.exports = v;
|
12 | }
|
13 | else if (typeof define === "function" && define.amd) {
|
14 | define("@angular/language-service/src/definitions", ["require", "exports", "tslib", "typescript", "@angular/language-service/src/locate_symbol", "@angular/language-service/src/ts_utils", "@angular/language-service/src/utils"], factory);
|
15 | }
|
16 | })(function (require, exports) {
|
17 | ;
|
18 | Object.defineProperty(exports, "__esModule", { value: true });
|
19 | exports.getTsDefinitionAndBoundSpan = exports.getDefinitionAndBoundSpan = void 0;
|
20 | var tslib_1 = require("tslib");
|
21 | var ts = require("typescript"); // used as value and is provided at runtime
|
22 | var locate_symbol_1 = require("@angular/language-service/src/locate_symbol");
|
23 | var ts_utils_1 = require("@angular/language-service/src/ts_utils");
|
24 | var utils_1 = require("@angular/language-service/src/utils");
|
25 | /**
|
26 | * Convert Angular Span to TypeScript TextSpan. Angular Span has 'start' and
|
27 | * 'end' whereas TS TextSpan has 'start' and 'length'.
|
28 | * @param span Angular Span
|
29 | */
|
30 | function ngSpanToTsTextSpan(span) {
|
31 | return {
|
32 | start: span.start,
|
33 | length: span.end - span.start,
|
34 | };
|
35 | }
|
36 | /**
|
37 | * Attempts to get the definition of a file whose URL is specified in a property assignment in a
|
38 | * directive decorator.
|
39 | * Currently applies to `templateUrl` and `styleUrls` properties.
|
40 | */
|
41 | function getUrlFromProperty(urlNode, tsLsHost) {
|
42 | // Get the property assignment node corresponding to the `templateUrl` or `styleUrls` assignment.
|
43 | // These assignments are specified differently; `templateUrl` is a string, and `styleUrls` is
|
44 | // an array of strings:
|
45 | // {
|
46 | // templateUrl: './template.ng.html',
|
47 | // styleUrls: ['./style.css', './other-style.css']
|
48 | // }
|
49 | // `templateUrl`'s property assignment can be found from the string literal node;
|
50 | // `styleUrls`'s property assignment can be found from the array (parent) node.
|
51 | //
|
52 | // First search for `templateUrl`.
|
53 | var asgn = ts_utils_1.getPropertyAssignmentFromValue(urlNode, 'templateUrl');
|
54 | if (!asgn) {
|
55 | // `templateUrl` assignment not found; search for `styleUrls` array assignment.
|
56 | asgn = ts_utils_1.getPropertyAssignmentFromValue(urlNode.parent, 'styleUrls');
|
57 | if (!asgn) {
|
58 | // Nothing found, bail.
|
59 | return;
|
60 | }
|
61 | }
|
62 | // If the property assignment is not a property of a class decorator, don't generate definitions
|
63 | // for it.
|
64 | if (!ts_utils_1.getClassDeclFromDecoratorProp(asgn)) {
|
65 | return;
|
66 | }
|
67 | // Extract url path specified by the url node, which is relative to the TypeScript source file
|
68 | // the url node is defined in.
|
69 | var url = utils_1.extractAbsoluteFilePath(urlNode);
|
70 | // If the file does not exist, bail. It is possible that the TypeScript language service host
|
71 | // does not have a `fileExists` method, in which case optimistically assume the file exists.
|
72 | if (tsLsHost.fileExists && !tsLsHost.fileExists(url))
|
73 | return;
|
74 | var templateDefinitions = [{
|
75 | kind: ts.ScriptElementKind.externalModuleName,
|
76 | name: url,
|
77 | containerKind: ts.ScriptElementKind.unknown,
|
78 | containerName: '',
|
79 | // Reading the template is expensive, so don't provide a preview.
|
80 | textSpan: { start: 0, length: 0 },
|
81 | fileName: url,
|
82 | }];
|
83 | return {
|
84 | definitions: templateDefinitions,
|
85 | textSpan: {
|
86 | // Exclude opening and closing quotes in the url span.
|
87 | start: urlNode.getStart() + 1,
|
88 | length: urlNode.getWidth() - 2,
|
89 | },
|
90 | };
|
91 | }
|
92 | /**
|
93 | * Traverse the template AST and look for the symbol located at `position`, then
|
94 | * return its definition and span of bound text.
|
95 | * @param info
|
96 | * @param position
|
97 | */
|
98 | function getDefinitionAndBoundSpan(info, position) {
|
99 | var e_1, _a, e_2, _b;
|
100 | var symbols = locate_symbol_1.locateSymbols(info, position);
|
101 | if (!symbols.length) {
|
102 | return;
|
103 | }
|
104 | var seen = new Set();
|
105 | var definitions = [];
|
106 | try {
|
107 | for (var symbols_1 = tslib_1.__values(symbols), symbols_1_1 = symbols_1.next(); !symbols_1_1.done; symbols_1_1 = symbols_1.next()) {
|
108 | var symbolInfo = symbols_1_1.value;
|
109 | var symbol = symbolInfo.symbol;
|
110 | // symbol.definition is really the locations of the symbol. There could be
|
111 | // more than one. No meaningful info could be provided without any location.
|
112 | var kind = symbol.kind, name_1 = symbol.name, container = symbol.container, locations = symbol.definition;
|
113 | if (!locations || !locations.length) {
|
114 | continue;
|
115 | }
|
116 | var containerKind = container ? container.kind : ts.ScriptElementKind.unknown;
|
117 | var containerName = container ? container.name : '';
|
118 | try {
|
119 | for (var locations_1 = (e_2 = void 0, tslib_1.__values(locations)), locations_1_1 = locations_1.next(); !locations_1_1.done; locations_1_1 = locations_1.next()) {
|
120 | var _c = locations_1_1.value, fileName = _c.fileName, span = _c.span;
|
121 | var textSpan = ngSpanToTsTextSpan(span);
|
122 | // In cases like two-way bindings, a request for the definitions of an expression may return
|
123 | // two of the same definition:
|
124 | // [(ngModel)]="prop"
|
125 | // ^^^^ -- one definition for the property binding, one for the event binding
|
126 | // To prune duplicate definitions, tag definitions with unique location signatures and ignore
|
127 | // definitions whose locations have already been seen.
|
128 | var signature = textSpan.start + ":" + textSpan.length + "@" + fileName;
|
129 | if (seen.has(signature))
|
130 | continue;
|
131 | definitions.push({
|
132 | kind: kind,
|
133 | name: name_1,
|
134 | containerKind: containerKind,
|
135 | containerName: containerName,
|
136 | textSpan: ngSpanToTsTextSpan(span),
|
137 | fileName: fileName,
|
138 | });
|
139 | seen.add(signature);
|
140 | }
|
141 | }
|
142 | catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
143 | finally {
|
144 | try {
|
145 | if (locations_1_1 && !locations_1_1.done && (_b = locations_1.return)) _b.call(locations_1);
|
146 | }
|
147 | finally { if (e_2) throw e_2.error; }
|
148 | }
|
149 | }
|
150 | }
|
151 | catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
152 | finally {
|
153 | try {
|
154 | if (symbols_1_1 && !symbols_1_1.done && (_a = symbols_1.return)) _a.call(symbols_1);
|
155 | }
|
156 | finally { if (e_1) throw e_1.error; }
|
157 | }
|
158 | return {
|
159 | definitions: definitions,
|
160 | textSpan: symbols[0].span,
|
161 | };
|
162 | }
|
163 | exports.getDefinitionAndBoundSpan = getDefinitionAndBoundSpan;
|
164 | /**
|
165 | * Gets an Angular-specific definition in a TypeScript source file.
|
166 | */
|
167 | function getTsDefinitionAndBoundSpan(sf, position, tsLsHost) {
|
168 | var node = ts_utils_1.findTightestNode(sf, position);
|
169 | if (!node)
|
170 | return;
|
171 | switch (node.kind) {
|
172 | case ts.SyntaxKind.StringLiteral:
|
173 | case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
|
174 | // Attempt to extract definition of a URL in a property assignment.
|
175 | return getUrlFromProperty(node, tsLsHost);
|
176 | default:
|
177 | return undefined;
|
178 | }
|
179 | }
|
180 | exports.getTsDefinitionAndBoundSpan = getTsDefinitionAndBoundSpan;
|
181 | });
|
182 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmaW5pdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9sYW5ndWFnZS1zZXJ2aWNlL3NyYy9kZWZpbml0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7Ozs7O0lBRUgsK0JBQWlDLENBQUUsMkNBQTJDO0lBRTlFLDZFQUE4QztJQUM5QyxtRUFBMkc7SUFFM0csNkRBQWdEO0lBRWhEOzs7O09BSUc7SUFDSCxTQUFTLGtCQUFrQixDQUFDLElBQVU7UUFDcEMsT0FBTztZQUNMLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztZQUNqQixNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSztTQUM5QixDQUFDO0lBQ0osQ0FBQztJQUNEOzs7O09BSUc7SUFDSCxTQUFTLGtCQUFrQixDQUN2QixPQUE2QixFQUM3QixRQUEwQztRQUM1QyxpR0FBaUc7UUFDakcsNkZBQTZGO1FBQzdGLHVCQUF1QjtRQUN2QixNQUFNO1FBQ04sNENBQTRDO1FBQzVDLHlEQUF5RDtRQUN6RCxNQUFNO1FBQ04saUZBQWlGO1FBQ2pGLCtFQUErRTtRQUMvRSxFQUFFO1FBQ0Ysa0NBQWtDO1FBQ2xDLElBQUksSUFBSSxHQUFHLHlDQUE4QixDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ1QsK0VBQStFO1lBQy9FLElBQUksR0FBRyx5Q0FBOEIsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ25FLElBQUksQ0FBQyxJQUFJLEVBQUU7Z0JBQ1QsdUJBQXVCO2dCQUN2QixPQUFPO2FBQ1I7U0FDRjtRQUVELGdHQUFnRztRQUNoRyxVQUFVO1FBQ1YsSUFBSSxDQUFDLHdDQUE2QixDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ3hDLE9BQU87U0FDUjtRQUVELDhGQUE4RjtR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Q0osYUFBYSxlQUFBOzRCQUNiLGFBQWEsZUFBQTs0QkFDYixRQUFRLEVBQUUsa0JBQWtCLENBQUMsSUFBSSxDQUFDOzRCQUNsQyxRQUFRLEVBQUUsUUFBUTt5QkFDbkIsQ0FBQyxDQUFDO3dCQUNILElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7cUJBQ3JCOzs7Ozs7Ozs7YUFDRjs7Ozs7Ozs7O1FBRUQsT0FBTztZQUNMLFdBQVcsYUFBQTtZQUNYLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtTQUMxQixDQUFDO0lBQ0osQ0FBQztJQWxERCw4REFrREM7SUFFRDs7T0FFRztJQUNILFNBQWdCLDJCQUEyQixDQUN2QyxFQUFpQixFQUFFLFFBQWdCLEVBQ25DLFFBQTBDO1FBQzVDLElBQU0sSUFBSSxHQUFHLDJCQUFnQixDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU87UUFDbEIsUUFBUSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ2pCLEtBQUssRUFBRSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUM7WUFDakMsS0FBSyxFQUFFLENBQUMsVUFBVSxDQUFDLDZCQUE2QjtnQkFDOUMsbUVBQW1FO2dCQUNuRSxPQUFPLGtCQUFrQixDQUFDLElBQTRCLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDcEU7Z0JBQ0UsT0FBTyxTQUFTLENBQUM7U0FDcEI7SUFDSCxDQUFDO0lBYkQsa0VBYUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0ICogYXMgdHMgZnJvbSAndHlwZXNjcmlwdCc7ICAvLyB1c2VkIGFzIHZhbHVlIGFuZCBpcyBwcm92aWRlZCBhdCBydW50aW1lXG5cbmltcG9ydCB7bG9jYXRlU3ltYm9sc30gZnJvbSAnLi9sb2NhdGVfc3ltYm9sJztcbmltcG9ydCB7ZmluZFRpZ2h0ZXN0Tm9kZSwgZ2V0Q2xhc3NEZWNsRnJvbURlY29yYXRvclByb3AsIGdldFByb3BlcnR5QXNzaWdubWVudEZyb21WYWx1ZX0gZnJvbSAnLi90c191dGlscyc7XG5pbXBvcnQge0FzdFJlc3VsdCwgU3Bhbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge2V4dHJhY3RBYnNvbHV0ZUZpbGVQYXRofSBmcm9tICcuL3V0aWxzJztcblxuLyoqXG4gKiBDb252ZXJ0IEFuZ3VsYXIgU3BhbiB0byBUeXBlU2NyaXB0IFRleHRTcGFuLiBBbmd1bGFyIFNwYW4gaGFzICdzdGFydCcgYW5kXG4gKiAnZW5kJyB3aGVyZWFzIFRTIFRleHRTcGFuIGhhcyAnc3RhcnQnIGFuZCAnbGVuZ3RoJy5cbiAqIEBwYXJhbSBzcGFuIEFuZ3VsYXIgU3BhblxuICovXG5mdW5jdGlvbiBuZ1NwYW5Ub1RzVGV4dFNwYW4oc3BhbjogU3Bhbik6IHRzLlRleHRTcGFuIHtcbiAgcmV0dXJuIHtcbiAgICBzdGFydDogc3Bhbi5zdGFydCxcbiAgICBsZW5ndGg6IHNwYW4uZW5kIC0gc3Bhbi5zdGFydCxcbiAgfTtcbn1cbi8qKlxuICogQXR0ZW1wdHMgdG8gZ2V0IHRoZSBkZWZpbml0aW9uIG9mIGEgZmlsZSB3aG9zZSBVUkwgaXMgc3BlY2lmaWVkIGluIGEgcHJvcGVydHkgYXNzaWdubWVudCBpbiBhXG4gKiBkaXJlY3RpdmUgZGVjb3JhdG9yLlxuICogQ3VycmVudGx5IGFwcGxpZXMgdG8gYHRlbXBsYXRlVXJsYCBhbmQgYHN0eWxlVXJsc2AgcHJvcGVydGllcy5cbiAqL1xuZnVuY3Rpb24gZ2V0VXJsRnJvbVByb3BlcnR5KFxuICAgIHVybE5vZGU6IHRzLlN0cmluZ0xpdGVyYWxMaWtlLFxuICAgIHRzTHNIb3N0OiBSZWFkb25seTx0cy5MYW5ndWFnZVNlcnZpY2VIb3N0Pik6IHRzLkRlZmluaXRpb25JbmZvQW5kQm91bmRTcGFufHVuZGVmaW5lZCB7XG4gIC8vIEdldCB0aGUgcHJvcGVydHkgYXNzaWdubWVudCBub2RlIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGB0ZW1wbGF0ZVVybGAgb3IgYHN0eWxlVXJsc2AgYXNzaWdubWVudC5cbiAgLy8gVGhlc2UgYXNzaWdubWVudHMgYXJlIHNwZWNpZmllZCBkaWZmZXJlbnRseTsgYHRlbXBsYXRlVXJsYCBpcyBhIHN0cmluZywgYW5kIGBzdHlsZVVybHNgIGlzXG4gIC8vIGFuIGFycmF5IG9mIHN0cmluZ3M6XG4gIC8vICAge1xuICAvLyAgICAgICAgdGVtcGxhdGVVcmw6ICcuL3RlbXBsYXRlLm5nLmh0bWwnLFxuICAvLyAgICAgICAgc3R5bGVVcmxzOiBbJy4vc3R5bGUuY3NzJywgJy4vb3RoZXItc3R5bGUuY3NzJ11cbiAgLy8gICB9XG4gIC8vIGB0ZW1wbGF0ZVVybGAncyBwcm9wZXJ0eSBhc3NpZ25tZW50IGNhbiBiZSBmb3VuZCBmcm9tIHRoZSBzdHJpbmcgbGl0ZXJhbCBub2RlO1xuICAvLyBgc3R5bGVVcmxzYCdzIHByb3BlcnR5IGFzc2lnbm1lbnQgY2FuIGJlIGZvdW5kIGZyb20gdGhlIGFycmF5IChwYXJlbnQpIG5vZGUuXG4gIC8vXG4gIC8vIEZpcnN0IHNlYXJjaCBmb3IgYHRlbXBsYXRlVXJsYC5cbiAgbGV0IGFzZ24gPSBnZXRQcm9wZXJ0eUFzc2lnbm1lbnRGcm9tVmFsdWUodXJsTm9kZSwgJ3RlbXBsYXRlVXJsJyk7XG4gIGlmICghYXNnbikge1xuICAgIC8vIGB0ZW1wbGF0ZVVybGAgYXNzaWdubWVudCBub3QgZm91bmQ7IHNlYXJjaCBmb3IgYHN0eWxlVXJsc2AgYXJyYXkgYXNzaWdubWVudC5cbiAgICBhc2duID0gZ2V0UHJvcGVydHlBc3NpZ25tZW50RnJvbVZhbHVlKHVybE5vZGUucGFyZW50LCAnc3R5bGVVcmxzJyk7XG4gICAgaWYgKCFhc2duKSB7XG4gICAgICAvLyBOb3RoaW5nIGZvdW5kLCBiYWlsLlxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIC8vIElmIHRoZSBwcm9wZXJ0eSBhc3NpZ25tZW50IGlzIG5vdCBhIHByb3BlcnR5IG9mIGEgY2xhc3MgZGVjb3JhdG9yLCBkb24ndCBnZW5lcmF0ZSBkZWZpbml0aW9uc1xuICAvLyBmb3IgaXQuXG4gIGlmICghZ2V0Q2xhc3NEZWNsRnJvbURlY29yYXRvclByb3AoYXNnbikpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBFeHRyYWN0IHVybCBwYXRoIHNwZWNpZmllZCBieSB0aGUgdXJsIG5vZGUsIHdoaWNoIGlzIHJlbGF0aXZlIHRvIHRoZSBUeXBlU2NyaXB0IHNvdXJjZSBmaWxlXG4gIC8vIHRoZSB1cmwgbm9kZSBpcyBkZWZpbmVkIGluLlxuICBjb25zdCB1cmwgPSBleHRyYWN0QWJzb2x1dGVGaWxlUGF0aCh1cmxOb2RlKTtcblxuICAvLyBJZiB0aGUgZmlsZSBkb2VzIG5vdCBleGlzdCwgYmFpbC4gSXQgaXMgcG9zc2libGUgdGhhdCB0aGUgVHlwZVNjcmlwdCBsYW5ndWFnZSBzZXJ2aWNlIGhvc3RcbiAgLy8gZG9lcyBub3QgaGF2ZSBhIGBmaWxlRXhpc3RzYCBtZXRob2QsIGluIHdoaWNoIGNhc2Ugb3B0aW1pc3RpY2FsbHkgYXNzdW1lIHRoZSBmaWxlIGV4aXN0cy5cbiAgaWYgKHRzTHNIb3N0LmZpbGVFeGlzdHMgJiYgIXRzTHNIb3N0LmZpbGVFeGlzdHModXJsKSkgcmV0dXJuO1xuXG4gIGNvbnN0IHRlbXBsYXRlRGVmaW5pdGlvbnM6IHRzLkRlZmluaXRpb25JbmZvW10gPSBbe1xuICAgIGtpbmQ6IHRzLlNjcmlwdEVsZW1lbnRLaW5kLmV4dGVybmFsTW9kdWxlTmFtZSxcbiAgICBuYW1lOiB1cmwsXG4gICAgY29udGFpbmVyS2luZDogdHMuU2NyaXB0RWxlbWVudEtpbmQudW5rbm93bixcbiAgICBjb250YWluZXJOYW1lOiAnJyxcbiAgICAvLyBSZWFkaW5nIHRoZSB0ZW1wbGF0ZSBpcyBleHBlbnNpdmUsIHNvIGRvbid0IHByb3ZpZGUgYSBwcmV2aWV3LlxuICAgIHRleHRTcGFuOiB7c3RhcnQ6IDAsIGxlbmd0aDogMH0sXG4gICAgZmlsZU5hbWU6IHVybCxcbiAgfV07XG5cbiAgcmV0dXJuIHtcbiAgICBkZWZpbml0aW9uczogdGVtcGxhdGVEZWZpbml0aW9ucyxcbiAgICB0ZXh0U3Bhbjoge1xuICAgICAgLy8gRXhjbHVkZSBvcGVuaW5nIGFuZCBjbG9zaW5nIHF1b3RlcyBpbiB0aGUgdXJsIHNwYW4uXG4gICAgICBzdGFydDogdXJsTm9kZS5nZXRTdGFydCgpICsgMSxcbiAgICAgIGxlbmd0aDogdXJsTm9kZS5nZXRXaWR0aCgpIC0gMixcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIFRyYXZlcnNlIHRoZSB0ZW1wbGF0ZSBBU1QgYW5kIGxvb2sgZm9yIHRoZSBzeW1ib2wgbG9jYXRlZCBhdCBgcG9zaXRpb25gLCB0aGVuXG4gKiByZXR1cm4gaXRzIGRlZmluaXRpb24gYW5kIHNwYW4gb2YgYm91bmQgdGV4dC5cbiAqIEBwYXJhbSBpbmZvXG4gKiBAcGFyYW0gcG9zaXRpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldERlZmluaXRpb25BbmRCb3VuZFNwYW4oXG4gICAgaW5mbzogQXN0UmVzdWx0LCBwb3NpdGlvbjogbnVtYmVyKTogdHMuRGVmaW5pdGlvbkluZm9BbmRCb3VuZFNwYW58dW5kZWZpbmVkIHtcbiAgY29uc3Qgc3ltYm9scyA9IGxvY2F0ZVN5bWJvbHMoaW5mbywgcG9zaXRpb24pO1xuICBpZiAoIXN5bWJvbHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBjb25zdCBkZWZpbml0aW9uczogdHMuRGVmaW5pdGlvbkluZm9bXSA9IFtdO1xuICBmb3IgKGNvbnN0IHN5bWJvbEluZm8gb2Ygc3ltYm9scykge1xuICAgIGNvbnN0IHtzeW1ib2x9ID0gc3ltYm9sSW5mbztcblxuICAgIC8vIHN5bWJvbC5kZWZpbml0aW9uIGlzIHJlYWxseSB0aGUgbG9jYXRpb25zIG9mIHRoZSBzeW1ib2wuIFRoZXJlIGNvdWxkIGJlXG4gICAgLy8gbW9yZSB0aGFuIG9uZS4gTm8gbWVhbmluZ2Z1bCBpbmZvIGNvdWxkIGJlIHByb3ZpZGVkIHdpdGhvdXQgYW55IGxvY2F0aW9uLlxuICAgIGNvbnN0IHtraW5kLCBuYW1lLCBjb250YWluZXIsIGRlZmluaXRpb246IGxvY2F0aW9uc30gPSBzeW1ib2w7XG4gICAgaWYgKCFsb2NhdGlvbnMgfHwgIWxvY2F0aW9ucy5sZW5ndGgpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnRhaW5lcktpbmQgPVxuICAgICAgICBjb250YWluZXIgPyBjb250YWluZXIua2luZCBhcyB0cy5TY3JpcHRFbGVtZW50S2luZCA6IHRzLlNjcmlwdEVsZW1lbnRLaW5kLnVua25vd247XG4gICAgY29uc3QgY29udGFpbmVyTmFtZSA9IGNvbnRhaW5lciA/IGNvbnRhaW5lci5uYW1lIDogJyc7XG5cbiAgICBmb3IgKGNvbnN0IHtmaWxlTmFtZSwgc3Bhbn0gb2YgbG9jYXRpb25zKSB7XG4gICAgICBjb25zdCB0ZXh0U3BhbiA9IG5nU3BhblRvVHNUZXh0U3BhbihzcGFuKTtcbiAgICAgIC8vIEluIGNhc2VzIGxpa2UgdHdvLXdheSBiaW5kaW5ncywgYSByZXF1ZXN0IGZvciB0aGUgZGVmaW5pdGlvbnMgb2YgYW4gZXhwcmVzc2lvbiBtYXkgcmV0dXJuXG4gICAgICAvLyB0d28gb2YgdGhlIHNhbWUgZGVmaW5pdGlvbjpcbiAgICAgIC8vICAgIFsobmdNb2RlbCldPVwicHJvcFwiXG4gICAgICAvLyAgICAgICAgICAgICAgICAgXl5eXiAgLS0gb25lIGRlZmluaXRpb24gZm9yIHRoZSBwcm9wZXJ0eSBiaW5kaW5nLCBvbmUgZm9yIHRoZSBldmVudCBiaW5kaW5nXG4gICAgICAvLyBUbyBwcnVuZSBkdXBsaWNhdGUgZGVmaW5pdGlvbnMsIHRhZyBkZWZpbml0aW9ucyB3aXRoIHVuaXF1ZSBsb2NhdGlvbiBzaWduYXR1cmVzIGFuZCBpZ25vcmVcbiAgICAgIC8vIGRlZmluaXRpb25zIHdob3NlIGxvY2F0aW9ucyBoYXZlIGFscmVhZHkgYmVlbiBzZWVuLlxuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gYCR7dGV4dFNwYW4uc3RhcnR9OiR7dGV4dFNwYW4ubGVuZ3RofUAke2ZpbGVOYW1lfWA7XG4gICAgICBpZiAoc2Vlbi5oYXMoc2lnbmF0dXJlKSkgY29udGludWU7XG5cbiAgICAgIGRlZmluaXRpb25zLnB1c2goe1xuICAgICAgICBraW5kOiBraW5kIGFzIHRzLlNjcmlwdEVsZW1lbnRLaW5kLFxuICAgICAgICBuYW1lLFxuICAgICAgICBjb250YWluZXJLaW5kLFxuICAgICAgICBjb250YWluZXJOYW1lLFxuICAgICAgICB0ZXh0U3BhbjogbmdTcGFuVG9Uc1RleHRTcGFuKHNwYW4pLFxuICAgICAgICBmaWxlTmFtZTogZmlsZU5hbWUsXG4gICAgICB9KTtcbiAgICAgIHNlZW4uYWRkKHNpZ25hdHVyZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBkZWZpbml0aW9ucyxcbiAgICB0ZXh0U3Bhbjogc3ltYm9sc1swXS5zcGFuLFxuICB9O1xufVxuXG4vKipcbiAqIEdldHMgYW4gQW5ndWxhci1zcGVjaWZpYyBkZWZpbml0aW9uIGluIGEgVHlwZVNjcmlwdCBzb3VyY2UgZmlsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRzRGVmaW5pdGlvbkFuZEJvdW5kU3BhbihcbiAgICBzZjogdHMuU291cmNlRmlsZSwgcG9zaXRpb246IG51bWJlcixcbiAgICB0c0xzSG9zdDogUmVhZG9ubHk8dHMuTGFuZ3VhZ2VTZXJ2aWNlSG9zdD4pOiB0cy5EZWZpbml0aW9uSW5mb0FuZEJvdW5kU3Bhbnx1bmRlZmluZWQge1xuICBjb25zdCBub2RlID0gZmluZFRpZ2h0ZXN0Tm9kZShzZiwgcG9zaXRpb24pO1xuICBpZiAoIW5vZGUpIHJldHVybjtcbiAgc3dpdGNoIChub2RlLmtpbmQpIHtcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuU3RyaW5nTGl0ZXJhbDpcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuTm9TdWJzdGl0dXRpb25UZW1wbGF0ZUxpdGVyYWw6XG4gICAgICAvLyBBdHRlbXB0IHRvIGV4dHJhY3QgZGVmaW5pdGlvbiBvZiBhIFVSTCBpbiBhIHByb3BlcnR5IGFzc2lnbm1lbnQuXG4gICAgICByZXR1cm4gZ2V0VXJsRnJvbVByb3BlcnR5KG5vZGUgYXMgdHMuU3RyaW5nTGl0ZXJhbExpa2UsIHRzTHNIb3N0KTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuIl19 |
\ | No newline at end of file |