Skip to content

Commit a185e79

Browse files
committed
Remove ILogger and MonitoredLogger, and rewire everything to use MessageRouter instead
1 parent 181c72b commit a185e79

File tree

14 files changed

+351
-252
lines changed

14 files changed

+351
-252
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import { TypeScriptHelpers } from './TypeScriptHelpers';
99
import { AstSymbol } from './AstSymbol';
1010
import { AstModule, AstModuleExportInfo } from './AstModule';
1111
import { PackageMetadataManager } from './PackageMetadataManager';
12-
import { ILogger } from '../api/ILogger';
1312
import { ExportAnalyzer } from './ExportAnalyzer';
1413
import { AstImport } from './AstImport';
14+
import { MessageRouter } from '../collector/MessageRouter';
1515

1616
export type AstEntity = AstSymbol | AstImport;
1717

@@ -83,11 +83,11 @@ export class AstSymbolTable {
8383
= new Map<ts.Identifier, AstEntity | undefined>();
8484

8585
public constructor(program: ts.Program, typeChecker: ts.TypeChecker, packageJsonLookup: PackageJsonLookup,
86-
logger: ILogger) {
86+
messageRouter: MessageRouter) {
8787

8888
this._program = program;
8989
this._typeChecker = typeChecker;
90-
this._packageMetadataManager = new PackageMetadataManager(packageJsonLookup, logger);
90+
this._packageMetadataManager = new PackageMetadataManager(packageJsonLookup, messageRouter);
9191

9292
this._exportAnalyzer = new ExportAnalyzer(
9393
this._program,

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
INodePackageJson
1212
} from '@microsoft/node-core-library';
1313
import { Extractor } from '../api/Extractor';
14-
import { ILogger } from '../api/ILogger';
14+
import { MessageRouter } from '../collector/MessageRouter';
15+
import { ConsoleMessageId } from '../api/ConsoleMessageId';
1516

1617
/**
1718
* Represents analyzed information for a package.json file.
@@ -57,7 +58,7 @@ export class PackageMetadataManager {
5758
public static tsdocMetadataFilename: string = 'tsdoc-metadata.json';
5859

5960
private readonly _packageJsonLookup: PackageJsonLookup;
60-
private readonly _logger: ILogger;
61+
private readonly _messageRouter: MessageRouter;
6162
private readonly _packageMetadataByPackageJsonPath: Map<string, PackageMetadata>
6263
= new Map<string, PackageMetadata>();
6364

@@ -147,9 +148,9 @@ export class PackageMetadataManager {
147148
});
148149
}
149150

150-
public constructor(packageJsonLookup: PackageJsonLookup, logger: ILogger) {
151+
public constructor(packageJsonLookup: PackageJsonLookup, messageRouter: MessageRouter) {
151152
this._packageJsonLookup = packageJsonLookup;
152-
this._logger = logger;
153+
this._messageRouter = messageRouter;
153154
}
154155

155156
/**
@@ -179,7 +180,7 @@ export class PackageMetadataManager {
179180
);
180181

181182
if (FileSystem.exists(tsdocMetadataPath)) {
182-
this._logger.logVerbose('Found metadata in ' + tsdocMetadataPath);
183+
this._messageRouter.logVerbose(ConsoleMessageId.FoundTSDocMetadata, 'Found metadata in ' + tsdocMetadataPath);
183184
// If the file exists at all, assume it was written by API Extractor
184185
aedocSupported = true;
185186
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
// See LICENSE in the project root for license information.
3+
4+
/**
5+
* Unique identifiers for console messages reported by API Extractor.
6+
*
7+
* @remarks
8+
*
9+
* These strings are possible values for the {@link ExtractorMessage.messageId} property
10+
* when the `ExtractorMessage.category` is {@link ExtractorMessageCategory.Console}.
11+
*
12+
* @public
13+
*/
14+
export const enum ConsoleMessageId {
15+
/**
16+
* "'Found metadata in ___"
17+
*/
18+
FoundTSDocMetadata = 'console-found-tsdoc-metadata',
19+
20+
/**
21+
* "Writing: ___"
22+
*/
23+
WritingDocModelFile = 'console-writing-doc-model-file',
24+
25+
/**
26+
* "Writing package typings: ___"
27+
*/
28+
WritingDtsRollup = 'console-writing-dts-rollup',
29+
30+
/**
31+
* "You have changed the public API signature for this project. Please overwrite ___ with a
32+
* copy of ___ and then request an API review. See the Git repository README.md for more info."
33+
*/
34+
ApiReportNotCopied = 'console-api-report-not-copied',
35+
36+
/**
37+
* "You have changed the public API signature for this project. Updating ___"
38+
*/
39+
ApiReportCopied = 'console-api-report-copied',
40+
41+
/**
42+
* "The API signature is up to date: ___"
43+
*/
44+
ApiReportUnchanged = 'console-api-report-unchanged',
45+
46+
/**
47+
* "The API review file has not been set up. Do this by copying ___ to ___ and committing it."
48+
*/
49+
ApiReportMissing = 'console-api-report-missing'
50+
}

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

Lines changed: 38 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
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 lodash = require('lodash');
5-
import colors = require('colors');
6-
74
import {
85
FileSystem,
96
NewlineKind,
107
PackageJsonLookup,
118
IPackageJson
129
} from '@microsoft/node-core-library';
1310
import { ExtractorConfig } from './ExtractorConfig';
14-
import { ILogger } from './ILogger';
1511
import { Collector } from '../collector/Collector';
1612
import { DtsRollupGenerator, DtsRollupKind } from '../generators/DtsRollupGenerator';
17-
import { MonitoredLogger } from './MonitoredLogger';
1813
import { ApiModelGenerator } from '../generators/ApiModelGenerator';
1914
import { ApiPackage } from '@microsoft/api-extractor-model';
2015
import { ReviewFileGenerator } from '../generators/ReviewFileGenerator';
@@ -23,6 +18,8 @@ import { ValidationEnhancer } from '../enhancers/ValidationEnhancer';
2318
import { DocCommentEnhancer } from '../enhancers/DocCommentEnhancer';
2419
import { CompilerState } from './CompilerState';
2520
import { ExtractorMessage } from './ExtractorMessage';
21+
import { MessageRouter } from '../collector/MessageRouter';
22+
import { ConsoleMessageId } from './ConsoleMessageId';
2623

2724
/**
2825
* Runtime options for Extractor.
@@ -36,12 +33,6 @@ export interface IExtractorInvokeOptions {
3633
*/
3734
compilerState?: CompilerState;
3835

39-
/**
40-
* Allows the caller to customize how API Extractor's errors, warnings, and informational logging is processed.
41-
* If omitted, the output will be printed to the console.
42-
*/
43-
customLogger?: Partial<ILogger>;
44-
4536
/**
4637
* Indicates that API Extractor is running as part of a local build, e.g. on developer's
4738
* machine. This disables certain validation that would normally be performed
@@ -52,6 +43,11 @@ export interface IExtractorInvokeOptions {
5243
*/
5344
localBuild?: boolean;
5445

46+
/**
47+
* If true, API Extractor will include {@link ExtractorLogLevel.Verbose} messages in its output.
48+
*/
49+
showVerboseMessages?: boolean;
50+
5551
/**
5652
* By default API Extractor uses its own TypeScript compiler version to analyze your project.
5753
* This can often cause compiler errors due to incompatibilities between different TS versions.
@@ -99,12 +95,18 @@ export class ExtractorResult {
9995
public readonly succeeded: boolean;
10096

10197
/**
102-
* Reports the number of times that {@link ILogger.logError} was called.
98+
* Reports the number of errors encountered during analysis.
99+
*
100+
* @remarks
101+
* This does not count exceptions, where unexpected issues prematurely abort the operation.
103102
*/
104103
public readonly errorCount: number;
105104

106105
/**
107-
* Reports the number of times that {@link ILogger.logWarning} was called.
106+
* Reports the number of warnings encountered during analysis.
107+
*
108+
* @remarks
109+
* This does not count warnings that are emitted in the API report file.
108110
*/
109111
public readonly warningCount: number;
110112

@@ -141,13 +143,6 @@ export class Extractor {
141143
return PackageJsonLookup.loadOwnPackageJson(__dirname);
142144
}
143145

144-
private static _defaultLogger: ILogger = {
145-
logVerbose: (message: string) => console.log('(Verbose) ' + message),
146-
logInfo: (message: string) => console.log(message),
147-
logWarning: (message: string) => console.warn(colors.yellow(message)),
148-
logError: (message: string) => console.error(colors.red(message))
149-
};
150-
151146
/**
152147
* Load the api-extractor.json config file from the specified path, and then invoke API Extractor.
153148
*/
@@ -166,18 +161,8 @@ export class Extractor {
166161
options = { };
167162
}
168163

169-
let mergedLogger: ILogger;
170-
if (options && options.customLogger) {
171-
mergedLogger = lodash.merge(lodash.clone(Extractor._defaultLogger), options.customLogger);
172-
} else {
173-
mergedLogger = Extractor._defaultLogger;
174-
}
175-
const monitoredLogger: MonitoredLogger = new MonitoredLogger(mergedLogger);
176-
177164
const localBuild: boolean = options.localBuild || false;
178165

179-
monitoredLogger.resetCounters();
180-
181166
let compilerState: CompilerState | undefined;
182167
if (options.compilerState) {
183168
compilerState = options.compilerState;
@@ -187,10 +172,13 @@ export class Extractor {
187172

188173
const collector: Collector = new Collector({
189174
program: compilerState.program,
190-
logger: monitoredLogger,
175+
messageCallback: options.messageCallback,
191176
extractorConfig: extractorConfig
192177
});
193178

179+
const messageRouter: MessageRouter = collector.messageRouter;
180+
messageRouter.showVerboseMessages = !!options.showVerboseMessages;
181+
194182
collector.analyze();
195183

196184
DocCommentEnhancer.analyze(collector);
@@ -200,7 +188,7 @@ export class Extractor {
200188
const apiPackage: ApiPackage = modelBuilder.buildApiPackage();
201189

202190
if (extractorConfig.docModelEnabled) {
203-
monitoredLogger.logVerbose('Writing: ' + extractorConfig.apiJsonFilePath);
191+
messageRouter.logVerbose(ConsoleMessageId.WritingDocModelFile, 'Writing: ' + extractorConfig.apiJsonFilePath);
204192
apiPackage.saveToJsonFile(extractorConfig.apiJsonFilePath, {
205193
toolPackage: Extractor.packageName,
206194
toolVersion: Extractor.version,
@@ -233,15 +221,17 @@ export class Extractor {
233221
if (!ReviewFileGenerator.areEquivalentApiFileContents(actualApiReviewContent, expectedApiReviewContent)) {
234222
if (!localBuild) {
235223
// For production, issue a warning that will break the CI build.
236-
monitoredLogger.logWarning('You have changed the public API signature for this project.'
224+
messageRouter.logWarning(ConsoleMessageId.ApiReportNotCopied,
225+
'You have changed the public API signature for this project.'
237226
// @microsoft/gulp-core-build seems to run JSON.stringify() on the error messages for some reason,
238227
// so try to avoid escaped characters:
239228
+ ` Please overwrite ${expectedApiReviewShortPath} with a`
240229
+ ` copy of ${actualApiReviewShortPath}`
241230
+ ' and then request an API review. See the Git repository README.md for more info.');
242231
} else {
243232
// For a local build, just copy the file automatically.
244-
monitoredLogger.logWarning('You have changed the public API signature for this project.'
233+
messageRouter.logWarning(ConsoleMessageId.ApiReportCopied,
234+
'You have changed the public API signature for this project.'
245235
+ ` Updating ${expectedApiReviewShortPath}`);
246236

247237
FileSystem.writeFile(expectedApiReviewPath, actualApiReviewContent, {
@@ -250,64 +240,55 @@ export class Extractor {
250240
});
251241
}
252242
} else {
253-
monitoredLogger.logVerbose(`The API signature is up to date: ${actualApiReviewShortPath}`);
243+
messageRouter.logVerbose(ConsoleMessageId.ApiReportUnchanged,
244+
`The API signature is up to date: ${actualApiReviewShortPath}`);
254245
}
255246
} else {
256247
// NOTE: This warning seems like a nuisance, but it has caught genuine mistakes.
257248
// For example, when projects were moved into category folders, the relative path for
258249
// the API review files ended up in the wrong place.
259-
monitoredLogger.logError(`The API review file has not been set up.`
250+
messageRouter.logError(ConsoleMessageId.ApiReportMissing, `The API review file has not been set up.`
260251
+ ` Do this by copying ${actualApiReviewShortPath}`
261252
+ ` to ${expectedApiReviewShortPath} and committing it.`);
262253
}
263254
}
264255

265256
if (extractorConfig.rollupEnabled) {
266-
Extractor._generateRollupDtsFile(collector, monitoredLogger,
267-
extractorConfig.publicTrimmedFilePath,
268-
DtsRollupKind.PublicRelease);
269-
270-
Extractor._generateRollupDtsFile(collector, monitoredLogger,
271-
extractorConfig.betaTrimmedFilePath,
272-
DtsRollupKind.BetaRelease);
273-
274-
Extractor._generateRollupDtsFile(collector, monitoredLogger,
275-
extractorConfig.untrimmedFilePath,
276-
DtsRollupKind.InternalRelease);
257+
Extractor._generateRollupDtsFile(collector, extractorConfig.publicTrimmedFilePath, DtsRollupKind.PublicRelease);
258+
Extractor._generateRollupDtsFile(collector, extractorConfig.betaTrimmedFilePath, DtsRollupKind.BetaRelease);
259+
Extractor._generateRollupDtsFile(collector, extractorConfig.untrimmedFilePath, DtsRollupKind.InternalRelease);
277260
}
278261

279262
if (extractorConfig.tsdocMetadataEnabled) {
280263
// Write the tsdoc-metadata.json file for this project
281264
PackageMetadataManager.writeTsdocMetadataFile(extractorConfig.tsdocMetadataFilePath);
282265
}
283266

284-
// Show out all the messages that we collected during analysis
285-
collector.messageRouter.reportMessagesToLogger(monitoredLogger, collector.workingPackage.packageFolder);
267+
// Show all the messages that we collected during analysis
268+
messageRouter.handleRemainingNonConsoleMessages();
286269

287270
// Determine success
288271
let succeeded: boolean;
289272
if (localBuild) {
290273
// For a local build, fail if there were errors (but ignore warnings)
291-
succeeded = monitoredLogger.errorCount === 0;
274+
succeeded = messageRouter.errorCount === 0;
292275
} else {
293276
// For a production build, fail if there were any errors or warnings
294-
succeeded = monitoredLogger.errorCount + monitoredLogger.warningCount === 0;
277+
succeeded = messageRouter.errorCount + messageRouter.warningCount === 0;
295278
}
296279

297280
return new ExtractorResult({
298281
compilerState,
299282
extractorConfig,
300283
succeeded,
301-
errorCount: monitoredLogger.errorCount,
302-
warningCount: monitoredLogger.warningCount
284+
errorCount: messageRouter.errorCount,
285+
warningCount: messageRouter.warningCount
303286
});
304287
}
305288

306-
private static _generateRollupDtsFile(collector: Collector, monitoredLogger: MonitoredLogger,
307-
outputPath: string, dtsKind: DtsRollupKind): void {
308-
289+
private static _generateRollupDtsFile(collector: Collector, outputPath: string, dtsKind: DtsRollupKind): void {
309290
if (outputPath !== '') {
310-
monitoredLogger.logVerbose(`Writing package typings: ${outputPath}`);
291+
collector.messageRouter.logVerbose(ConsoleMessageId.WritingDtsRollup, `Writing package typings: ${outputPath}`);
311292
DtsRollupGenerator.writeTypingsFile(collector, outputPath, dtsKind);
312293
}
313294
}

0 commit comments

Comments
 (0)