Skip to content

Commit 1534b3b

Browse files
committed
The dtsRollup generator now builds and works correctly
1 parent e5aa1f0 commit 1534b3b

14 files changed

Lines changed: 63 additions & 487 deletions

apps/api-extractor/src-old/utils/PrettyPrinter.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,6 @@ export class PrettyPrinter {
7878
return Text.convertToLf(rootSpan.getModifiedText());
7979
}
8080

81-
/**
82-
* Returns a string such as this, based on the context information in the provided node:
83-
* "[C:\Folder\File.ts#123]"
84-
*/
85-
public static formatFileAndLineNumber(node: ts.Node): string {
86-
const sourceFile: ts.SourceFile = node.getSourceFile();
87-
const lineAndCharacter: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(node.getStart());
88-
return `[${sourceFile.fileName}#${lineAndCharacter.line}]`;
89-
}
90-
9181
private static _getSymbolFlagString(flag: ts.SymbolFlags): string {
9282
return ts.SymbolFlags[flag];
9383
}

apps/api-extractor/src/analyzer/AstDeclaration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import * as ts from 'typescript';
55
import { AstSymbol } from './AstSymbol';
6-
import { Span } from '../../utils/Span';
6+
import { Span } from './Span';
77

88
/**
99
* Constructor parameters for AstDeclaration

apps/api-extractor/src/analyzer/AstSymbolTable.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { PackageJsonLookup } from '@microsoft/node-core-library';
88

99
import { AstDeclaration } from './AstDeclaration';
1010
import { SymbolAnalyzer, IFollowAliasesResult } from './SymbolAnalyzer';
11-
import { TypeScriptHelpers } from '../../utils/TypeScriptHelpers';
11+
import { TypeScriptHelpers } from './TypeScriptHelpers';
1212
import { AstSymbol } from './AstSymbol';
1313
import { AstImport } from './AstImport';
1414
import { AstEntryPoint, IExportedMember } from './AstEntryPoint';

apps/api-extractor/src/analyzer/ExtractorContext.ts

Lines changed: 19 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,17 @@ import {
77
PackageJsonLookup,
88
IPackageJson,
99
PackageName,
10-
IParsedPackageName,
11-
FileSystem
10+
IParsedPackageName
1211
} from '@microsoft/node-core-library';
1312

14-
import { AstPackage } from './ast/AstPackage';
15-
import { DocItemLoader } from './DocItemLoader';
16-
import { ILogger } from './extractor/ILogger';
17-
import { IExtractorPoliciesConfig, IExtractorValidationRulesConfig } from './extractor/IExtractorConfig';
18-
import { TypeScriptMessageFormatter } from './utils/TypeScriptMessageFormatter';
13+
import { ILogger } from '../api/ILogger';
14+
import { IExtractorPoliciesConfig, IExtractorValidationRulesConfig } from '../api/IExtractorConfig';
15+
import { TypeScriptMessageFormatter } from '../analyzer/TypeScriptMessageFormatter';
1916

2017
/**
2118
* Options for ExtractorContext constructor.
2219
*/
23-
export interface IExtractorContextOptions {
20+
export interface IExtractorContextParameters {
2421
/**
2522
* Configuration for the TypeScript compiler. The most important options to set are:
2623
*
@@ -52,7 +49,6 @@ export interface IExtractorContextOptions {
5249
*/
5350
export class ExtractorContext {
5451
public typeChecker: ts.TypeChecker;
55-
public package: AstPackage;
5652

5753
/**
5854
* The parsed package.json file for this package.
@@ -61,62 +57,54 @@ export class ExtractorContext {
6157

6258
public readonly parsedPackageName: IParsedPackageName;
6359

64-
/**
65-
* One DocItemLoader is needed per analyzer to look up external API members
66-
* as needed.
67-
*/
68-
public readonly docItemLoader: DocItemLoader;
69-
7060
public readonly packageJsonLookup: PackageJsonLookup;
7161

7262
public readonly policies: IExtractorPoliciesConfig;
7363

7464
public readonly validationRules: IExtractorValidationRulesConfig;
7565

66+
public readonly entryPointSourceFile: ts.SourceFile;
67+
7668
// If the entry point is "C:\Folder\project\src\index.ts" and the nearest package.json
7769
// is "C:\Folder\project\package.json", then the packageFolder is "C:\Folder\project"
7870
private _packageFolder: string;
7971

8072
private _logger: ILogger;
8173

82-
constructor(options: IExtractorContextOptions) {
74+
constructor(parameters: IExtractorContextParameters) {
8375
this.packageJsonLookup = new PackageJsonLookup();
8476

85-
this.policies = options.policies;
86-
this.validationRules = options.validationRules;
77+
this.policies = parameters.policies;
78+
this.validationRules = parameters.validationRules;
8779

88-
const folder: string | undefined = this.packageJsonLookup.tryGetPackageFolderFor(options.entryPointFile);
80+
const folder: string | undefined = this.packageJsonLookup.tryGetPackageFolderFor(parameters.entryPointFile);
8981
if (!folder) {
90-
throw new Error('Unable to find a package.json for entry point: ' + options.entryPointFile);
82+
throw new Error('Unable to find a package.json for entry point: ' + parameters.entryPointFile);
9183
}
9284
this._packageFolder = folder;
9385

9486
this.packageJson = this.packageJsonLookup.tryLoadPackageJsonFor(this._packageFolder)!;
9587

9688
this.parsedPackageName = PackageName.parse(this.packageJson.name);
9789

98-
this.docItemLoader = new DocItemLoader(this._packageFolder);
99-
100-
this._logger = options.logger;
90+
this._logger = parameters.logger;
10191

10292
// This runs a full type analysis, and then augments the Abstract Syntax Tree (i.e. declarations)
10393
// with semantic information (i.e. symbols). The "diagnostics" are a subset of the everyday
10494
// compile errors that would result from a full compilation.
105-
for (const diagnostic of options.program.getSemanticDiagnostics()) {
95+
for (const diagnostic of parameters.program.getSemanticDiagnostics()) {
10696
const errorText: string = TypeScriptMessageFormatter.format(diagnostic.messageText);
10797
this.reportError(`TypeScript: ${errorText}`, diagnostic.file, diagnostic.start);
10898
}
10999

110-
this.typeChecker = options.program.getTypeChecker();
100+
this.typeChecker = parameters.program.getTypeChecker();
111101

112-
const rootFile: ts.SourceFile | undefined = options.program.getSourceFile(options.entryPointFile);
113-
if (!rootFile) {
114-
throw new Error('Unable to load file: ' + options.entryPointFile);
102+
const entryPointSourceFile: ts.SourceFile | undefined = parameters.program.getSourceFile(parameters.entryPointFile);
103+
if (!entryPointSourceFile) {
104+
throw new Error('Unable to load file: ' + parameters.entryPointFile);
115105
}
116106

117-
this.package = new AstPackage(this, rootFile); // construct members
118-
this.package.completeInitialization(); // creates ApiDocumentation
119-
this.package.visitTypeReferencesForAstItem();
107+
this.entryPointSourceFile = entryPointSourceFile;
120108
}
121109

122110
/**
@@ -152,29 +140,4 @@ export class ExtractorContext {
152140
this._logger.logError(message);
153141
}
154142
}
155-
156-
/**
157-
* Scans for external package api files and loads them into the docItemLoader member before
158-
* any API analysis begins.
159-
*
160-
* @param externalJsonCollectionPath - an absolute path to to the folder that contains all the external
161-
* api json files.
162-
* Ex: if externalJsonPath is './resources', then in that folder
163-
* are 'es6-collections.api.json', etc.
164-
*/
165-
public loadExternalPackages(externalJsonCollectionPath: string): void {
166-
if (!externalJsonCollectionPath) {
167-
return;
168-
}
169-
170-
FileSystem.readFolder(externalJsonCollectionPath, {
171-
absolutePaths: true
172-
}).forEach(file => {
173-
if (path.extname(file) === '.json') {
174-
// Example: "C:\Example\my-package.json" --> "my-package"
175-
const packageName: string = path.parse(file).name;
176-
this.docItemLoader.loadPackageIntoCache(file, packageName);
177-
}
178-
});
179-
}
180143
}

apps/api-extractor/src/analyzer/SymbolAnalyzer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import * as ts from 'typescript';
77

8-
import { TypeScriptHelpers } from '../../utils/TypeScriptHelpers';
8+
import { TypeScriptHelpers } from './TypeScriptHelpers';
99
import { AstImport } from './AstImport';
1010

1111
/**

apps/api-extractor/src/analyzer/TypeScriptHelpers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/* tslint:disable:no-bitwise */
55

66
import * as ts from 'typescript';
7-
import { PrettyPrinter } from './PrettyPrinter';
7+
import { TypeScriptMessageFormatter } from './TypeScriptMessageFormatter';
88

99
export class TypeScriptHelpers {
1010
/**
@@ -90,7 +90,7 @@ export class TypeScriptHelpers {
9090
public static getSymbolForDeclaration(declaration: ts.Declaration): ts.Symbol {
9191
const symbol: ts.Symbol | undefined = TypeScriptHelpers.tryGetSymbolForDeclaration(declaration);
9292
if (!symbol) {
93-
throw new Error(PrettyPrinter.formatFileAndLineNumber(declaration) + ': '
93+
throw new Error(TypeScriptMessageFormatter.formatFileAndLineNumber(declaration) + ': '
9494
+ 'Unable to determine semantic information for this declaration');
9595
}
9696
return symbol;

apps/api-extractor/src/analyzer/TypeScriptMessageFormatter.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,14 @@ export class TypeScriptMessageFormatter {
2323

2424
return formattedErrors.join('; ');
2525
}
26+
27+
/**
28+
* Returns a string such as this, based on the context information in the provided node:
29+
* "[C:\Folder\File.ts#123]"
30+
*/
31+
public static formatFileAndLineNumber(node: ts.Node): string {
32+
const sourceFile: ts.SourceFile = node.getSourceFile();
33+
const lineAndCharacter: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(node.getStart());
34+
return `[${sourceFile.fileName}#${lineAndCharacter.line}]`;
35+
}
2636
}

apps/api-extractor/src/analyzer/test/TypeScriptHelpers.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22
// See LICENSE in the project root for license information.
33

4-
import { TypeScriptHelpers } from '../utils/TypeScriptHelpers';
4+
import { TypeScriptHelpers } from '../TypeScriptHelpers';
55

66
interface ITestCase {
77
input: string;

apps/api-extractor/src/api/Extractor.ts

Lines changed: 5 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,13 @@ import {
1515
import {
1616
IExtractorConfig,
1717
IExtractorProjectConfig,
18-
IExtractorApiJsonFileConfig,
1918
IExtractorDtsRollupConfig
2019
} from './IExtractorConfig';
21-
import { ExtractorContext } from '../ExtractorContext';
2220
import { ILogger } from './ILogger';
23-
import { ApiJsonGenerator } from '../generators/ApiJsonGenerator';
24-
import { ApiFileGenerator } from '../generators/ApiFileGenerator';
25-
import { DtsRollupGenerator, DtsRollupKind } from '../generators/dtsRollup/DtsRollupGenerator';
21+
import { ExtractorContext } from '../analyzer/ExtractorContext';
22+
import { DtsRollupGenerator, DtsRollupKind } from '../generators/DtsRollupGenerator';
2623
import { MonitoredLogger } from './MonitoredLogger';
27-
import { TypeScriptMessageFormatter } from '../utils/TypeScriptMessageFormatter';
24+
import { TypeScriptMessageFormatter } from '../analyzer/TypeScriptMessageFormatter';
2825

2926
/**
3027
* Options for {@link Extractor.processProject}.
@@ -99,10 +96,10 @@ export class Extractor {
9996
* The JSON Schema for API Extractor config file (api-extractor-config.schema.json).
10097
*/
10198
public static jsonSchema: JsonSchema = JsonSchema.fromFile(
102-
path.join(__dirname, './api-extractor.schema.json'));
99+
path.join(__dirname, '../schemas/api-extractor.schema.json'));
103100

104101
private static _defaultConfig: Partial<IExtractorConfig> = JsonFile.load(path.join(__dirname,
105-
'./api-extractor-defaults.json'));
102+
'../schemas/api-extractor-defaults.json'));
106103

107104
private static _declarationFileExtensionRegExp: RegExp = /\.d\.ts$/i;
108105

@@ -315,77 +312,6 @@ export class Extractor {
315312
validationRules: this.actualConfig.validationRules
316313
});
317314

318-
for (const externalJsonFileFolder of projectConfig.externalJsonFileFolders || []) {
319-
context.loadExternalPackages(path.resolve(this._absoluteRootFolder, externalJsonFileFolder));
320-
}
321-
322-
const packageBaseName: string = path.basename(context.packageName);
323-
324-
const apiJsonFileConfig: IExtractorApiJsonFileConfig = this.actualConfig.apiJsonFile;
325-
326-
if (apiJsonFileConfig.enabled) {
327-
const outputFolder: string = path.resolve(this._absoluteRootFolder,
328-
apiJsonFileConfig.outputFolder);
329-
330-
const jsonGenerator: ApiJsonGenerator = new ApiJsonGenerator();
331-
const apiJsonFilename: string = path.join(outputFolder, packageBaseName + '.api.json');
332-
333-
this._monitoredLogger.logVerbose('Writing: ' + apiJsonFilename);
334-
jsonGenerator.writeJsonFile(apiJsonFilename, context);
335-
}
336-
337-
if (this.actualConfig.apiReviewFile.enabled) {
338-
const generator: ApiFileGenerator = new ApiFileGenerator();
339-
const apiReviewFilename: string = packageBaseName + '.api.ts';
340-
341-
const actualApiReviewPath: string = path.resolve(this._absoluteRootFolder,
342-
this.actualConfig.apiReviewFile.tempFolder, apiReviewFilename);
343-
const actualApiReviewShortPath: string = this._getShortFilePath(actualApiReviewPath);
344-
345-
const expectedApiReviewPath: string = path.resolve(this._absoluteRootFolder,
346-
this.actualConfig.apiReviewFile.apiReviewFolder, apiReviewFilename);
347-
const expectedApiReviewShortPath: string = this._getShortFilePath(expectedApiReviewPath);
348-
349-
const actualApiReviewContent: string = generator.generateApiFileContent(context);
350-
351-
// Write the actual file
352-
FileSystem.writeFile(actualApiReviewPath, actualApiReviewContent, {
353-
ensureFolderExists: true
354-
});
355-
356-
// Compare it against the expected file
357-
if (FileSystem.exists(expectedApiReviewPath)) {
358-
const expectedApiReviewContent: string = FileSystem.readFile(expectedApiReviewPath);
359-
360-
if (!ApiFileGenerator.areEquivalentApiFileContents(actualApiReviewContent, expectedApiReviewContent)) {
361-
if (!this._localBuild) {
362-
// For production, issue a warning that will break the CI build.
363-
this._monitoredLogger.logWarning('You have changed the public API signature for this project.'
364-
// @microsoft/gulp-core-build seems to run JSON.stringify() on the error messages for some reason,
365-
// so try to avoid escaped characters:
366-
+ ` Please overwrite ${expectedApiReviewShortPath} with a`
367-
+ ` copy of ${actualApiReviewShortPath}`
368-
+ ' and then request an API review. See the Git repository README.md for more info.');
369-
} else {
370-
// For a local build, just copy the file automatically.
371-
this._monitoredLogger.logWarning('You have changed the public API signature for this project.'
372-
+ ` Updating ${expectedApiReviewShortPath}`);
373-
374-
FileSystem.writeFile(expectedApiReviewPath, actualApiReviewContent);
375-
}
376-
} else {
377-
this._monitoredLogger.logVerbose(`The API signature is up to date: ${actualApiReviewShortPath}`);
378-
}
379-
} else {
380-
// NOTE: This warning seems like a nuisance, but it has caught genuine mistakes.
381-
// For example, when projects were moved into category folders, the relative path for
382-
// the API review files ended up in the wrong place.
383-
this._monitoredLogger.logError(`The API review file has not been set up.`
384-
+ ` Do this by copying ${actualApiReviewShortPath}`
385-
+ ` to ${expectedApiReviewShortPath} and committing it.`);
386-
}
387-
}
388-
389315
this._generateRollupDtsFiles(context);
390316

391317
if (this._localBuild) {
@@ -477,13 +403,6 @@ export class Extractor {
477403
dtsRollupGenerator.writeTypingsFile(mainDtsRollupFullPath, dtsKind);
478404
}
479405

480-
private _getShortFilePath(absolutePath: string): string {
481-
if (!path.isAbsolute(absolutePath)) {
482-
throw new Error('Expected absolute path: ' + absolutePath);
483-
}
484-
return path.relative(this._absoluteRootFolder, absolutePath).replace(/\\/g, '/');
485-
}
486-
487406
/**
488407
* Update the parsed command line to use paths from the specified TS compiler folder, if
489408
* a TS compiler folder is specified.

apps/api-extractor/src/cli/RunAction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import {
1717
CommandLineFlagParameter
1818
} from '@microsoft/ts-command-line';
1919

20-
import { Extractor } from '../extractor/Extractor';
21-
import { IExtractorConfig } from '../extractor/IExtractorConfig';
20+
import { Extractor } from '../api/Extractor';
21+
import { IExtractorConfig } from '../api/IExtractorConfig';
2222

2323
import { ApiExtractorCommandLine } from './ApiExtractorCommandLine';
2424

0 commit comments

Comments
 (0)