1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | Object.defineProperty(exports, "__esModule", { value: true });
|
16 | const jsdocLib = require("../javascript/jsdoc");
|
17 | const model_1 = require("../model/model");
|
18 | const immutable_1 = require("./immutable");
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | class ScannedClass {
|
32 | constructor(className, localClassName, astNode, statementAst, jsdoc, description, sourceRange, properties, methods, constructorMethod, staticMethods, superClass, mixins, privacy, warnings, abstract, demos) {
|
33 | this.name = className;
|
34 | this.localName = localClassName;
|
35 | this.astNode = astNode;
|
36 | this.statementAst = statementAst;
|
37 | this.jsdoc = jsdoc;
|
38 | this.description = description;
|
39 | this.sourceRange = sourceRange;
|
40 | this.properties = properties;
|
41 | this.methods = methods;
|
42 | this.constructorMethod = constructorMethod;
|
43 | this.staticMethods = staticMethods;
|
44 | this.superClass = superClass;
|
45 | this.mixins = mixins;
|
46 | this.privacy = privacy;
|
47 | this.warnings = warnings;
|
48 | this.abstract = abstract;
|
49 | const summaryTag = jsdocLib.getTag(jsdoc, 'summary');
|
50 | this.summary = (summaryTag && summaryTag.description) || '';
|
51 | this.demos = demos;
|
52 | }
|
53 | resolve(document) {
|
54 | return new Class(this, document);
|
55 | }
|
56 | |
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 | finishInitialization(methods, properties) {
|
63 | const mutableMethods = immutable_1.unsafeAsMutable(this.methods);
|
64 | for (const [name, method] of methods) {
|
65 | mutableMethods.set(name, method);
|
66 | }
|
67 | for (const [name, prop] of properties) {
|
68 | this.properties.set(name, prop);
|
69 | }
|
70 | }
|
71 | }
|
72 | exports.ScannedClass = ScannedClass;
|
73 | class Class {
|
74 | constructor(init, document) {
|
75 | this.kinds = new Set(['class']);
|
76 | this.identifiers = new Set();
|
77 | this.properties = new Map();
|
78 | this.methods = new Map();
|
79 | this.staticMethods = new Map();
|
80 | |
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | this.mixins = [];
|
89 | ({
|
90 | jsdoc: this.jsdoc,
|
91 | description: this.description,
|
92 | summary: this.summary,
|
93 | abstract: this.abstract,
|
94 | privacy: this.privacy,
|
95 | astNode: this.astNode,
|
96 | statementAst: this.statementAst,
|
97 | sourceRange: this.sourceRange
|
98 | } = init);
|
99 | this._parsedDocument = document.parsedDocument;
|
100 | this.warnings =
|
101 | init.warnings === undefined ? [] : Array.from(init.warnings);
|
102 | this.demos = [...init.demos || [], ...jsdocLib.extractDemos(init.jsdoc)];
|
103 | this.name = init.name || init.className;
|
104 | if (this.name) {
|
105 | this.identifiers.add(this.name);
|
106 | }
|
107 | if (init.superClass) {
|
108 | this.superClass = init.superClass;
|
109 | }
|
110 | this.mixins = (init.mixins || []);
|
111 | this.constructorMethod = init.constructorMethod;
|
112 | const superClassLikes = this._getSuperclassAndMixins(document, init);
|
113 | for (const superClassLike of superClassLikes) {
|
114 | this.inheritFrom(superClassLike);
|
115 | }
|
116 | if (init.properties !== undefined) {
|
117 | this._overwriteInherited(this.properties, init.properties, undefined, true);
|
118 | }
|
119 | if (init.methods !== undefined) {
|
120 | this._overwriteInherited(this.methods, init.methods, undefined, true);
|
121 | }
|
122 | if (init.constructorMethod !== undefined) {
|
123 | this.constructorMethod = this._overwriteSingleInherited(this.constructorMethod, init.constructorMethod, undefined);
|
124 | }
|
125 | if (init.staticMethods !== undefined) {
|
126 | this._overwriteInherited(this.staticMethods, init.staticMethods, undefined, true);
|
127 | }
|
128 | }
|
129 | |
130 |
|
131 |
|
132 | get className() {
|
133 | return this.name;
|
134 | }
|
135 | inheritFrom(superClass) {
|
136 | this._overwriteInherited(this.staticMethods, superClass.staticMethods, superClass.name);
|
137 | this._overwriteInherited(this.properties, superClass.properties, superClass.name);
|
138 | this._overwriteInherited(this.methods, superClass.methods, superClass.name);
|
139 | this.constructorMethod = this._overwriteSingleInherited(this.constructorMethod, superClass.constructorMethod, superClass.name);
|
140 | }
|
141 | |
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 | _overwriteInherited(existing, overriding, overridingClassName, applyingSelf = false) {
|
157 | for (const [key, overridingVal] of overriding) {
|
158 | const newVal = Object.assign({}, overridingVal, {
|
159 | inheritedFrom: overridingVal['inheritedFrom'] || overridingClassName
|
160 | });
|
161 | if (existing.has(key)) {
|
162 | |
163 |
|
164 |
|
165 |
|
166 |
|
167 | const existingValue = existing.get(key);
|
168 | if (existingValue.privacy === 'private') {
|
169 | let warningSourceRange = this.sourceRange;
|
170 | if (applyingSelf) {
|
171 | warningSourceRange = newVal.sourceRange || this.sourceRange;
|
172 | }
|
173 | this.warnings.push(new model_1.Warning({
|
174 | code: 'overriding-private',
|
175 | message: `Overriding private member '${overridingVal.name}' ` +
|
176 | `inherited from ${existingValue.inheritedFrom || 'parent'}`,
|
177 | sourceRange: warningSourceRange,
|
178 | severity: model_1.Severity.WARNING,
|
179 | parsedDocument: this._parsedDocument,
|
180 | }));
|
181 | }
|
182 | }
|
183 | existing.set(key, newVal);
|
184 | }
|
185 | }
|
186 | |
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | _overwriteSingleInherited(existing, overridingVal, overridingClassName) {
|
201 | if (!overridingVal) {
|
202 | return existing;
|
203 | }
|
204 | return Object.assign({}, overridingVal, {
|
205 | inheritedFrom: overridingVal['inheritedFrom'] || overridingClassName
|
206 | });
|
207 | }
|
208 | |
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 | _getSuperclassAndMixins(document, _init) {
|
215 | const mixins = this.mixins.map((m) => this._resolveReferenceToSuperClass(m, document));
|
216 | const superClass = this._resolveReferenceToSuperClass(this.superClass, document);
|
217 | const prototypeChain = [];
|
218 | if (superClass) {
|
219 | prototypeChain.push(superClass);
|
220 | }
|
221 | for (const mixin of mixins) {
|
222 | if (mixin) {
|
223 | prototypeChain.push(mixin);
|
224 | }
|
225 | }
|
226 | return prototypeChain;
|
227 | }
|
228 | _resolveReferenceToSuperClass(scannedReference, document) {
|
229 | if (!scannedReference || scannedReference.identifier === 'HTMLElement') {
|
230 | return undefined;
|
231 | }
|
232 | const reference = scannedReference.resolve(document);
|
233 | if (reference.warnings.length > 0) {
|
234 | this.warnings.push(...reference.warnings);
|
235 | }
|
236 | return reference.feature;
|
237 | }
|
238 | emitMetadata() {
|
239 | return {};
|
240 | }
|
241 | emitPropertyMetadata(_property) {
|
242 | return {};
|
243 | }
|
244 | emitMethodMetadata(_method) {
|
245 | return {};
|
246 | }
|
247 | }
|
248 | exports.Class = Class;
|
249 |
|
\ | No newline at end of file |