UNPKG

6.64 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
5 * This code may only be used under the BSD style license found at
6 * http://polymer.github.io/LICENSE.txt
7 * The complete set of authors may be found at
8 * http://polymer.github.io/AUTHORS.txt
9 * The complete set of contributors may be found at
10 * http://polymer.github.io/CONTRIBUTORS.txt
11 * Code distributed by Google as part of the polymer project is also
12 * subject to an additional IP rights grant found at
13 * http://polymer.github.io/PATENTS.txt
14 */
15var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
16 return new (P || (P = Promise))(function (resolve, reject) {
17 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
20 step((generator = generator.apply(thisArg, _arguments || [])).next());
21 });
22};
23Object.defineProperty(exports, "__esModule", { value: true });
24const babel = require("@babel/types");
25const esutil = require("../javascript/esutil");
26const esutil_1 = require("../javascript/esutil");
27const jsdoc = require("../javascript/jsdoc");
28const model_1 = require("../model/model");
29const js_utils_1 = require("./js-utils");
30const polymer_core_feature_1 = require("./polymer-core-feature");
31/**
32 * Scans for Polymer 1.x core "features".
33 *
34 * In the Polymer 1.x core library, the `Polymer.Base` prototype is dynamically
35 * augmented with properties via calls to `Polymer.Base._addFeature`. These
36 * calls are spread across multiple files and split between the micro, mini,
37 * and standard "feature layers". Polymer 2.x does not use this pattern.
38 *
39 * Example: https://github.com/Polymer/polymer/blob/1.x/src/mini/debouncer.html
40 */
41class PolymerCoreFeatureScanner {
42 scan(document, visit) {
43 return __awaiter(this, void 0, void 0, function* () {
44 const visitor = new PolymerCoreFeatureVisitor(document);
45 yield visit(visitor);
46 return { features: visitor.features };
47 });
48 }
49}
50exports.PolymerCoreFeatureScanner = PolymerCoreFeatureScanner;
51class PolymerCoreFeatureVisitor {
52 constructor(document) {
53 this.document = document;
54 this.features = [];
55 }
56 /**
57 * Scan for `Polymer.Base = {...}`.
58 */
59 enterAssignmentExpression(assignment, parent) {
60 if (!babel.isMemberExpression(assignment.left) ||
61 !esutil.matchesCallExpression(assignment.left, ['Polymer', 'Base'])) {
62 return;
63 }
64 const parsedJsdoc = jsdoc.parseJsdoc(esutil.getAttachedComment(parent) || '');
65 const feature = new polymer_core_feature_1.ScannedPolymerCoreFeature(this.document.sourceRangeForNode(assignment), { node: assignment, language: 'js', containingDocument: this.document }, parsedJsdoc.description.trim(), parsedJsdoc);
66 this.features.push(feature);
67 const rhs = assignment.right;
68 if (!babel.isObjectExpression(rhs)) {
69 feature.warnings.push(new model_1.Warning({
70 message: `Expected assignment to \`Polymer.Base\` to be an object.` +
71 `Got \`${rhs.type}\` instead.`,
72 severity: model_1.Severity.WARNING,
73 code: 'invalid-polymer-base-assignment',
74 sourceRange: this.document.sourceRangeForNode(assignment),
75 parsedDocument: this.document
76 }));
77 return;
78 }
79 this._scanObjectProperties(rhs, feature);
80 }
81 /**
82 * Scan for `addFeature({...})`.
83 */
84 enterCallExpression(call, parent) {
85 if (!babel.isMemberExpression(call.callee) ||
86 !esutil.matchesCallExpression(call.callee, ['Polymer', 'Base', '_addFeature'])) {
87 return;
88 }
89 const parsedJsdoc = jsdoc.parseJsdoc(esutil.getAttachedComment(parent) || '');
90 const feature = new polymer_core_feature_1.ScannedPolymerCoreFeature(this.document.sourceRangeForNode(call), { language: 'js', node: call, containingDocument: this.document }, parsedJsdoc.description.trim(), parsedJsdoc);
91 this.features.push(feature);
92 if (call.arguments.length !== 1) {
93 feature.warnings.push(new model_1.Warning({
94 message: `Expected only one argument to \`Polymer.Base._addFeature\`. ` +
95 `Got ${call.arguments.length}.`,
96 severity: model_1.Severity.WARNING,
97 code: 'invalid-polymer-core-feature-call',
98 sourceRange: this.document.sourceRangeForNode(call),
99 parsedDocument: this.document
100 }));
101 return;
102 }
103 const arg = call.arguments[0];
104 if (!babel.isObjectExpression(arg)) {
105 feature.warnings.push(new model_1.Warning({
106 message: `Expected argument to \`Polymer.Base._addFeature\` to be an ` +
107 `object. Got \`${arg.type}\` instead.`,
108 severity: model_1.Severity.WARNING,
109 code: 'invalid-polymer-core-feature-call',
110 sourceRange: this.document.sourceRangeForNode(call),
111 parsedDocument: this.document
112 }));
113 return;
114 }
115 this._scanObjectProperties(arg, feature);
116 }
117 /**
118 * Scan all properties of the given object expression and add them to the
119 * given feature.
120 */
121 _scanObjectProperties(obj, feature) {
122 for (const prop of esutil.getSimpleObjectProperties(obj)) {
123 const sourceRange = this.document.sourceRangeForNode(prop);
124 if (!sourceRange) {
125 continue;
126 }
127 if (babel.isMethod(prop) || babel.isFunction(prop.value)) {
128 const method = esutil_1.toScannedMethod(prop, sourceRange, this.document);
129 feature.methods.set(method.name, method);
130 }
131 else {
132 const property = js_utils_1.toScannedPolymerProperty(prop, sourceRange, this.document);
133 if (property === undefined) {
134 continue;
135 }
136 feature.properties.set(property.name, property);
137 }
138 // TODO(aomarks) Are there any getters/setters on Polymer.Base?
139 // TODO(aomarks) Merge with similar code in polymer-element-scanner.
140 }
141 }
142}
143//# sourceMappingURL=polymer-core-feature-scanner.js.map
\No newline at end of file