1 | "use strict";
|
2 |
|
3 |
|
4 | var __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 | }));
|
15 | var __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 | });
|
20 | var __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 | };
|
27 | Object.defineProperty(exports, "__esModule", { value: true });
|
28 | exports.ApiReportGenerator = void 0;
|
29 | const ts = __importStar(require("typescript"));
|
30 | const node_core_library_1 = require("@rushstack/node-core-library");
|
31 | const api_extractor_model_1 = require("@microsoft/api-extractor-model");
|
32 | const Collector_1 = require("../collector/Collector");
|
33 | const TypeScriptHelpers_1 = require("../analyzer/TypeScriptHelpers");
|
34 | const Span_1 = require("../analyzer/Span");
|
35 | const AstDeclaration_1 = require("../analyzer/AstDeclaration");
|
36 | const AstImport_1 = require("../analyzer/AstImport");
|
37 | const AstSymbol_1 = require("../analyzer/AstSymbol");
|
38 | const IndentedWriter_1 = require("./IndentedWriter");
|
39 | const DtsEmitHelpers_1 = require("./DtsEmitHelpers");
|
40 | const AstNamespaceImport_1 = require("../analyzer/AstNamespaceImport");
|
41 | const SourceFileLocationFormatter_1 = require("../analyzer/SourceFileLocationFormatter");
|
42 | class ApiReportGenerator {
|
43 | |
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 | static areEquivalentApiFileContents(actualFileContent, expectedFileContent) {
|
51 |
|
52 | const normalizedActual = actualFileContent.replace(/[\s]+/g, ' ');
|
53 | const normalizedExpected = expectedFileContent.replace(/[\s]+/g, ' ');
|
54 | return normalizedActual === normalizedExpected;
|
55 | }
|
56 | static generateReviewFileContent(collector) {
|
57 | const writer = new IndentedWriter_1.IndentedWriter();
|
58 | writer.trimLeadingSpaces = true;
|
59 | writer.writeLine([
|
60 | `## API Report File for "${collector.workingPackage.name}"`,
|
61 | ``,
|
62 | `> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).`,
|
63 | ``
|
64 | ].join('\n'));
|
65 |
|
66 | writer.writeLine('```ts\n');
|
67 |
|
68 | for (const typeDirectiveReference of Array.from(collector.dtsTypeReferenceDirectives).sort()) {
|
69 |
|
70 | writer.writeLine(`/// <reference types="${typeDirectiveReference}" />`);
|
71 | }
|
72 | for (const libDirectiveReference of Array.from(collector.dtsLibReferenceDirectives).sort()) {
|
73 | writer.writeLine(`/// <reference lib="${libDirectiveReference}" />`);
|
74 | }
|
75 | writer.ensureSkippedLine();
|
76 |
|
77 | for (const entity of collector.entities) {
|
78 | if (entity.astEntity instanceof AstImport_1.AstImport) {
|
79 | DtsEmitHelpers_1.DtsEmitHelpers.emitImport(writer, entity, entity.astEntity);
|
80 | }
|
81 | }
|
82 | writer.ensureSkippedLine();
|
83 |
|
84 | for (const entity of collector.entities) {
|
85 | const astEntity = entity.astEntity;
|
86 | if (entity.consumable || collector.extractorConfig.apiReportIncludeForgottenExports) {
|
87 | const exportsToEmit = new Map();
|
88 | for (const exportName of entity.exportNames) {
|
89 | if (!entity.shouldInlineExport) {
|
90 | exportsToEmit.set(exportName, { exportName, associatedMessages: [] });
|
91 | }
|
92 | }
|
93 | if (astEntity instanceof AstSymbol_1.AstSymbol) {
|
94 |
|
95 | for (const astDeclaration of astEntity.astDeclarations || []) {
|
96 |
|
97 | const fetchedMessages = collector.messageRouter.fetchAssociatedMessagesForReviewFile(astDeclaration);
|
98 |
|
99 |
|
100 |
|
101 | const messagesToReport = [];
|
102 | for (const message of fetchedMessages) {
|
103 | if (message.properties.exportName) {
|
104 | const exportToEmit = exportsToEmit.get(message.properties.exportName);
|
105 | if (exportToEmit) {
|
106 | exportToEmit.associatedMessages.push(message);
|
107 | continue;
|
108 | }
|
109 | }
|
110 | messagesToReport.push(message);
|
111 | }
|
112 | writer.ensureSkippedLine();
|
113 | writer.write(ApiReportGenerator._getAedocSynopsis(collector, astDeclaration, messagesToReport));
|
114 | const span = new Span_1.Span(astDeclaration.declaration);
|
115 | const apiItemMetadata = collector.fetchApiItemMetadata(astDeclaration);
|
116 | if (apiItemMetadata.isPreapproved) {
|
117 | ApiReportGenerator._modifySpanForPreapproved(span);
|
118 | }
|
119 | else {
|
120 | ApiReportGenerator._modifySpan(collector, span, entity, astDeclaration, false);
|
121 | }
|
122 | span.writeModifiedText(writer);
|
123 | writer.ensureNewLine();
|
124 | }
|
125 | }
|
126 | if (astEntity instanceof AstNamespaceImport_1.AstNamespaceImport) {
|
127 | const astModuleExportInfo = astEntity.fetchAstModuleExportInfo(collector);
|
128 | if (entity.nameForEmit === undefined) {
|
129 |
|
130 | throw new node_core_library_1.InternalError('referencedEntry.nameForEmit is undefined');
|
131 | }
|
132 | if (astModuleExportInfo.starExportedExternalModules.size > 0) {
|
133 |
|
134 | throw new Error(`The ${entity.nameForEmit} namespace import includes a star export, which is not supported:\n` +
|
135 | SourceFileLocationFormatter_1.SourceFileLocationFormatter.formatDeclaration(astEntity.declaration));
|
136 | }
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 | writer.ensureSkippedLine();
|
149 | writer.writeLine(`declare namespace ${entity.nameForEmit} {`);
|
150 |
|
151 | writer.increaseIndent();
|
152 | writer.writeLine('export {');
|
153 | writer.increaseIndent();
|
154 | const exportClauses = [];
|
155 | for (const [exportedName, exportedEntity] of astModuleExportInfo.exportedLocalEntities) {
|
156 | const collectorEntity = collector.tryGetCollectorEntity(exportedEntity);
|
157 | if (collectorEntity === undefined) {
|
158 |
|
159 |
|
160 | throw new node_core_library_1.InternalError(`Cannot find collector entity for ${entity.nameForEmit}.${exportedEntity.localName}`);
|
161 | }
|
162 | if (collectorEntity.nameForEmit === exportedName) {
|
163 | exportClauses.push(collectorEntity.nameForEmit);
|
164 | }
|
165 | else {
|
166 | exportClauses.push(`${collectorEntity.nameForEmit} as ${exportedName}`);
|
167 | }
|
168 | }
|
169 | writer.writeLine(exportClauses.join(',\n'));
|
170 | writer.decreaseIndent();
|
171 | writer.writeLine('}');
|
172 | writer.decreaseIndent();
|
173 | writer.writeLine('}');
|
174 | }
|
175 |
|
176 | for (const exportToEmit of exportsToEmit.values()) {
|
177 |
|
178 | if (exportToEmit.associatedMessages.length > 0) {
|
179 | writer.ensureSkippedLine();
|
180 | for (const message of exportToEmit.associatedMessages) {
|
181 | ApiReportGenerator._writeLineAsComments(writer, 'Warning: ' + message.formatMessageWithoutLocation());
|
182 | }
|
183 | }
|
184 | DtsEmitHelpers_1.DtsEmitHelpers.emitNamedExport(writer, exportToEmit.exportName, entity);
|
185 | }
|
186 | writer.ensureSkippedLine();
|
187 | }
|
188 | }
|
189 | DtsEmitHelpers_1.DtsEmitHelpers.emitStarExports(writer, collector);
|
190 |
|
191 | const unassociatedMessages = collector.messageRouter.fetchUnassociatedMessagesForReviewFile();
|
192 | if (unassociatedMessages.length > 0) {
|
193 | writer.ensureSkippedLine();
|
194 | ApiReportGenerator._writeLineAsComments(writer, 'Warnings were encountered during analysis:');
|
195 | ApiReportGenerator._writeLineAsComments(writer, '');
|
196 | for (const unassociatedMessage of unassociatedMessages) {
|
197 | ApiReportGenerator._writeLineAsComments(writer, unassociatedMessage.formatMessageWithLocation(collector.workingPackage.packageFolder));
|
198 | }
|
199 | }
|
200 | if (collector.workingPackage.tsdocComment === undefined) {
|
201 | writer.ensureSkippedLine();
|
202 | ApiReportGenerator._writeLineAsComments(writer, '(No @packageDocumentation comment for this package)');
|
203 | }
|
204 |
|
205 | writer.ensureSkippedLine();
|
206 | writer.writeLine('```');
|
207 |
|
208 | return writer.toString().replace(ApiReportGenerator._trimSpacesRegExp, '');
|
209 | }
|
210 | |
211 |
|
212 |
|
213 | static _modifySpan(collector, span, entity, astDeclaration, insideTypeLiteral) {
|
214 |
|
215 |
|
216 | if ((astDeclaration.modifierFlags & ts.ModifierFlags.Private) !== 0) {
|
217 | span.modification.skipAll();
|
218 | return;
|
219 | }
|
220 | const previousSpan = span.previousSibling;
|
221 | let recurseChildren = true;
|
222 | let sortChildren = false;
|
223 | switch (span.kind) {
|
224 | case ts.SyntaxKind.JSDocComment:
|
225 | span.modification.skipAll();
|
226 |
|
227 | recurseChildren = false;
|
228 | break;
|
229 | case ts.SyntaxKind.ExportKeyword:
|
230 | case ts.SyntaxKind.DefaultKeyword:
|
231 | case ts.SyntaxKind.DeclareKeyword:
|
232 |
|
233 | span.modification.skipAll();
|
234 | break;
|
235 | case ts.SyntaxKind.InterfaceKeyword:
|
236 | case ts.SyntaxKind.ClassKeyword:
|
237 | case ts.SyntaxKind.EnumKeyword:
|
238 | case ts.SyntaxKind.NamespaceKeyword:
|
239 | case ts.SyntaxKind.ModuleKeyword:
|
240 | case ts.SyntaxKind.TypeKeyword:
|
241 | case ts.SyntaxKind.FunctionKeyword:
|
242 |
|
243 | let replacedModifiers = '';
|
244 | if (entity.shouldInlineExport) {
|
245 | replacedModifiers = 'export ' + replacedModifiers;
|
246 | }
|
247 | if (previousSpan && previousSpan.kind === ts.SyntaxKind.SyntaxList) {
|
248 |
|
249 |
|
250 | previousSpan.modification.prefix = replacedModifiers + previousSpan.modification.prefix;
|
251 | }
|
252 | else {
|
253 |
|
254 | span.modification.prefix = replacedModifiers + span.modification.prefix;
|
255 | }
|
256 | break;
|
257 | case ts.SyntaxKind.SyntaxList:
|
258 | if (span.parent) {
|
259 | if (AstDeclaration_1.AstDeclaration.isSupportedSyntaxKind(span.parent.kind)) {
|
260 |
|
261 |
|
262 | sortChildren = true;
|
263 | }
|
264 | else if (span.parent.kind === ts.SyntaxKind.ModuleBlock) {
|
265 |
|
266 | sortChildren = true;
|
267 | }
|
268 | }
|
269 | break;
|
270 | case ts.SyntaxKind.VariableDeclaration:
|
271 | if (!span.parent) {
|
272 |
|
273 |
|
274 |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 | const list = TypeScriptHelpers_1.TypeScriptHelpers.matchAncestor(span.node, [
|
280 | ts.SyntaxKind.VariableDeclarationList,
|
281 | ts.SyntaxKind.VariableDeclaration
|
282 | ]);
|
283 | if (!list) {
|
284 |
|
285 | throw new node_core_library_1.InternalError('Unsupported variable declaration');
|
286 | }
|
287 | const listPrefix = list
|
288 | .getSourceFile()
|
289 | .text.substring(list.getStart(), list.declarations[0].getStart());
|
290 | span.modification.prefix = listPrefix + span.modification.prefix;
|
291 | span.modification.suffix = ';';
|
292 | if (entity.shouldInlineExport) {
|
293 | span.modification.prefix = 'export ' + span.modification.prefix;
|
294 | }
|
295 | }
|
296 | break;
|
297 | case ts.SyntaxKind.Identifier:
|
298 | const referencedEntity = collector.tryGetEntityForNode(span.node);
|
299 | if (referencedEntity) {
|
300 | if (!referencedEntity.nameForEmit) {
|
301 |
|
302 | throw new node_core_library_1.InternalError('referencedEntry.nameForEmit is undefined');
|
303 | }
|
304 | span.modification.prefix = referencedEntity.nameForEmit;
|
305 |
|
306 |
|
307 | }
|
308 | else {
|
309 |
|
310 |
|
311 | }
|
312 | break;
|
313 | case ts.SyntaxKind.TypeLiteral:
|
314 | insideTypeLiteral = true;
|
315 | break;
|
316 | case ts.SyntaxKind.ImportType:
|
317 | DtsEmitHelpers_1.DtsEmitHelpers.modifyImportTypeSpan(collector, span, astDeclaration, (childSpan, childAstDeclaration) => {
|
318 | ApiReportGenerator._modifySpan(collector, childSpan, entity, childAstDeclaration, insideTypeLiteral);
|
319 | });
|
320 | break;
|
321 | }
|
322 | if (recurseChildren) {
|
323 | for (const child of span.children) {
|
324 | let childAstDeclaration = astDeclaration;
|
325 | if (AstDeclaration_1.AstDeclaration.isSupportedSyntaxKind(child.kind)) {
|
326 | childAstDeclaration = collector.astSymbolTable.getChildAstDeclarationByNode(child.node, astDeclaration);
|
327 | if (sortChildren) {
|
328 | span.modification.sortChildren = true;
|
329 | child.modification.sortKey = Collector_1.Collector.getSortKeyIgnoringUnderscore(childAstDeclaration.astSymbol.localName);
|
330 | }
|
331 | if (!insideTypeLiteral) {
|
332 | const messagesToReport = collector.messageRouter.fetchAssociatedMessagesForReviewFile(childAstDeclaration);
|
333 | const aedocSynopsis = ApiReportGenerator._getAedocSynopsis(collector, childAstDeclaration, messagesToReport);
|
334 | child.modification.prefix = aedocSynopsis + child.modification.prefix;
|
335 | }
|
336 | }
|
337 | ApiReportGenerator._modifySpan(collector, child, entity, childAstDeclaration, insideTypeLiteral);
|
338 | }
|
339 | }
|
340 | }
|
341 | |
342 |
|
343 |
|
344 | static _modifySpanForPreapproved(span) {
|
345 |
|
346 |
|
347 |
|
348 |
|
349 |
|
350 |
|
351 |
|
352 |
|
353 |
|
354 |
|
355 |
|
356 |
|
357 |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 |
|
376 | let skipRest = false;
|
377 | for (const child of span.children) {
|
378 | if (skipRest || child.kind === ts.SyntaxKind.SyntaxList || child.kind === ts.SyntaxKind.JSDocComment) {
|
379 | child.modification.skipAll();
|
380 | }
|
381 | if (child.kind === ts.SyntaxKind.Identifier) {
|
382 | skipRest = true;
|
383 | child.modification.omitSeparatorAfter = true;
|
384 | child.modification.suffix = ' { /* (preapproved) */ }';
|
385 | }
|
386 | }
|
387 | }
|
388 | |
389 |
|
390 |
|
391 |
|
392 |
|
393 | static _getAedocSynopsis(collector, astDeclaration, messagesToReport) {
|
394 | const writer = new IndentedWriter_1.IndentedWriter();
|
395 | for (const message of messagesToReport) {
|
396 | ApiReportGenerator._writeLineAsComments(writer, 'Warning: ' + message.formatMessageWithoutLocation());
|
397 | }
|
398 | if (!collector.isAncillaryDeclaration(astDeclaration)) {
|
399 | const footerParts = [];
|
400 | const apiItemMetadata = collector.fetchApiItemMetadata(astDeclaration);
|
401 | if (!apiItemMetadata.releaseTagSameAsParent) {
|
402 | if (apiItemMetadata.effectiveReleaseTag !== api_extractor_model_1.ReleaseTag.None) {
|
403 | footerParts.push(api_extractor_model_1.ReleaseTag.getTagName(apiItemMetadata.effectiveReleaseTag));
|
404 | }
|
405 | }
|
406 | if (apiItemMetadata.isSealed) {
|
407 | footerParts.push('@sealed');
|
408 | }
|
409 | if (apiItemMetadata.isVirtual) {
|
410 | footerParts.push('@virtual');
|
411 | }
|
412 | if (apiItemMetadata.isOverride) {
|
413 | footerParts.push('@override');
|
414 | }
|
415 | if (apiItemMetadata.isEventProperty) {
|
416 | footerParts.push('@eventProperty');
|
417 | }
|
418 | if (apiItemMetadata.tsdocComment) {
|
419 | if (apiItemMetadata.tsdocComment.deprecatedBlock) {
|
420 | footerParts.push('@deprecated');
|
421 | }
|
422 | }
|
423 | if (apiItemMetadata.needsDocumentation) {
|
424 | footerParts.push('(undocumented)');
|
425 | }
|
426 | if (footerParts.length > 0) {
|
427 | if (messagesToReport.length > 0) {
|
428 | ApiReportGenerator._writeLineAsComments(writer, '');
|
429 | }
|
430 | ApiReportGenerator._writeLineAsComments(writer, footerParts.join(' '));
|
431 | }
|
432 | }
|
433 | return writer.toString();
|
434 | }
|
435 | static _writeLineAsComments(writer, line) {
|
436 | const lines = node_core_library_1.Text.convertToLf(line).split('\n');
|
437 | for (const realLine of lines) {
|
438 | writer.write('// ');
|
439 | writer.write(realLine);
|
440 | writer.writeLine();
|
441 | }
|
442 | }
|
443 | }
|
444 | ApiReportGenerator._trimSpacesRegExp = / +$/gm;
|
445 | exports.ApiReportGenerator = ApiReportGenerator;
|
446 |
|
\ | No newline at end of file |