Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[api-extractor] Extract source file locations for relevant API items #3590

Merged
merged 11 commits into from
Oct 11, 2022
9 changes: 7 additions & 2 deletions apps/api-extractor/src/api/Extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { ExtractorMessage } from './ExtractorMessage';
import { MessageRouter } from '../collector/MessageRouter';
import { ConsoleMessageId } from './ConsoleMessageId';
import { TSDocConfigFile } from '@microsoft/tsdoc-config';
import { SourceMapper } from '../collector/SourceMapper';

/**
* Runtime options for Extractor.
Expand Down Expand Up @@ -202,13 +203,16 @@ export class Extractor {
compilerState = CompilerState.create(extractorConfig, options);
}

const sourceMapper: SourceMapper = new SourceMapper();

const messageRouter: MessageRouter = new MessageRouter({
workingPackageFolder: extractorConfig.packageFolder,
messageCallback: options.messageCallback,
messagesConfig: extractorConfig.messages || {},
showVerboseMessages: !!options.showVerboseMessages,
showDiagnostics: !!options.showDiagnostics,
tsdocConfiguration: extractorConfig.tsdocConfiguration
tsdocConfiguration: extractorConfig.tsdocConfiguration,
sourceMapper
});

if (extractorConfig.tsdocConfigFile.filePath && !extractorConfig.tsdocConfigFile.fileNotFound) {
Expand Down Expand Up @@ -250,7 +254,8 @@ export class Extractor {
const collector: Collector = new Collector({
program: compilerState.program as ts.Program,
messageRouter,
extractorConfig: extractorConfig
extractorConfig: extractorConfig,
sourceMapper
});

collector.analyze();
Expand Down
7 changes: 7 additions & 0 deletions apps/api-extractor/src/api/ExtractorConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ interface IExtractorConfigParameters {
docModelEnabled: boolean;
apiJsonFilePath: string;
docModelIncludeForgottenExports: boolean;
projectFolderUrl: string | undefined;
rollupEnabled: boolean;
untrimmedFilePath: string;
alphaTrimmedFilePath: string;
Expand Down Expand Up @@ -257,6 +258,8 @@ export class ExtractorConfig {
public readonly apiJsonFilePath: string;
/** {@inheritDoc IConfigDocModel.includeForgottenExports} */
public readonly docModelIncludeForgottenExports: boolean;
/** {@inheritDoc IConfigDocModel.projectFolderUrl} */
public readonly projectFolderUrl: string | undefined;

/** {@inheritDoc IConfigDtsRollup.enabled} */
public readonly rollupEnabled: boolean;
Expand Down Expand Up @@ -317,6 +320,7 @@ export class ExtractorConfig {
this.docModelEnabled = parameters.docModelEnabled;
this.apiJsonFilePath = parameters.apiJsonFilePath;
this.docModelIncludeForgottenExports = parameters.docModelIncludeForgottenExports;
this.projectFolderUrl = parameters.projectFolderUrl;
this.rollupEnabled = parameters.rollupEnabled;
this.untrimmedFilePath = parameters.untrimmedFilePath;
this.alphaTrimmedFilePath = parameters.alphaTrimmedFilePath;
Expand Down Expand Up @@ -894,6 +898,7 @@ export class ExtractorConfig {
let docModelEnabled: boolean = false;
let apiJsonFilePath: string = '';
let docModelIncludeForgottenExports: boolean = false;
let projectFolderUrl: string | undefined;
if (configObject.docModel) {
docModelEnabled = !!configObject.docModel.enabled;
apiJsonFilePath = ExtractorConfig._resolvePathWithTokens(
Expand All @@ -902,6 +907,7 @@ export class ExtractorConfig {
tokenContext
);
docModelIncludeForgottenExports = !!configObject.docModel.includeForgottenExports;
projectFolderUrl = configObject.docModel.projectFolderUrl;
}

let tsdocMetadataEnabled: boolean = false;
Expand Down Expand Up @@ -1009,6 +1015,7 @@ export class ExtractorConfig {
docModelEnabled,
apiJsonFilePath,
docModelIncludeForgottenExports,
projectFolderUrl,
rollupEnabled,
untrimmedFilePath,
alphaTrimmedFilePath,
Expand Down
14 changes: 14 additions & 0 deletions apps/api-extractor/src/api/IConfigFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,20 @@ export interface IConfigDocModel {
* @defaultValue `false`
*/
includeForgottenExports?: boolean;

/**
* The base URL where the project's source code can be viewed on a website such as GitHub or
* Azure DevOps. This URL path corresponds to the `<projectFolder>` path on disk.
*
* @remarks
* This URL is concatenated with the file paths serialized to the doc model to produce URL file paths to individual API items.
* For example, if the `projectFolderUrl` is "https://github.com/microsoft/rushstack/tree/main/apps/api-extractor" and an API
* item's file path is "api/ExtractorConfig.ts", the full URL file path would be
* "https://github.com/microsoft/rushstack/tree/main/apps/api-extractor/api/ExtractorConfig.js".
*
* Can be omitted if you don't need source code links in your API documentation reference.
*/
projectFolderUrl?: string;
}

/**
Expand Down
6 changes: 6 additions & 0 deletions apps/api-extractor/src/collector/Collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { AstReferenceResolver } from '../analyzer/AstReferenceResolver';
import { ExtractorConfig } from '../api/ExtractorConfig';
import { AstNamespaceImport } from '../analyzer/AstNamespaceImport';
import { AstImport } from '../analyzer/AstImport';
import { SourceMapper } from './SourceMapper';

/**
* Options for Collector constructor.
Expand All @@ -44,6 +45,8 @@ export interface ICollectorOptions {
messageRouter: MessageRouter;

extractorConfig: ExtractorConfig;

sourceMapper: SourceMapper;
}

/**
Expand All @@ -66,6 +69,8 @@ export class Collector {

public readonly extractorConfig: ExtractorConfig;

public readonly sourceMapper: SourceMapper;

/**
* The `ExtractorConfig.bundledPackages` names in a set.
*/
Expand Down Expand Up @@ -97,6 +102,7 @@ export class Collector {

this._program = options.program;
this.extractorConfig = options.extractorConfig;
this.sourceMapper = options.sourceMapper;

const entryPointSourceFile: ts.SourceFile | undefined = options.program.getSourceFile(
this.extractorConfig.mainEntryPointFilePath
Expand Down
56 changes: 30 additions & 26 deletions apps/api-extractor/src/collector/MessageRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '../api/ExtractorMessage';
import { ExtractorMessageId, allExtractorMessageIds } from '../api/ExtractorMessageId';
import { IExtractorMessagesConfig, IConfigMessageReportingRule } from '../api/IConfigFile';
import { SourceMapper } from './SourceMapper';
import { ISourceLocation, SourceMapper } from './SourceMapper';
import { ExtractorLogLevel } from '../api/ExtractorLogLevel';
import { ConsoleMessageId } from '../api/ConsoleMessageId';

Expand All @@ -32,6 +32,7 @@ export interface IMessageRouterOptions {
showVerboseMessages: boolean;
showDiagnostics: boolean;
tsdocConfiguration: tsdoc.TSDocConfiguration;
sourceMapper: SourceMapper;
}

export interface IBuildJsonDumpObjectOptions {
Expand Down Expand Up @@ -89,7 +90,7 @@ export class MessageRouter {

this._messages = [];
this._associatedMessagesForAstDeclaration = new Map<AstDeclaration, ExtractorMessage[]>();
this._sourceMapper = new SourceMapper();
this._sourceMapper = options.sourceMapper;
this._tsdocConfiguration = options.tsdocConfiguration;

// showDiagnostics implies showVerboseMessages
Expand Down Expand Up @@ -200,18 +201,19 @@ export class MessageRouter {
};

if (diagnostic.file) {
// NOTE: Since compiler errors pertain to issues specific to the .d.ts files,
// we do not apply source mappings for them.
const sourceFile: ts.SourceFile = diagnostic.file;
const lineAndCharacter: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(
diagnostic.start || 0
);

options.sourceFilePath = sourceFile.fileName;
options.sourceFileLine = lineAndCharacter.line + 1;
options.sourceFileColumn = lineAndCharacter.character + 1;
const sourceLocation: ISourceLocation = this._sourceMapper.getSourceLocation({
sourceFile,
pos: diagnostic.start || 0,
useDtsLocation: true
});
options.sourceFilePath = sourceLocation.sourceFilePath;
options.sourceFileLine = sourceLocation.sourceFileLine;
options.sourceFileColumn = sourceLocation.sourceFileColumn;
zelliott marked this conversation as resolved.
Show resolved Hide resolved
}

// NOTE: Since compiler errors pertain to issues specific to the .d.ts files,
// we do not apply source mappings for them.
this._messages.push(new ExtractorMessage(options));
}

Expand Down Expand Up @@ -252,20 +254,20 @@ export class MessageRouter {
astDeclaration?: AstDeclaration
): void {
for (const message of parserContext.log.messages) {
const lineAndCharacter: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(
message.textRange.pos
);

const options: IExtractorMessageOptions = {
category: ExtractorMessageCategory.TSDoc,
messageId: message.messageId,
text: message.unformattedText,
sourceFilePath: sourceFile.fileName,
sourceFileLine: lineAndCharacter.line + 1,
sourceFileColumn: lineAndCharacter.character + 1
text: message.unformattedText
};

this._sourceMapper.updateExtractorMessageOptions(options);
const sourceLocation: ISourceLocation = this._sourceMapper.getSourceLocation({
sourceFile,
pos: message.textRange.pos
});
options.sourceFilePath = sourceLocation.sourceFilePath;
options.sourceFileLine = sourceLocation.sourceFileLine;
options.sourceFileColumn = sourceLocation.sourceFileColumn;

const extractorMessage: ExtractorMessage = new ExtractorMessage(options);

if (astDeclaration) {
Expand Down Expand Up @@ -369,19 +371,21 @@ export class MessageRouter {
pos: number,
properties?: IExtractorMessageProperties
): ExtractorMessage {
const lineAndCharacter: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(pos);

const options: IExtractorMessageOptions = {
category: ExtractorMessageCategory.Extractor,
messageId,
text: messageText,
sourceFilePath: sourceFile.fileName,
sourceFileLine: lineAndCharacter.line + 1,
sourceFileColumn: lineAndCharacter.character + 1,
properties
};

this._sourceMapper.updateExtractorMessageOptions(options);
const sourceLocation: ISourceLocation = this._sourceMapper.getSourceLocation({
sourceFile,
pos
});
options.sourceFilePath = sourceLocation.sourceFilePath;
options.sourceFileLine = sourceLocation.sourceFileLine;
options.sourceFileColumn = sourceLocation.sourceFileColumn;

const extractorMessage: ExtractorMessage = new ExtractorMessage(options);

this._messages.push(extractorMessage);
Expand Down
Loading