mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 01:04:49 -05:00
@@ -118,6 +118,12 @@ namespace ts.server {
|
||||
return (watch as GeneratedFileWatcher).generatedFilePath !== undefined;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface EmitResult {
|
||||
emitSkipped: boolean;
|
||||
diagnostics: readonly Diagnostic[];
|
||||
}
|
||||
|
||||
export abstract class Project implements LanguageServiceHost, ModuleResolutionHost {
|
||||
private rootFiles: ScriptInfo[] = [];
|
||||
private rootFilesMap = createMap<ProjectRootFile>();
|
||||
@@ -587,11 +593,11 @@ namespace ts.server {
|
||||
/**
|
||||
* Returns true if emit was conducted
|
||||
*/
|
||||
emitFile(scriptInfo: ScriptInfo, writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => void): boolean {
|
||||
emitFile(scriptInfo: ScriptInfo, writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => void): EmitResult {
|
||||
if (!this.languageServiceEnabled || !this.shouldEmitFile(scriptInfo)) {
|
||||
return false;
|
||||
return { emitSkipped: true, diagnostics: emptyArray };
|
||||
}
|
||||
const { emitSkipped, outputFiles } = this.getLanguageService(/*ensureSynchronized*/ false).getEmitOutput(scriptInfo.fileName);
|
||||
const { emitSkipped, diagnostics, outputFiles } = this.getLanguageService().getEmitOutput(scriptInfo.fileName);
|
||||
if (!emitSkipped) {
|
||||
for (const outputFile of outputFiles) {
|
||||
const outputFileAbsoluteFileName = getNormalizedAbsolutePath(outputFile.name, this.currentDirectory);
|
||||
@@ -599,7 +605,7 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
return !emitSkipped;
|
||||
return { emitSkipped, diagnostics };
|
||||
}
|
||||
|
||||
enableLanguageService() {
|
||||
|
||||
@@ -857,10 +857,25 @@ namespace ts.server.protocol {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface EmitOutputRequest extends FileRequest {}
|
||||
export interface EmitOutputRequest extends FileRequest {
|
||||
command: CommandTypes.EmitOutput;
|
||||
arguments: EmitOutputRequestArgs;
|
||||
}
|
||||
/** @internal */
|
||||
export interface EmitOutputRequestArgs extends FileRequestArgs {
|
||||
includeLinePosition?: boolean;
|
||||
/** if true - return response as object with emitSkipped and diagnostics */
|
||||
richResponse?: boolean;
|
||||
}
|
||||
/** @internal */
|
||||
export interface EmitOutputResponse extends Response {
|
||||
readonly body: EmitOutput;
|
||||
readonly body: EmitOutput | ts.EmitOutput;
|
||||
}
|
||||
/** @internal */
|
||||
export interface EmitOutput {
|
||||
outputFiles: OutputFile[];
|
||||
emitSkipped: boolean;
|
||||
diagnostics: Diagnostic[] | DiagnosticWithLinePosition[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1808,6 +1823,18 @@ namespace ts.server.protocol {
|
||||
* if true - then file should be recompiled even if it does not have any changes.
|
||||
*/
|
||||
forced?: boolean;
|
||||
includeLinePosition?: boolean;
|
||||
/** if true - return response as object with emitSkipped and diagnostics */
|
||||
richResponse?: boolean;
|
||||
}
|
||||
|
||||
export interface CompileOnSaveEmitFileResponse extends Response {
|
||||
body: boolean | EmitResult;
|
||||
}
|
||||
|
||||
export interface EmitResult {
|
||||
emitSkipped: boolean;
|
||||
diagnostics: Diagnostic[] | DiagnosticWithLinePosition[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -85,9 +85,9 @@ namespace ts.server {
|
||||
return { line: lineAndCharacter.line + 1, offset: lineAndCharacter.character + 1 };
|
||||
}
|
||||
|
||||
function formatConfigFileDiag(diag: Diagnostic, includeFileName: true): protocol.DiagnosticWithFileName;
|
||||
function formatConfigFileDiag(diag: Diagnostic, includeFileName: false): protocol.Diagnostic;
|
||||
function formatConfigFileDiag(diag: Diagnostic, includeFileName: boolean): protocol.Diagnostic | protocol.DiagnosticWithFileName {
|
||||
function formatDiagnosticToProtocol(diag: Diagnostic, includeFileName: true): protocol.DiagnosticWithFileName;
|
||||
function formatDiagnosticToProtocol(diag: Diagnostic, includeFileName: false): protocol.Diagnostic;
|
||||
function formatDiagnosticToProtocol(diag: Diagnostic, includeFileName: boolean): protocol.Diagnostic | protocol.DiagnosticWithFileName {
|
||||
const start = (diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start!)))!; // TODO: GH#18217
|
||||
const end = (diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start! + diag.length!)))!; // TODO: GH#18217
|
||||
const text = flattenDiagnosticMessageText(diag.messageText, "\n");
|
||||
@@ -699,7 +699,7 @@ namespace ts.server {
|
||||
break;
|
||||
case ConfigFileDiagEvent:
|
||||
const { triggerFile, configFileName: configFile, diagnostics } = event.data;
|
||||
const bakedDiags = map(diagnostics, diagnostic => formatConfigFileDiag(diagnostic, /*includeFileName*/ true));
|
||||
const bakedDiags = map(diagnostics, diagnostic => formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ true));
|
||||
this.event<protocol.ConfigFileDiagnosticEventBody>({
|
||||
triggerFile,
|
||||
configFile,
|
||||
@@ -998,7 +998,7 @@ namespace ts.server {
|
||||
this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnosticsForConfigFile) :
|
||||
map(
|
||||
diagnosticsForConfigFile,
|
||||
diagnostic => formatConfigFileDiag(diagnostic, /*includeFileName*/ false)
|
||||
diagnostic => formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ false)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1009,8 +1009,10 @@ namespace ts.server {
|
||||
length: d.length!, // TODO: GH#18217
|
||||
category: diagnosticCategoryName(d),
|
||||
code: d.code,
|
||||
source: d.source,
|
||||
startLocation: (d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start!)))!, // TODO: GH#18217
|
||||
endLocation: (d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start! + d.length!)))!, // TODO: GH#18217
|
||||
reportsUnnecessary: d.reportsUnnecessary,
|
||||
relatedInformation: map(d.relatedInformation, formatRelatedInformation)
|
||||
}));
|
||||
}
|
||||
@@ -1108,11 +1110,20 @@ namespace ts.server {
|
||||
};
|
||||
}
|
||||
|
||||
private getEmitOutput(args: protocol.FileRequestArgs): EmitOutput {
|
||||
private getEmitOutput(args: protocol.EmitOutputRequestArgs): EmitOutput | protocol.EmitOutput {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
return project.shouldEmitFile(project.getScriptInfo(file)) ?
|
||||
project.getLanguageService().getEmitOutput(file) :
|
||||
{ emitSkipped: true, outputFiles: [] };
|
||||
if (!project.shouldEmitFile(project.getScriptInfo(file))) {
|
||||
return { emitSkipped: true, outputFiles: [], diagnostics: [] };
|
||||
}
|
||||
const result = project.getLanguageService().getEmitOutput(file);
|
||||
return args.richResponse ?
|
||||
{
|
||||
...result,
|
||||
diagnostics: args.includeLinePosition ?
|
||||
this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(result.diagnostics) :
|
||||
result.diagnostics.map(d => formatDiagnosticToProtocol(d, /*includeFileName*/ true))
|
||||
} :
|
||||
result;
|
||||
}
|
||||
|
||||
private mapDefinitionInfo(definitions: readonly DefinitionInfo[], project: Project): readonly protocol.FileSpanWithContext[] {
|
||||
@@ -1708,16 +1719,24 @@ namespace ts.server {
|
||||
);
|
||||
}
|
||||
|
||||
private emitFile(args: protocol.CompileOnSaveEmitFileRequestArgs) {
|
||||
private emitFile(args: protocol.CompileOnSaveEmitFileRequestArgs): boolean | protocol.EmitResult | EmitResult {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
if (!project) {
|
||||
Errors.ThrowNoProject();
|
||||
}
|
||||
if (!project.languageServiceEnabled) {
|
||||
return false;
|
||||
return args.richResponse ? { emitSkipped: true, diagnostics: [] } : false;
|
||||
}
|
||||
const scriptInfo = project.getScriptInfo(file)!;
|
||||
return project.emitFile(scriptInfo, (path, data, writeByteOrderMark) => this.host.writeFile(path, data, writeByteOrderMark));
|
||||
const { emitSkipped, diagnostics } = project.emitFile(scriptInfo, (path, data, writeByteOrderMark) => this.host.writeFile(path, data, writeByteOrderMark));
|
||||
return args.richResponse ?
|
||||
{
|
||||
emitSkipped,
|
||||
diagnostics: args.includeLinePosition ?
|
||||
this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnostics) :
|
||||
diagnostics.map(d => formatDiagnosticToProtocol(d, /*includeFileName*/ true))
|
||||
} :
|
||||
!emitSkipped;
|
||||
}
|
||||
|
||||
private getSignatureHelpItems(args: protocol.SignatureHelpRequestArgs, simplifiedResult: boolean): protocol.SignatureHelpItems | SignatureHelpItems | undefined {
|
||||
|
||||
Reference in New Issue
Block a user