UNPKG

41.2 kBJavaScriptView Raw
1"use strict";
2// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3// See LICENSE in the project root for license information.
4var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5 if (k2 === undefined) k2 = k;
6 var desc = Object.getOwnPropertyDescriptor(m, k);
7 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8 desc = { enumerable: true, get: function() { return m[k]; } };
9 }
10 Object.defineProperty(o, k2, desc);
11}) : (function(o, m, k, k2) {
12 if (k2 === undefined) k2 = k;
13 o[k2] = m[k];
14}));
15var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16 Object.defineProperty(o, "default", { enumerable: true, value: v });
17}) : function(o, v) {
18 o["default"] = v;
19});
20var __importStar = (this && this.__importStar) || function (mod) {
21 if (mod && mod.__esModule) return mod;
22 var result = {};
23 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
24 __setModuleDefault(result, mod);
25 return result;
26};
27Object.defineProperty(exports, "__esModule", { value: true });
28exports.ApiModelGenerator = void 0;
29/* eslint-disable no-bitwise */
30const ts = __importStar(require("typescript"));
31const api_extractor_model_1 = require("@microsoft/api-extractor-model");
32const ExcerptBuilder_1 = require("./ExcerptBuilder");
33const AstSymbol_1 = require("../analyzer/AstSymbol");
34const DeclarationReferenceGenerator_1 = require("./DeclarationReferenceGenerator");
35const AstNamespaceImport_1 = require("../analyzer/AstNamespaceImport");
36const TypeScriptInternals_1 = require("../analyzer/TypeScriptInternals");
37class ApiModelGenerator {
38 constructor(collector) {
39 this._collector = collector;
40 this._apiModel = new api_extractor_model_1.ApiModel();
41 this._referenceGenerator = new DeclarationReferenceGenerator_1.DeclarationReferenceGenerator(collector.packageJsonLookup, collector.workingPackage.name, collector.program, collector.typeChecker, collector.bundledPackageNames);
42 }
43 get apiModel() {
44 return this._apiModel;
45 }
46 buildApiPackage() {
47 const packageDocComment = this._collector.workingPackage.tsdocComment;
48 const apiPackage = new api_extractor_model_1.ApiPackage({
49 name: this._collector.workingPackage.name,
50 docComment: packageDocComment,
51 tsdocConfiguration: this._collector.extractorConfig.tsdocConfiguration
52 });
53 this._apiModel.addMember(apiPackage);
54 const apiEntryPoint = new api_extractor_model_1.ApiEntryPoint({ name: '' });
55 apiPackage.addMember(apiEntryPoint);
56 // Create a CollectorEntity for each top-level export
57 for (const entity of this._collector.entities) {
58 if (entity.exported) {
59 this._processAstEntity(entity.astEntity, entity.nameForEmit, apiEntryPoint);
60 }
61 }
62 return apiPackage;
63 }
64 _processAstEntity(astEntity, exportedName, parentApiItem) {
65 if (astEntity instanceof AstSymbol_1.AstSymbol) {
66 // Skip ancillary declarations; we will process them with the main declaration
67 for (const astDeclaration of this._collector.getNonAncillaryDeclarations(astEntity)) {
68 this._processDeclaration(astDeclaration, exportedName, parentApiItem);
69 }
70 return;
71 }
72 if (astEntity instanceof AstNamespaceImport_1.AstNamespaceImport) {
73 // Note that a single API item can belong to two different AstNamespaceImport namespaces. For example:
74 //
75 // // file.ts defines "thing()"
76 // import * as example1 from "./file";
77 // import * as example2 from "./file";
78 //
79 // // ...so here we end up with example1.thing() and example2.thing()
80 // export { example1, example2 }
81 //
82 // The current logic does not try to associate "thing()" with a specific parent. Instead
83 // the API documentation will show duplicated entries for example1.thing() and example2.thing()./
84 //
85 // This could be improved in the future, but it requires a stable mechanism for choosing an associated parent.
86 // For thoughts about this: https://github.com/microsoft/rushstack/issues/1308
87 this._processAstModule(astEntity.astModule, exportedName, parentApiItem);
88 return;
89 }
90 // TODO: Figure out how to represent reexported AstImport objects. Basically we need to introduce a new
91 // ApiItem subclass for "export alias", similar to a type alias, but representing declarations of the
92 // form "export { X } from 'external-package'". We can also use this to solve GitHub issue #950.
93 }
94 _processAstModule(astModule, exportedName, parentApiItem) {
95 const name = exportedName ? exportedName : astModule.moduleSymbol.name;
96 const containerKey = api_extractor_model_1.ApiNamespace.getContainerKey(name);
97 let apiNamespace = parentApiItem.tryGetMemberByKey(containerKey);
98 if (apiNamespace === undefined) {
99 apiNamespace = new api_extractor_model_1.ApiNamespace({
100 name,
101 docComment: undefined,
102 releaseTag: api_extractor_model_1.ReleaseTag.None,
103 excerptTokens: []
104 });
105 parentApiItem.addMember(apiNamespace);
106 }
107 astModule.astModuleExportInfo.exportedLocalEntities.forEach((exportedEntity, exportedName) => {
108 this._processAstEntity(exportedEntity, exportedName, apiNamespace);
109 });
110 }
111 _processDeclaration(astDeclaration, exportedName, parentApiItem) {
112 if ((astDeclaration.modifierFlags & ts.ModifierFlags.Private) !== 0) {
113 return; // trim out private declarations
114 }
115 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
116 const releaseTag = apiItemMetadata.effectiveReleaseTag;
117 if (releaseTag === api_extractor_model_1.ReleaseTag.Internal || releaseTag === api_extractor_model_1.ReleaseTag.Alpha) {
118 return; // trim out items marked as "@internal" or "@alpha"
119 }
120 switch (astDeclaration.declaration.kind) {
121 case ts.SyntaxKind.CallSignature:
122 this._processApiCallSignature(astDeclaration, exportedName, parentApiItem);
123 break;
124 case ts.SyntaxKind.Constructor:
125 this._processApiConstructor(astDeclaration, exportedName, parentApiItem);
126 break;
127 case ts.SyntaxKind.ConstructSignature:
128 this._processApiConstructSignature(astDeclaration, exportedName, parentApiItem);
129 break;
130 case ts.SyntaxKind.ClassDeclaration:
131 this._processApiClass(astDeclaration, exportedName, parentApiItem);
132 break;
133 case ts.SyntaxKind.EnumDeclaration:
134 this._processApiEnum(astDeclaration, exportedName, parentApiItem);
135 break;
136 case ts.SyntaxKind.EnumMember:
137 this._processApiEnumMember(astDeclaration, exportedName, parentApiItem);
138 break;
139 case ts.SyntaxKind.FunctionDeclaration:
140 this._processApiFunction(astDeclaration, exportedName, parentApiItem);
141 break;
142 case ts.SyntaxKind.GetAccessor:
143 this._processApiProperty(astDeclaration, exportedName, parentApiItem);
144 break;
145 case ts.SyntaxKind.SetAccessor:
146 this._processApiProperty(astDeclaration, exportedName, parentApiItem);
147 break;
148 case ts.SyntaxKind.IndexSignature:
149 this._processApiIndexSignature(astDeclaration, exportedName, parentApiItem);
150 break;
151 case ts.SyntaxKind.InterfaceDeclaration:
152 this._processApiInterface(astDeclaration, exportedName, parentApiItem);
153 break;
154 case ts.SyntaxKind.MethodDeclaration:
155 this._processApiMethod(astDeclaration, exportedName, parentApiItem);
156 break;
157 case ts.SyntaxKind.MethodSignature:
158 this._processApiMethodSignature(astDeclaration, exportedName, parentApiItem);
159 break;
160 case ts.SyntaxKind.ModuleDeclaration:
161 this._processApiNamespace(astDeclaration, exportedName, parentApiItem);
162 break;
163 case ts.SyntaxKind.PropertyDeclaration:
164 this._processApiProperty(astDeclaration, exportedName, parentApiItem);
165 break;
166 case ts.SyntaxKind.PropertySignature:
167 this._processApiPropertySignature(astDeclaration, exportedName, parentApiItem);
168 break;
169 case ts.SyntaxKind.TypeAliasDeclaration:
170 this._processApiTypeAlias(astDeclaration, exportedName, parentApiItem);
171 break;
172 case ts.SyntaxKind.VariableDeclaration:
173 this._processApiVariable(astDeclaration, exportedName, parentApiItem);
174 break;
175 default:
176 // ignore unknown types
177 }
178 }
179 _processChildDeclarations(astDeclaration, exportedName, parentApiItem) {
180 for (const childDeclaration of astDeclaration.children) {
181 this._processDeclaration(childDeclaration, undefined, parentApiItem);
182 }
183 }
184 _processApiCallSignature(astDeclaration, exportedName, parentApiItem) {
185 const overloadIndex = this._collector.getOverloadIndex(astDeclaration);
186 const containerKey = api_extractor_model_1.ApiCallSignature.getContainerKey(overloadIndex);
187 let apiCallSignature = parentApiItem.tryGetMemberByKey(containerKey);
188 if (apiCallSignature === undefined) {
189 const callSignature = astDeclaration.declaration;
190 const nodesToCapture = [];
191 const returnTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
192 nodesToCapture.push({ node: callSignature.type, tokenRange: returnTypeTokenRange });
193 const typeParameters = this._captureTypeParameters(nodesToCapture, callSignature.typeParameters);
194 const parameters = this._captureParameters(nodesToCapture, callSignature.parameters);
195 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
196 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
197 const docComment = apiItemMetadata.tsdocComment;
198 const releaseTag = apiItemMetadata.effectiveReleaseTag;
199 apiCallSignature = new api_extractor_model_1.ApiCallSignature({
200 docComment,
201 releaseTag,
202 typeParameters,
203 parameters,
204 overloadIndex,
205 excerptTokens,
206 returnTypeTokenRange
207 });
208 parentApiItem.addMember(apiCallSignature);
209 }
210 }
211 _processApiConstructor(astDeclaration, exportedName, parentApiItem) {
212 const overloadIndex = this._collector.getOverloadIndex(astDeclaration);
213 const containerKey = api_extractor_model_1.ApiConstructor.getContainerKey(overloadIndex);
214 let apiConstructor = parentApiItem.tryGetMemberByKey(containerKey);
215 if (apiConstructor === undefined) {
216 const constructorDeclaration = astDeclaration.declaration;
217 const nodesToCapture = [];
218 const parameters = this._captureParameters(nodesToCapture, constructorDeclaration.parameters);
219 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
220 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
221 const docComment = apiItemMetadata.tsdocComment;
222 const releaseTag = apiItemMetadata.effectiveReleaseTag;
223 const isProtected = (astDeclaration.modifierFlags & ts.ModifierFlags.Protected) !== 0;
224 apiConstructor = new api_extractor_model_1.ApiConstructor({
225 docComment,
226 releaseTag,
227 isProtected,
228 parameters,
229 overloadIndex,
230 excerptTokens
231 });
232 parentApiItem.addMember(apiConstructor);
233 }
234 }
235 _processApiClass(astDeclaration, exportedName, parentApiItem) {
236 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
237 const containerKey = api_extractor_model_1.ApiClass.getContainerKey(name);
238 let apiClass = parentApiItem.tryGetMemberByKey(containerKey);
239 if (apiClass === undefined) {
240 const classDeclaration = astDeclaration.declaration;
241 const nodesToCapture = [];
242 const typeParameters = this._captureTypeParameters(nodesToCapture, classDeclaration.typeParameters);
243 let extendsTokenRange = undefined;
244 const implementsTokenRanges = [];
245 for (const heritageClause of classDeclaration.heritageClauses || []) {
246 if (heritageClause.token === ts.SyntaxKind.ExtendsKeyword) {
247 extendsTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
248 if (heritageClause.types.length > 0) {
249 nodesToCapture.push({ node: heritageClause.types[0], tokenRange: extendsTokenRange });
250 }
251 }
252 else if (heritageClause.token === ts.SyntaxKind.ImplementsKeyword) {
253 for (const heritageType of heritageClause.types) {
254 const implementsTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
255 implementsTokenRanges.push(implementsTokenRange);
256 nodesToCapture.push({ node: heritageType, tokenRange: implementsTokenRange });
257 }
258 }
259 }
260 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
261 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
262 const docComment = apiItemMetadata.tsdocComment;
263 const releaseTag = apiItemMetadata.effectiveReleaseTag;
264 apiClass = new api_extractor_model_1.ApiClass({
265 name,
266 docComment,
267 releaseTag,
268 excerptTokens,
269 typeParameters,
270 extendsTokenRange,
271 implementsTokenRanges
272 });
273 parentApiItem.addMember(apiClass);
274 }
275 this._processChildDeclarations(astDeclaration, exportedName, apiClass);
276 }
277 _processApiConstructSignature(astDeclaration, exportedName, parentApiItem) {
278 const overloadIndex = this._collector.getOverloadIndex(astDeclaration);
279 const containerKey = api_extractor_model_1.ApiConstructSignature.getContainerKey(overloadIndex);
280 let apiConstructSignature = parentApiItem.tryGetMemberByKey(containerKey);
281 if (apiConstructSignature === undefined) {
282 const constructSignature = astDeclaration.declaration;
283 const nodesToCapture = [];
284 const returnTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
285 nodesToCapture.push({ node: constructSignature.type, tokenRange: returnTypeTokenRange });
286 const typeParameters = this._captureTypeParameters(nodesToCapture, constructSignature.typeParameters);
287 const parameters = this._captureParameters(nodesToCapture, constructSignature.parameters);
288 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
289 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
290 const docComment = apiItemMetadata.tsdocComment;
291 const releaseTag = apiItemMetadata.effectiveReleaseTag;
292 apiConstructSignature = new api_extractor_model_1.ApiConstructSignature({
293 docComment,
294 releaseTag,
295 typeParameters,
296 parameters,
297 overloadIndex,
298 excerptTokens,
299 returnTypeTokenRange
300 });
301 parentApiItem.addMember(apiConstructSignature);
302 }
303 }
304 _processApiEnum(astDeclaration, exportedName, parentApiItem) {
305 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
306 const containerKey = api_extractor_model_1.ApiEnum.getContainerKey(name);
307 let apiEnum = parentApiItem.tryGetMemberByKey(containerKey);
308 if (apiEnum === undefined) {
309 const excerptTokens = this._buildExcerptTokens(astDeclaration, []);
310 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
311 const docComment = apiItemMetadata.tsdocComment;
312 const releaseTag = apiItemMetadata.effectiveReleaseTag;
313 const preserveMemberOrder = this._collector.extractorConfig.enumMemberOrder === api_extractor_model_1.EnumMemberOrder.Preserve;
314 apiEnum = new api_extractor_model_1.ApiEnum({ name, docComment, releaseTag, excerptTokens, preserveMemberOrder });
315 parentApiItem.addMember(apiEnum);
316 }
317 this._processChildDeclarations(astDeclaration, exportedName, apiEnum);
318 }
319 _processApiEnumMember(astDeclaration, exportedName, parentApiItem) {
320 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
321 const containerKey = api_extractor_model_1.ApiEnumMember.getContainerKey(name);
322 let apiEnumMember = parentApiItem.tryGetMemberByKey(containerKey);
323 if (apiEnumMember === undefined) {
324 const enumMember = astDeclaration.declaration;
325 const nodesToCapture = [];
326 let initializerTokenRange = undefined;
327 if (enumMember.initializer) {
328 initializerTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
329 nodesToCapture.push({ node: enumMember.initializer, tokenRange: initializerTokenRange });
330 }
331 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
332 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
333 const docComment = apiItemMetadata.tsdocComment;
334 const releaseTag = apiItemMetadata.effectiveReleaseTag;
335 apiEnumMember = new api_extractor_model_1.ApiEnumMember({
336 name,
337 docComment,
338 releaseTag,
339 excerptTokens,
340 initializerTokenRange
341 });
342 parentApiItem.addMember(apiEnumMember);
343 }
344 }
345 _processApiFunction(astDeclaration, exportedName, parentApiItem) {
346 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
347 const overloadIndex = this._collector.getOverloadIndex(astDeclaration);
348 const containerKey = api_extractor_model_1.ApiFunction.getContainerKey(name, overloadIndex);
349 let apiFunction = parentApiItem.tryGetMemberByKey(containerKey);
350 if (apiFunction === undefined) {
351 const functionDeclaration = astDeclaration.declaration;
352 const nodesToCapture = [];
353 const returnTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
354 nodesToCapture.push({ node: functionDeclaration.type, tokenRange: returnTypeTokenRange });
355 const typeParameters = this._captureTypeParameters(nodesToCapture, functionDeclaration.typeParameters);
356 const parameters = this._captureParameters(nodesToCapture, functionDeclaration.parameters);
357 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
358 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
359 const docComment = apiItemMetadata.tsdocComment;
360 const releaseTag = apiItemMetadata.effectiveReleaseTag;
361 if (releaseTag === api_extractor_model_1.ReleaseTag.Internal || releaseTag === api_extractor_model_1.ReleaseTag.Alpha) {
362 return; // trim out items marked as "@internal" or "@alpha"
363 }
364 apiFunction = new api_extractor_model_1.ApiFunction({
365 name,
366 docComment,
367 releaseTag,
368 typeParameters,
369 parameters,
370 overloadIndex,
371 excerptTokens,
372 returnTypeTokenRange
373 });
374 parentApiItem.addMember(apiFunction);
375 }
376 }
377 _processApiIndexSignature(astDeclaration, exportedName, parentApiItem) {
378 const overloadIndex = this._collector.getOverloadIndex(astDeclaration);
379 const containerKey = api_extractor_model_1.ApiIndexSignature.getContainerKey(overloadIndex);
380 let apiIndexSignature = parentApiItem.tryGetMemberByKey(containerKey);
381 if (apiIndexSignature === undefined) {
382 const indexSignature = astDeclaration.declaration;
383 const nodesToCapture = [];
384 const returnTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
385 nodesToCapture.push({ node: indexSignature.type, tokenRange: returnTypeTokenRange });
386 const parameters = this._captureParameters(nodesToCapture, indexSignature.parameters);
387 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
388 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
389 const docComment = apiItemMetadata.tsdocComment;
390 const releaseTag = apiItemMetadata.effectiveReleaseTag;
391 const isReadonly = this._isReadonly(astDeclaration);
392 apiIndexSignature = new api_extractor_model_1.ApiIndexSignature({
393 docComment,
394 releaseTag,
395 parameters,
396 overloadIndex,
397 excerptTokens,
398 returnTypeTokenRange,
399 isReadonly
400 });
401 parentApiItem.addMember(apiIndexSignature);
402 }
403 }
404 _processApiInterface(astDeclaration, exportedName, parentApiItem) {
405 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
406 const containerKey = api_extractor_model_1.ApiInterface.getContainerKey(name);
407 let apiInterface = parentApiItem.tryGetMemberByKey(containerKey);
408 if (apiInterface === undefined) {
409 const interfaceDeclaration = astDeclaration.declaration;
410 const nodesToCapture = [];
411 const typeParameters = this._captureTypeParameters(nodesToCapture, interfaceDeclaration.typeParameters);
412 const extendsTokenRanges = [];
413 for (const heritageClause of interfaceDeclaration.heritageClauses || []) {
414 if (heritageClause.token === ts.SyntaxKind.ExtendsKeyword) {
415 for (const heritageType of heritageClause.types) {
416 const extendsTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
417 extendsTokenRanges.push(extendsTokenRange);
418 nodesToCapture.push({ node: heritageType, tokenRange: extendsTokenRange });
419 }
420 }
421 }
422 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
423 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
424 const docComment = apiItemMetadata.tsdocComment;
425 const releaseTag = apiItemMetadata.effectiveReleaseTag;
426 apiInterface = new api_extractor_model_1.ApiInterface({
427 name,
428 docComment,
429 releaseTag,
430 excerptTokens,
431 typeParameters,
432 extendsTokenRanges
433 });
434 parentApiItem.addMember(apiInterface);
435 }
436 this._processChildDeclarations(astDeclaration, exportedName, apiInterface);
437 }
438 _processApiMethod(astDeclaration, exportedName, parentApiItem) {
439 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
440 const isStatic = (astDeclaration.modifierFlags & ts.ModifierFlags.Static) !== 0;
441 const overloadIndex = this._collector.getOverloadIndex(astDeclaration);
442 const containerKey = api_extractor_model_1.ApiMethod.getContainerKey(name, isStatic, overloadIndex);
443 let apiMethod = parentApiItem.tryGetMemberByKey(containerKey);
444 if (apiMethod === undefined) {
445 const methodDeclaration = astDeclaration.declaration;
446 const nodesToCapture = [];
447 const returnTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
448 nodesToCapture.push({ node: methodDeclaration.type, tokenRange: returnTypeTokenRange });
449 const typeParameters = this._captureTypeParameters(nodesToCapture, methodDeclaration.typeParameters);
450 const parameters = this._captureParameters(nodesToCapture, methodDeclaration.parameters);
451 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
452 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
453 const docComment = apiItemMetadata.tsdocComment;
454 const releaseTag = apiItemMetadata.effectiveReleaseTag;
455 if (releaseTag === api_extractor_model_1.ReleaseTag.Internal || releaseTag === api_extractor_model_1.ReleaseTag.Alpha) {
456 return; // trim out items marked as "@internal" or "@alpha"
457 }
458 const isOptional = (astDeclaration.astSymbol.followedSymbol.flags & ts.SymbolFlags.Optional) !== 0;
459 const isProtected = (astDeclaration.modifierFlags & ts.ModifierFlags.Protected) !== 0;
460 apiMethod = new api_extractor_model_1.ApiMethod({
461 name,
462 docComment,
463 releaseTag,
464 isProtected,
465 isStatic,
466 isOptional,
467 typeParameters,
468 parameters,
469 overloadIndex,
470 excerptTokens,
471 returnTypeTokenRange
472 });
473 parentApiItem.addMember(apiMethod);
474 }
475 }
476 _processApiMethodSignature(astDeclaration, exportedName, parentApiItem) {
477 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
478 const overloadIndex = this._collector.getOverloadIndex(astDeclaration);
479 const containerKey = api_extractor_model_1.ApiMethodSignature.getContainerKey(name, overloadIndex);
480 let apiMethodSignature = parentApiItem.tryGetMemberByKey(containerKey);
481 if (apiMethodSignature === undefined) {
482 const methodSignature = astDeclaration.declaration;
483 const nodesToCapture = [];
484 const returnTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
485 nodesToCapture.push({ node: methodSignature.type, tokenRange: returnTypeTokenRange });
486 const typeParameters = this._captureTypeParameters(nodesToCapture, methodSignature.typeParameters);
487 const parameters = this._captureParameters(nodesToCapture, methodSignature.parameters);
488 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
489 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
490 const docComment = apiItemMetadata.tsdocComment;
491 const releaseTag = apiItemMetadata.effectiveReleaseTag;
492 const isOptional = (astDeclaration.astSymbol.followedSymbol.flags & ts.SymbolFlags.Optional) !== 0;
493 apiMethodSignature = new api_extractor_model_1.ApiMethodSignature({
494 name,
495 docComment,
496 releaseTag,
497 isOptional,
498 typeParameters,
499 parameters,
500 overloadIndex,
501 excerptTokens,
502 returnTypeTokenRange
503 });
504 parentApiItem.addMember(apiMethodSignature);
505 }
506 }
507 _processApiNamespace(astDeclaration, exportedName, parentApiItem) {
508 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
509 const containerKey = api_extractor_model_1.ApiNamespace.getContainerKey(name);
510 let apiNamespace = parentApiItem.tryGetMemberByKey(containerKey);
511 if (apiNamespace === undefined) {
512 const excerptTokens = this._buildExcerptTokens(astDeclaration, []);
513 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
514 const docComment = apiItemMetadata.tsdocComment;
515 const releaseTag = apiItemMetadata.effectiveReleaseTag;
516 apiNamespace = new api_extractor_model_1.ApiNamespace({ name, docComment, releaseTag, excerptTokens });
517 parentApiItem.addMember(apiNamespace);
518 }
519 this._processChildDeclarations(astDeclaration, exportedName, apiNamespace);
520 }
521 _processApiProperty(astDeclaration, exportedName, parentApiItem) {
522 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
523 const isStatic = (astDeclaration.modifierFlags & ts.ModifierFlags.Static) !== 0;
524 const containerKey = api_extractor_model_1.ApiProperty.getContainerKey(name, isStatic);
525 let apiProperty = parentApiItem.tryGetMemberByKey(containerKey);
526 if (apiProperty === undefined) {
527 const declaration = astDeclaration.declaration;
528 const nodesToCapture = [];
529 const propertyTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
530 let propertyTypeNode;
531 if (ts.isPropertyDeclaration(declaration) || ts.isGetAccessorDeclaration(declaration)) {
532 propertyTypeNode = declaration.type;
533 }
534 if (ts.isSetAccessorDeclaration(declaration)) {
535 // Note that TypeScript always reports an error if a setter does not have exactly one parameter.
536 propertyTypeNode = declaration.parameters[0].type;
537 }
538 nodesToCapture.push({ node: propertyTypeNode, tokenRange: propertyTypeTokenRange });
539 let initializerTokenRange = undefined;
540 if (ts.isPropertyDeclaration(declaration) && declaration.initializer) {
541 initializerTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
542 nodesToCapture.push({ node: declaration.initializer, tokenRange: initializerTokenRange });
543 }
544 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
545 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
546 const docComment = apiItemMetadata.tsdocComment;
547 const releaseTag = apiItemMetadata.effectiveReleaseTag;
548 const isOptional = (astDeclaration.astSymbol.followedSymbol.flags & ts.SymbolFlags.Optional) !== 0;
549 const isProtected = (astDeclaration.modifierFlags & ts.ModifierFlags.Protected) !== 0;
550 const isReadonly = this._isReadonly(astDeclaration);
551 apiProperty = new api_extractor_model_1.ApiProperty({
552 name,
553 docComment,
554 releaseTag,
555 isProtected,
556 isStatic,
557 isOptional,
558 isReadonly,
559 excerptTokens,
560 propertyTypeTokenRange,
561 initializerTokenRange
562 });
563 parentApiItem.addMember(apiProperty);
564 }
565 else {
566 // If the property was already declared before (via a merged interface declaration),
567 // we assume its signature is identical, because the language requires that.
568 }
569 }
570 _processApiPropertySignature(astDeclaration, exportedName, parentApiItem) {
571 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
572 const containerKey = api_extractor_model_1.ApiPropertySignature.getContainerKey(name);
573 let apiPropertySignature = parentApiItem.tryGetMemberByKey(containerKey);
574 if (apiPropertySignature === undefined) {
575 const propertySignature = astDeclaration.declaration;
576 const nodesToCapture = [];
577 const propertyTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
578 nodesToCapture.push({ node: propertySignature.type, tokenRange: propertyTypeTokenRange });
579 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
580 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
581 const docComment = apiItemMetadata.tsdocComment;
582 const releaseTag = apiItemMetadata.effectiveReleaseTag;
583 const isOptional = (astDeclaration.astSymbol.followedSymbol.flags & ts.SymbolFlags.Optional) !== 0;
584 const isReadonly = this._isReadonly(astDeclaration);
585 apiPropertySignature = new api_extractor_model_1.ApiPropertySignature({
586 name,
587 docComment,
588 releaseTag,
589 isOptional,
590 excerptTokens,
591 propertyTypeTokenRange,
592 isReadonly
593 });
594 parentApiItem.addMember(apiPropertySignature);
595 }
596 else {
597 // If the property was already declared before (via a merged interface declaration),
598 // we assume its signature is identical, because the language requires that.
599 }
600 }
601 _processApiTypeAlias(astDeclaration, exportedName, parentApiItem) {
602 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
603 const containerKey = api_extractor_model_1.ApiTypeAlias.getContainerKey(name);
604 let apiTypeAlias = parentApiItem.tryGetMemberByKey(containerKey);
605 if (apiTypeAlias === undefined) {
606 const typeAliasDeclaration = astDeclaration.declaration;
607 const nodesToCapture = [];
608 const typeParameters = this._captureTypeParameters(nodesToCapture, typeAliasDeclaration.typeParameters);
609 const typeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
610 nodesToCapture.push({ node: typeAliasDeclaration.type, tokenRange: typeTokenRange });
611 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
612 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
613 const docComment = apiItemMetadata.tsdocComment;
614 const releaseTag = apiItemMetadata.effectiveReleaseTag;
615 apiTypeAlias = new api_extractor_model_1.ApiTypeAlias({
616 name,
617 docComment,
618 typeParameters,
619 releaseTag,
620 excerptTokens,
621 typeTokenRange
622 });
623 parentApiItem.addMember(apiTypeAlias);
624 }
625 }
626 _processApiVariable(astDeclaration, exportedName, parentApiItem) {
627 const name = exportedName ? exportedName : astDeclaration.astSymbol.localName;
628 const containerKey = api_extractor_model_1.ApiVariable.getContainerKey(name);
629 let apiVariable = parentApiItem.tryGetMemberByKey(containerKey);
630 if (apiVariable === undefined) {
631 const variableDeclaration = astDeclaration.declaration;
632 const nodesToCapture = [];
633 const variableTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
634 nodesToCapture.push({ node: variableDeclaration.type, tokenRange: variableTypeTokenRange });
635 let initializerTokenRange = undefined;
636 if (variableDeclaration.initializer) {
637 initializerTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
638 nodesToCapture.push({ node: variableDeclaration.initializer, tokenRange: initializerTokenRange });
639 }
640 const excerptTokens = this._buildExcerptTokens(astDeclaration, nodesToCapture);
641 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
642 const docComment = apiItemMetadata.tsdocComment;
643 const releaseTag = apiItemMetadata.effectiveReleaseTag;
644 const isReadonly = this._isReadonly(astDeclaration);
645 apiVariable = new api_extractor_model_1.ApiVariable({
646 name,
647 docComment,
648 releaseTag,
649 excerptTokens,
650 variableTypeTokenRange,
651 initializerTokenRange,
652 isReadonly
653 });
654 parentApiItem.addMember(apiVariable);
655 }
656 }
657 /**
658 * @param nodesToCapture - A list of child nodes whose token ranges we want to capture
659 */
660 _buildExcerptTokens(astDeclaration, nodesToCapture) {
661 const excerptTokens = [];
662 // Build the main declaration
663 ExcerptBuilder_1.ExcerptBuilder.addDeclaration(excerptTokens, astDeclaration, nodesToCapture, this._referenceGenerator);
664 const declarationMetadata = this._collector.fetchDeclarationMetadata(astDeclaration);
665 // Add any ancillary declarations
666 for (const ancillaryDeclaration of declarationMetadata.ancillaryDeclarations) {
667 ExcerptBuilder_1.ExcerptBuilder.addBlankLine(excerptTokens);
668 ExcerptBuilder_1.ExcerptBuilder.addDeclaration(excerptTokens, ancillaryDeclaration, nodesToCapture, this._referenceGenerator);
669 }
670 return excerptTokens;
671 }
672 _captureTypeParameters(nodesToCapture, typeParameterNodes) {
673 const typeParameters = [];
674 if (typeParameterNodes) {
675 for (const typeParameter of typeParameterNodes) {
676 const constraintTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
677 nodesToCapture.push({ node: typeParameter.constraint, tokenRange: constraintTokenRange });
678 const defaultTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
679 nodesToCapture.push({ node: typeParameter.default, tokenRange: defaultTypeTokenRange });
680 typeParameters.push({
681 typeParameterName: typeParameter.name.getText().trim(),
682 constraintTokenRange,
683 defaultTypeTokenRange
684 });
685 }
686 }
687 return typeParameters;
688 }
689 _captureParameters(nodesToCapture, parameterNodes) {
690 const parameters = [];
691 for (const parameter of parameterNodes) {
692 const parameterTypeTokenRange = ExcerptBuilder_1.ExcerptBuilder.createEmptyTokenRange();
693 nodesToCapture.push({ node: parameter.type, tokenRange: parameterTypeTokenRange });
694 parameters.push({
695 parameterName: parameter.name.getText().trim(),
696 parameterTypeTokenRange,
697 isOptional: this._collector.typeChecker.isOptionalParameter(parameter)
698 });
699 }
700 return parameters;
701 }
702 _isReadonly(astDeclaration) {
703 var _a;
704 switch (astDeclaration.declaration.kind) {
705 case ts.SyntaxKind.GetAccessor:
706 case ts.SyntaxKind.IndexSignature:
707 case ts.SyntaxKind.PropertyDeclaration:
708 case ts.SyntaxKind.PropertySignature:
709 case ts.SyntaxKind.SetAccessor:
710 case ts.SyntaxKind.VariableDeclaration: {
711 const apiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
712 const docComment = apiItemMetadata.tsdocComment;
713 const declarationMetadata = this._collector.fetchDeclarationMetadata(astDeclaration);
714 const hasReadonlyModifier = (astDeclaration.modifierFlags & ts.ModifierFlags.Readonly) !== 0;
715 const hasReadonlyDocTag = !!((_a = docComment === null || docComment === void 0 ? void 0 : docComment.modifierTagSet) === null || _a === void 0 ? void 0 : _a.hasTagName('@readonly'));
716 const isGetterWithNoSetter = ts.isGetAccessorDeclaration(astDeclaration.declaration) &&
717 declarationMetadata.ancillaryDeclarations.length === 0;
718 const isVarConst = ts.isVariableDeclaration(astDeclaration.declaration) &&
719 TypeScriptInternals_1.TypeScriptInternals.isVarConst(astDeclaration.declaration);
720 return hasReadonlyModifier || hasReadonlyDocTag || isGetterWithNoSetter || isVarConst;
721 }
722 default: {
723 // Readonly-ness does not make sense for any other declaration kind.
724 return false;
725 }
726 }
727 }
728}
729exports.ApiModelGenerator = ApiModelGenerator;
730//# sourceMappingURL=ApiModelGenerator.js.map
\No newline at end of file