UNPKG

15.5 kBJavaScriptView Raw
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/ts_utils", ["require", "exports", "tslib", "typescript/lib/tsserverlibrary"], factory);
15 }
16})(function (require, exports) {
17 "use strict";
18 Object.defineProperty(exports, "__esModule", { value: true });
19 exports.findPropertyValueOfType = exports.getDirectiveClassLike = exports.getClassDeclFromDecoratorProp = exports.getPropertyAssignmentFromValue = exports.findTightestNode = void 0;
20 var tslib_1 = require("tslib");
21 var ts = require("typescript/lib/tsserverlibrary");
22 /**
23 * Return the node that most tightly encompass the specified `position`.
24 * @param node
25 * @param position
26 */
27 function findTightestNode(node, position) {
28 if (node.getStart() <= position && position < node.getEnd()) {
29 return node.forEachChild(function (c) { return findTightestNode(c, position); }) || node;
30 }
31 }
32 exports.findTightestNode = findTightestNode;
33 /**
34 * Returns a property assignment from the assignment value if the property name
35 * matches the specified `key`, or `undefined` if there is no match.
36 */
37 function getPropertyAssignmentFromValue(value, key) {
38 var propAssignment = value.parent;
39 if (!propAssignment || !ts.isPropertyAssignment(propAssignment) ||
40 propAssignment.name.getText() !== key) {
41 return;
42 }
43 return propAssignment;
44 }
45 exports.getPropertyAssignmentFromValue = getPropertyAssignmentFromValue;
46 /**
47 * Given a decorator property assignment, return the ClassDeclaration node that corresponds to the
48 * directive class the property applies to.
49 * If the property assignment is not on a class decorator, no declaration is returned.
50 *
51 * For example,
52 *
53 * @Component({
54 * template: '<div></div>'
55 * ^^^^^^^^^^^^^^^^^^^^^^^---- property assignment
56 * })
57 * class AppComponent {}
58 * ^---- class declaration node
59 *
60 * @param propAsgn property assignment
61 */
62 function getClassDeclFromDecoratorProp(propAsgnNode) {
63 if (!propAsgnNode.parent || !ts.isObjectLiteralExpression(propAsgnNode.parent)) {
64 return;
65 }
66 var objLitExprNode = propAsgnNode.parent;
67 if (!objLitExprNode.parent || !ts.isCallExpression(objLitExprNode.parent)) {
68 return;
69 }
70 var callExprNode = objLitExprNode.parent;
71 if (!callExprNode.parent || !ts.isDecorator(callExprNode.parent)) {
72 return;
73 }
74 var decorator = callExprNode.parent;
75 if (!decorator.parent || !ts.isClassDeclaration(decorator.parent)) {
76 return;
77 }
78 var classDeclNode = decorator.parent;
79 return classDeclNode;
80 }
81 exports.getClassDeclFromDecoratorProp = getClassDeclFromDecoratorProp;
82 /**
83 * Return metadata about `node` if it looks like an Angular directive class.
84 * In this case, potential matches are `@NgModule`, `@Component`, `@Directive`,
85 * `@Pipe`, etc.
86 * These class declarations all share some common attributes, namely their
87 * decorator takes exactly one parameter and the parameter must be an object
88 * literal.
89 *
90 * For example,
91 * v---------- `decoratorId`
92 * @NgModule({ <
93 * declarations: [], < classDecln-al
94 * }) <
95 * class AppModule {} <
96 * ^----- `classId`
97 *
98 * @param node Potential node that represents an Angular directive.
99 */
100 function getDirectiveClassLike(node) {
101 var e_1, _a;
102 if (!ts.isClassDeclaration(node) || !node.name || !node.decorators) {
103 return;
104 }
105 try {
106 for (var _b = tslib_1.__values(node.decorators), _c = _b.next(); !_c.done; _c = _b.next()) {
107 var d = _c.value;
108 var expr = d.expression;
109 if (!ts.isCallExpression(expr) || expr.arguments.length !== 1 ||
110 !ts.isIdentifier(expr.expression)) {
111 continue;
112 }
113 var arg = expr.arguments[0];
114 if (ts.isObjectLiteralExpression(arg)) {
115 return {
116 decoratorId: expr.expression,
117 classId: node.name,
118 };
119 }
120 }
121 }
122 catch (e_1_1) { e_1 = { error: e_1_1 }; }
123 finally {
124 try {
125 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
126 }
127 finally { if (e_1) throw e_1.error; }
128 }
129 }
130 exports.getDirectiveClassLike = getDirectiveClassLike;
131 /**
132 * Finds the value of a property assignment that is nested in a TypeScript node and is of a certain
133 * type T.
134 *
135 * @param startNode node to start searching for nested property assignment from
136 * @param propName property assignment name
137 * @param predicate function to verify that a node is of type T.
138 * @return node property assignment value of type T, or undefined if none is found
139 */
140 function findPropertyValueOfType(startNode, propName, predicate) {
141 if (ts.isPropertyAssignment(startNode) && startNode.name.getText() === propName) {
142 var initializer = startNode.initializer;
143 if (predicate(initializer))
144 return initializer;
145 }
146 return startNode.forEachChild(function (c) { return findPropertyValueOfType(c, propName, predicate); });
147 }
148 exports.findPropertyValueOfType = findPropertyValueOfType;
149});
150//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHNfdXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9sYW5ndWFnZS1zZXJ2aWNlL3NyYy90c191dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7Ozs7O0lBRUgsbURBQXFEO0lBRXJEOzs7O09BSUc7SUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxJQUFhLEVBQUUsUUFBZ0I7UUFDOUQsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksUUFBUSxJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDM0QsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQUEsQ0FBQyxJQUFJLE9BQUEsZ0JBQWdCLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxFQUE3QixDQUE2QixDQUFDLElBQUksSUFBSSxDQUFDO1NBQ3RFO0lBQ0gsQ0FBQztJQUpELDRDQUlDO0lBRUQ7OztPQUdHO0lBQ0gsU0FBZ0IsOEJBQThCLENBQUMsS0FBYyxFQUFFLEdBQVc7UUFFeEUsSUFBTSxjQUFjLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUNwQyxJQUFJLENBQUMsY0FBYyxJQUFJLENBQUMsRUFBRSxDQUFDLG9CQUFvQixDQUFDLGNBQWMsQ0FBQztZQUMzRCxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLEdBQUcsRUFBRTtZQUN6QyxPQUFPO1NBQ1I7UUFDRCxPQUFPLGNBQWMsQ0FBQztJQUN4QixDQUFDO0lBUkQsd0VBUUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7O09BZUc7SUFDSCxTQUFnQiw2QkFBNkIsQ0FBQyxZQUFtQztRQUUvRSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyx5QkFBeUIsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDOUUsT0FBTztTQUNSO1FBQ0QsSUFBTSxjQUFjLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQztRQUMzQyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDekUsT0FBTztTQUNSO1FBQ0QsSUFBTSxZQUFZLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQztRQUMzQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ2hFLE9BQU87U0FDUjtRQUNELElBQU0sU0FBUyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUM7UUFDdEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ2pFLE9BQU87U0FDUjtRQUNELElBQU0sYUFBYSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7UUFDdkMsT0FBTyxhQUFhLENBQUM7SUFDdkIsQ0FBQztJQW5CRCxzRUFtQkM7SUFPRDs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FpQkc7SUFDSCxTQUFnQixxQkFBcUIsQ0FBQyxJQUFhOztRQUNqRCxJQUFJLENBQUMsRUFBRSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbEUsT0FBTztTQUNSOztZQUNELEtBQWdCLElBQUEsS0FBQSxpQkFBQSxJQUFJLENBQUMsVUFBVSxDQUFBLGdCQUFBLDRCQUFFO2dCQUE1QixJQUFNLENBQUMsV0FBQTtnQkFDVixJQUFNLElBQUksR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDO2dCQUMxQixJQUFJLENBQUMsRUFBRSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUM7b0JBQ3pELENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUU7b0JBQ3JDLFNBQVM7aUJBQ1Y7Z0JBQ0QsSUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDOUIsSUFBSSxFQUFFLENBQUMseUJBQXlCLENBQUMsR0FBRyxDQUFDLEVBQUU7b0JBQ3JDLE9BQU87d0JBQ0wsV0FBVyxFQUFFLElBQUksQ0FBQyxVQUFVO3dCQUM1QixPQUFPLEVBQUUsSUFBSSxDQUFDLElBQUk7cUJBQ25CLENBQUM7aUJBQ0g7YUFDRjs7Ozs7Ozs7O0lBQ0gsQ0FBQztJQWxCRCxzREFrQkM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNILFNBQWdCLHVCQUF1QixDQUNuQyxTQUFrQixFQUFFLFFBQWdCLEVBQUUsU0FBdUM7UUFDL0UsSUFBSSxFQUFFLENBQUMsb0JBQW9CLENBQUMsU0FBUyxDQUFDLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxRQUFRLEVBQUU7WUFDeEUsSUFBQSxXQUFXLEdBQUksU0FBUyxZQUFiLENBQWM7WUFDaEMsSUFBSSxTQUFTLENBQUMsV0FBVyxDQUFDO2dCQUFFLE9BQU8sV0FBVyxDQUFDO1NBQ2hEO1FBQ0QsT0FBTyxTQUFTLENBQUMsWUFBWSxDQUFDLFVBQUEsQ0FBQyxJQUFJLE9BQUEsdUJBQXVCLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQUMsRUFBL0MsQ0FBK0MsQ0FBQyxDQUFDO0lBQ3RGLENBQUM7SUFQRCwwREFPQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQgKiBhcyB0cyBmcm9tICd0eXBlc2NyaXB0L2xpYi90c3NlcnZlcmxpYnJhcnknO1xuXG4vKipcbiAqIFJldHVybiB0aGUgbm9kZSB0aGF0IG1vc3QgdGlnaHRseSBlbmNvbXBhc3MgdGhlIHNwZWNpZmllZCBgcG9zaXRpb25gLlxuICogQHBhcmFtIG5vZGVcbiAqIEBwYXJhbSBwb3NpdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZFRpZ2h0ZXN0Tm9kZShub2RlOiB0cy5Ob2RlLCBwb3NpdGlvbjogbnVtYmVyKTogdHMuTm9kZXx1bmRlZmluZWQge1xuICBpZiAobm9kZS5nZXRTdGFydCgpIDw9IHBvc2l0aW9uICYmIHBvc2l0aW9uIDwgbm9kZS5nZXRFbmQoKSkge1xuICAgIHJldHVybiBub2RlLmZvckVhY2hDaGlsZChjID0+IGZpbmRUaWdodGVzdE5vZGUoYywgcG9zaXRpb24pKSB8fCBub2RlO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBhIHByb3BlcnR5IGFzc2lnbm1lbnQgZnJvbSB0aGUgYXNzaWdubWVudCB2YWx1ZSBpZiB0aGUgcHJvcGVydHkgbmFtZVxuICogbWF0Y2hlcyB0aGUgc3BlY2lmaWVkIGBrZXlgLCBvciBgdW5kZWZpbmVkYCBpZiB0aGVyZSBpcyBubyBtYXRjaC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFByb3BlcnR5QXNzaWdubWVudEZyb21WYWx1ZSh2YWx1ZTogdHMuTm9kZSwga2V5OiBzdHJpbmcpOiB0cy5Qcm9wZXJ0eUFzc2lnbm1lbnR8XG4gICAgdW5kZWZpbmVkIHtcbiAgY29uc3QgcHJvcEFzc2lnbm1lbnQgPSB2YWx1ZS5wYXJlbnQ7XG4gIGlmICghcHJvcEFzc2lnbm1lbnQgfHwgIXRzLmlzUHJvcGVydHlBc3NpZ25tZW50KHByb3BBc3NpZ25tZW50KSB8fFxuICAgICAgcHJvcEFzc2lnbm1lbnQubmFtZS5nZXRUZXh0KCkgIT09IGtleSkge1xuICAgIHJldHVybjtcbiAgfVxuICByZXR1cm4gcHJvcEFzc2lnbm1lbnQ7XG59XG5cbi8qKlxuICogR2l2ZW4gYSBkZWNvcmF0b3IgcHJvcGVydHkgYXNzaWdubWVudCwgcmV0dXJuIHRoZSBDbGFzc0RlY2xhcmF0aW9uIG5vZGUgdGhhdCBjb3JyZXNwb25kcyB0byB0aGVcbiAqIGRpcmVjdGl2ZSBjbGFzcyB0aGUgcHJvcGVydHkgYXBwbGllcyB0by5cbiAqIElmIHRoZSBwcm9wZXJ0eSBhc3NpZ25tZW50IGlzIG5vdCBvbiBhIGNsYXNzIGRlY29yYXRvciwgbm8gZGVjbGFyYXRpb24gaXMgcmV0dXJuZWQuXG4gKlxuICogRm9yIGV4YW1wbGUsXG4gKlxuICogQENvbXBvbmVudCh7XG4gKiAgIHRlbXBsYXRlOiAnPGRpdj48L2Rpdj4nXG4gKiAgIF5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eLS0tLSBwcm9wZXJ0eSBhc3NpZ25tZW50XG4gKiB9KVxuICogY2xhc3MgQXBwQ29tcG9uZW50IHt9XG4gKiAgICAgICAgICAgXi0tLS0gY2xhc3MgZGVjbGFyYXRpb24gbm9kZVxuICpcbiAqIEBwYXJhbSBwcm9wQXNnbiBwcm9wZXJ0eSBhc3NpZ25tZW50XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDbGFzc0RlY2xGcm9tRGVjb3JhdG9yUHJvcChwcm9wQXNnbk5vZGU6IHRzLlByb3BlcnR5QXNzaWdubWVudCk6XG4gICAgdHMuQ2xhc3NEZWNsYXJhdGlvbnx1bmRlZmluZWQge1xuICBpZiAoIXByb3BBc2duTm9kZS5wYXJlbnQgfHwgIXRzLmlzT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24ocHJvcEFzZ25Ob2RlLnBhcmVudCkpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3Qgb2JqTGl0RXhwck5vZGUgPSBwcm9wQXNnbk5vZGUucGFyZW50O1xuICBpZiAoIW9iakxpdEV4cHJOb2RlLnBhcmVudCB8fCAhdHMuaXNDYWxsRXhwcmVzc2lvbihvYmpMaXRFeHByTm9kZS5wYXJlbnQpKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IGNhbGxFeHByTm9kZSA9IG9iakxpdEV4cHJOb2RlLnBhcmVudDtcbiAgaWYgKCFjYWxsRXhwck5vZGUucGFyZW50IHx8ICF0cy5pc0RlY29yYXRvcihjYWxsRXhwck5vZGUucGFyZW50KSkge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBkZWNvcmF0b3IgPSBjYWxsRXhwck5vZGUucGFyZW50O1xuICBpZiAoIWRlY29yYXRvci5wYXJlbnQgfHwgIXRzLmlzQ2xhc3NEZWNsYXJhdGlvbihkZWNvcmF0b3IucGFyZW50KSkge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBjbGFzc0RlY2xOb2RlID0gZGVjb3JhdG9yLnBhcmVudDtcbiAgcmV0dXJuIGNsYXNzRGVjbE5vZGU7XG59XG5cbmludGVyZmFjZSBEaXJlY3RpdmVDbGFzc0xpa2Uge1xuICBkZWNvcmF0b3JJZDogdHMuSWRlbnRpZmllcjsgIC8vIGRlY29yYXRvciBpZGVudGlmaWVyLCBsaWtlIEBDb21wb25lbnRcbiAgY2xhc3NJZDogdHMuSWRlbnRpZmllcjtcbn1cblxuLyoqXG4gKiBSZXR1cm4gbWV0YWRhdGEgYWJvdXQgYG5vZGVgIGlmIGl0IGxvb2tzIGxpa2UgYW4gQW5ndWxhciBkaXJlY3RpdmUgY2xhc3MuXG4gKiBJbiB0aGlzIGNhc2UsIHBvdGVudGlhbCBtYXRjaGVzIGFyZSBgQE5nTW9kdWxlYCwgYEBDb21wb25lbnRgLCBgQERpcmVjdGl2ZWAsXG4gKiBgQFBpcGVgLCBldGMuXG4gKiBUaGVzZSBjbGFzcyBkZWNsYXJhdGlvbnMgYWxsIHNoYXJlIHNvbWUgY29tbW9uIGF0dHJpYnV0ZXMsIG5hbWVseSB0aGVpclxuICogZGVjb3JhdG9yIHRha2VzIGV4YWN0bHkgb25lIHBhcmFtZXRlciBhbmQgdGhlIHBhcmFtZXRlciBtdXN0IGJlIGFuIG9iamVjdFxuICogbGl0ZXJhbC5cbiAqXG4gKiBGb3IgZXhhbXBsZSxcbiAqICAgICB2LS0tLS0tLS0tLSBgZGVjb3JhdG9ySWRgXG4gKiBATmdNb2R1bGUoeyAgICAgICAgICAgPFxuICogICBkZWNsYXJhdGlvbnM6IFtdLCAgIDwgY2xhc3NEZWNsbi1hbFxuICogfSkgICAgICAgICAgICAgICAgICAgIDxcbiAqIGNsYXNzIEFwcE1vZHVsZSB7fSAgICA8XG4gKiAgICAgICAgICBeLS0tLS0gYGNsYXNzSWRgXG4gKlxuICogQHBhcmFtIG5vZGUgUG90ZW50aWFsIG5vZGUgdGhhdCByZXByZXNlbnRzIGFuIEFuZ3VsYXIgZGlyZWN0aXZlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGlyZWN0aXZlQ2xhc3NMaWtlKG5vZGU6IHRzLk5vZGUpOiBEaXJlY3RpdmVDbGFzc0xpa2V8dW5kZWZpbmVkIHtcbiAgaWYgKCF0cy5pc0NsYXNzRGVjbGFyYXRpb24obm9kZSkgfHwgIW5vZGUubmFtZSB8fCAhbm9kZS5kZWNvcmF0b3JzKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGZvciAoY29uc3QgZCBvZiBub2RlLmRlY29yYXRvcnMpIHtcbiAgICBjb25zdCBleHByID0gZC5leHByZXNzaW9uO1xuICAgIGlmICghdHMuaXNDYWxsRXhwcmVzc2lvbihleHByKSB8fCBleHByLmFyZ3VtZW50cy5sZW5ndGggIT09IDEgfHxcbiAgICAgICAgIXRzLmlzSWRlbnRpZmllcihleHByLmV4cHJlc3Npb24pKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgYXJnID0gZXhwci5hcmd1bWVudHNbMF07XG4gICAgaWYgKHRzLmlzT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24oYXJnKSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZGVjb3JhdG9ySWQ6IGV4cHIuZXhwcmVzc2lvbixcbiAgICAgICAgY2xhc3NJZDogbm9kZS5uYW1lLFxuICAgICAgfTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBGaW5kcyB0aGUgdmFsdWUgb2YgYSBwcm9wZXJ0eSBhc3NpZ25tZW50IHRoYXQgaXMgbmVzdGVkIGluIGEgVHlwZVNjcmlwdCBub2RlIGFuZCBpcyBvZiBhIGNlcnRhaW5cbiAqIHR5cGUgVC5cbiAqXG4gKiBAcGFyYW0gc3RhcnROb2RlIG5vZGUgdG8gc3RhcnQgc2VhcmNoaW5nIGZvciBuZXN0ZWQgcHJvcGVydHkgYXNzaWdubWVudCBmcm9tXG4gKiBAcGFyYW0gcHJvcE5hbWUgcHJvcGVydHkgYXNzaWdubWVudCBuYW1lXG4gKiBAcGFyYW0gcHJlZGljYXRlIGZ1bmN0aW9uIHRvIHZlcmlmeSB0aGF0IGEgbm9kZSBpcyBvZiB0eXBlIFQuXG4gKiBAcmV0dXJuIG5vZGUgcHJvcGVydHkgYXNzaWdubWVudCB2YWx1ZSBvZiB0eXBlIFQsIG9yIHVuZGVmaW5lZCBpZiBub25lIGlzIGZvdW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kUHJvcGVydHlWYWx1ZU9mVHlwZTxUIGV4dGVuZHMgdHMuTm9kZT4oXG4gICAgc3RhcnROb2RlOiB0cy5Ob2RlLCBwcm9wTmFtZTogc3RyaW5nLCBwcmVkaWNhdGU6IChub2RlOiB0cy5Ob2RlKSA9PiBub2RlIGlzIFQpOiBUfHVuZGVmaW5lZCB7XG4gIGlmICh0cy5pc1Byb3BlcnR5QXNzaWdubWVudChzdGFydE5vZGUpICYmIHN0YXJ0Tm9kZS5uYW1lLmdldFRleHQoKSA9PT0gcHJvcE5hbWUpIHtcbiAgICBjb25zdCB7aW5pdGlhbGl6ZXJ9ID0gc3RhcnROb2RlO1xuICAgIGlmIChwcmVkaWNhdGUoaW5pdGlhbGl6ZXIpKSByZXR1cm4gaW5pdGlhbGl6ZXI7XG4gIH1cbiAgcmV0dXJuIHN0YXJ0Tm9kZS5mb3JFYWNoQ2hpbGQoYyA9PiBmaW5kUHJvcGVydHlWYWx1ZU9mVHlwZShjLCBwcm9wTmFtZSwgcHJlZGljYXRlKSk7XG59XG4iXX0=
\No newline at end of file