Skip to content

Commit b12be3d

Browse files
Remove dependency from the typechecker to the compiler host.
This also lets us not expose the compiler host from the Program instance. The compiler host was only needed by the type checker to get the host newline. The host newline was used for concatenating diagnostic message chains. Now we don't concatenate them up front. Instead, we just store the message chain in the diagnostic itself. Then when we pass it to the host, it can then decide what newline to use.
1 parent de30866 commit b12be3d

19 files changed

Lines changed: 135 additions & 134 deletions

src/compiler/checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3476,7 +3476,7 @@ module ts {
34763476
errorInfo = concatenateDiagnosticMessageChains(containingMessageChain, errorInfo);
34773477
}
34783478

3479-
diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, host.getCompilerHost().getNewLine()));
3479+
diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo));
34803480
}
34813481
return result !== Ternary.False;
34823482

@@ -8924,7 +8924,7 @@ module ts {
89248924

89258925
var errorInfo = chainDiagnosticMessages(undefined, Diagnostics.Named_properties_0_of_types_1_and_2_are_not_identical, prop.name, typeName1, typeName2);
89268926
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2);
8927-
diagnostics.add(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo, host.getCompilerHost().getNewLine()));
8927+
diagnostics.add(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo));
89288928
}
89298929
}
89308930
}

src/compiler/core.ts

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -325,38 +325,6 @@ module ts {
325325
return headChain;
326326
}
327327

328-
export function flattenDiagnosticChain(file: SourceFile, start: number, length: number, diagnosticChain: DiagnosticMessageChain, newLine: string): Diagnostic {
329-
Debug.assert(start >= 0, "start must be non-negative, is " + start);
330-
Debug.assert(length >= 0, "length must be non-negative, is " + length);
331-
332-
var code = diagnosticChain.code;
333-
var category = diagnosticChain.category;
334-
var messageText = "";
335-
336-
var indent = 0;
337-
while (diagnosticChain) {
338-
if (indent) {
339-
messageText += newLine;
340-
341-
for (var i = 0; i < indent; i++) {
342-
messageText += " ";
343-
}
344-
}
345-
messageText += diagnosticChain.messageText;
346-
indent++;
347-
diagnosticChain = diagnosticChain.next;
348-
}
349-
350-
return {
351-
file,
352-
start,
353-
length,
354-
code,
355-
category,
356-
messageText
357-
};
358-
}
359-
360328
export function compareValues<T>(a: T, b: T): Comparison {
361329
if (a === b) return Comparison.EqualTo;
362330
if (a === undefined) return Comparison.LessThan;
@@ -373,10 +341,34 @@ module ts {
373341
compareValues(d1.start, d2.start) ||
374342
compareValues(d1.length, d2.length) ||
375343
compareValues(d1.code, d2.code) ||
376-
compareValues(d1.messageText, d2.messageText) ||
344+
compareMessageText(d1.messageText, d2.messageText) ||
377345
0;
378346
}
379347

348+
function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): number {
349+
while (text1 && text2) {
350+
// We still have both chains.
351+
var string1 = typeof text1 === "string" ? text1 : text1.messageText;
352+
var string2 = typeof text2 === "string" ? text2 : text2.messageText;
353+
354+
var res = compareValues(string1, string2);
355+
if (res) {
356+
return res;
357+
}
358+
359+
text1 = typeof text1 === "string" ? undefined : text1.next;
360+
text2 = typeof text2 === "string" ? undefined : text2.next;
361+
}
362+
363+
if (!text1 && !text2) {
364+
// if the chains are done, then these messages are the same.
365+
return 0;
366+
}
367+
368+
// We still have one chain remaining. The shorter chain should come first.
369+
return text1 ? 1 : -1;
370+
}
371+
380372
export function deduplicateSortedDiagnostics(diagnostics: Diagnostic[]): Diagnostic[] {
381373
if (diagnostics.length < 2) {
382374
return diagnostics;

src/compiler/program.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ module ts {
2323
}
2424
catch (e) {
2525
if (onError) {
26-
onError(e.number === unsupportedFileEncodingErrorCode ?
27-
createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText :
28-
e.message);
26+
onError(e.number === unsupportedFileEncodingErrorCode
27+
? createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText
28+
: e.message);
2929
}
3030
text = "";
3131
}
@@ -97,7 +97,6 @@ module ts {
9797
getSourceFile: getSourceFile,
9898
getSourceFiles: () => files,
9999
getCompilerOptions: () => options,
100-
getCompilerHost: () => host,
101100
getDiagnostics,
102101
getGlobalDiagnostics,
103102
getTypeCheckerDiagnostics,
@@ -118,17 +117,16 @@ module ts {
118117
return program;
119118

120119
function getEmitHost(writeFileCallback?: WriteFileCallback) {
121-
var compilerHost = program.getCompilerHost();
122120
return {
123-
getCanonicalFileName: compilerHost.getCanonicalFileName,
121+
getCanonicalFileName: host.getCanonicalFileName,
124122
getCommonSourceDirectory: program.getCommonSourceDirectory,
125123
getCompilerOptions: program.getCompilerOptions,
126-
getCurrentDirectory: compilerHost.getCurrentDirectory,
127-
getNewLine: compilerHost.getNewLine,
124+
getCurrentDirectory: host.getCurrentDirectory,
125+
getNewLine: host.getNewLine,
128126
getSourceFile: program.getSourceFile,
129127
getSourceFiles: program.getSourceFiles,
130128
isEmitBlocked,
131-
writeFile: writeFileCallback || compilerHost.writeFile,
129+
writeFile: writeFileCallback || host.writeFile,
132130
};
133131
}
134132

src/compiler/tsc.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ module ts {
7878
}
7979

8080
function getDiagnosticText(message: DiagnosticMessage, ...args: any[]): string {
81-
var diagnostic: Diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
82-
return diagnostic.messageText;
81+
var diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
82+
return <string>diagnostic.messageText;
8383
}
8484

8585
function reportDiagnostic(diagnostic: Diagnostic) {
@@ -92,7 +92,7 @@ module ts {
9292
}
9393

9494
var category = DiagnosticCategory[diagnostic.category].toLowerCase();
95-
output += category + " TS" + diagnostic.code + ": " + diagnostic.messageText + sys.newLine;
95+
output += category + " TS" + diagnostic.code + ": " + flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) + sys.newLine;
9696

9797
sys.write(output);
9898
}

src/compiler/types.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -933,15 +933,14 @@ module ts {
933933

934934
export interface Program extends ScriptReferenceHost {
935935
getSourceFiles(): SourceFile[];
936-
getCompilerHost(): CompilerHost;
937936

938937
/**
939938
* Emits the javascript and declaration files. If targetSourceFile is not specified, then
940939
* the javascript and declaration files will be produced for all the files in this program.
941940
* If targetSourceFile is specified, then only the javascript and declaration for that
942941
* specific file will be generated.
943942
*
944-
* If writeFile is not specified then the writeFile callback from getCompilerHost() will be
943+
* If writeFile is not specified then the writeFile callback from the compiler host will be
945944
* used for writing the javascript and declaration files. Otherwise, the writeFile parameter
946945
* will be invoked when writing the javascript and declaration files.
947946
*/
@@ -1009,7 +1008,6 @@ module ts {
10091008

10101009
export interface TypeCheckerHost {
10111010
getCompilerOptions(): CompilerOptions;
1012-
getCompilerHost(): CompilerHost;
10131011

10141012
getSourceFiles(): SourceFile[];
10151013
getSourceFile(fileName: string): SourceFile;
@@ -1451,7 +1449,7 @@ module ts {
14511449
file: SourceFile;
14521450
start: number;
14531451
length: number;
1454-
messageText: string;
1452+
messageText: string | DiagnosticMessageChain;
14551453
category: DiagnosticCategory;
14561454
code: number;
14571455
}

src/compiler/utilities.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,45 @@ module ts {
199199
return createFileDiagnostic(file, start, length, message, arg0, arg1, arg2);
200200
}
201201

202-
export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain, newLine: string): Diagnostic {
202+
export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain): Diagnostic {
203203
node = getErrorSpanForNode(node);
204204
var file = getSourceFileOfNode(node);
205205
var start = skipTrivia(file.text, node.pos);
206206
var length = node.end - start;
207-
return flattenDiagnosticChain(file, start, length, messageChain, newLine);
207+
return {
208+
file,
209+
start,
210+
length,
211+
code: messageChain.code,
212+
category: messageChain.category,
213+
messageText: messageChain
214+
};
215+
}
216+
217+
export function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string {
218+
if (typeof messageText === "string") {
219+
return messageText;
220+
}
221+
else {
222+
var diagnosticChain = messageText;
223+
var result = "";
224+
225+
var indent = 0;
226+
while (diagnosticChain) {
227+
if (indent) {
228+
result += newLine;
229+
230+
for (var i = 0; i < indent; i++) {
231+
result += " ";
232+
}
233+
}
234+
result += diagnosticChain.messageText;
235+
indent++;
236+
diagnosticChain = diagnosticChain.next;
237+
}
238+
239+
return result;
240+
}
208241
}
209242

210243
export function getErrorSpanForNode(node: Node): Node {

src/harness/fourslash.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,9 @@ module FourSlash {
513513
}
514514

515515
errors.forEach(function (error: ts.Diagnostic) {
516-
Harness.IO.log(" minChar: " + error.start + ", limChar: " + (error.start + error.length) + ", message: " + error.messageText + "\n");
516+
Harness.IO.log(" minChar: " + error.start +
517+
", limChar: " + (error.start + error.length) +
518+
", message: " + ts.flattenDiagnosticMessageText(error.messageText, ts.sys.newLine) + "\n");
517519
});
518520
}
519521

@@ -1179,7 +1181,10 @@ module FourSlash {
11791181

11801182
if (errorList.length) {
11811183
errorList.forEach(err => {
1182-
Harness.IO.log("start: " + err.start + ", length: " + err.length + ", message: " + err.messageText);
1184+
Harness.IO.log(
1185+
"start: " + err.start +
1186+
", length: " + err.length +
1187+
", message: " + ts.flattenDiagnosticMessageText(err.messageText, ts.sys.newLine));
11831188
});
11841189
}
11851190
}
@@ -2214,7 +2219,7 @@ module FourSlash {
22142219

22152220
var errors = program.getDiagnostics().concat(checker.getDiagnostics());
22162221
if (errors.length > 0) {
2217-
throw new Error('Error compiling ' + fileName + ': ' + errors.map(e => e.messageText).join('\r\n'));
2222+
throw new Error('Error compiling ' + fileName + ': ' + errors.map(e => ts.flattenDiagnosticMessageText(e.messageText, ts.sys.newLine)).join('\r\n'));
22182223
}
22192224
program.emit();
22202225
result = result || ''; // Might have an empty fourslash file

src/harness/harness.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ module Utils {
183183
return {
184184
start: diagnostic.start,
185185
length: diagnostic.length,
186-
messageText: diagnostic.messageText,
186+
messageText: ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine),
187187
category: (<any>ts).DiagnosticCategory[diagnostic.category],
188188
code: diagnostic.code
189189
};
@@ -305,7 +305,9 @@ module Utils {
305305

306306
assert.equal(d1.start, d2.start, "d1.start !== d2.start");
307307
assert.equal(d1.length, d2.length, "d1.length !== d2.length");
308-
assert.equal(d1.messageText, d2.messageText, "d1.messageText !== d2.messageText");
308+
assert.equal(
309+
ts.flattenDiagnosticMessageText(d1.messageText, ts.sys.newLine),
310+
ts.flattenDiagnosticMessageText(d2.messageText, ts.sys.newLine), "d1.messageText !== d2.messageText");
309311
assert.equal(d1.category, d2.category, "d1.category !== d2.category");
310312
assert.equal(d1.code, d2.code, "d1.code !== d2.code");
311313
}
@@ -1182,7 +1184,7 @@ module Harness {
11821184
end: err.start + err.length,
11831185
line: errorLineInfo.line,
11841186
character: errorLineInfo.character,
1185-
message: err.messageText,
1187+
message: ts.flattenDiagnosticMessageText(err.messageText, ts.sys.newLine),
11861188
category: ts.DiagnosticCategory[err.category].toLowerCase(),
11871189
code: err.code
11881190
};

src/harness/harnessLanguageService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ module Harness.LanguageService {
134134
public trace(s: string) {
135135
}
136136

137+
public getNewLine(): string {
138+
return "\r\n";
139+
}
140+
137141
public addDefaultLibrary() {
138142
this.addScript(Harness.Compiler.defaultLibFileName, Harness.Compiler.defaultLibSourceFile.text);
139143
}

src/harness/projectsRunner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,14 +275,14 @@ class ProjectRunner extends RunnerBase {
275275
function compileCompileDTsFiles(compilerResult: BatchCompileProjectTestCaseResult) {
276276
var allInputFiles: { emittedFileName: string; code: string; }[] = [];
277277
var compilerOptions = compilerResult.program.getCompilerOptions();
278-
var compilerHost = compilerResult.program.getCompilerHost();
278+
279279
ts.forEach(compilerResult.program.getSourceFiles(), sourceFile => {
280280
if (Harness.Compiler.isDTS(sourceFile.fileName)) {
281281
allInputFiles.unshift({ emittedFileName: sourceFile.fileName, code: sourceFile.text });
282282
}
283283
else if (ts.shouldEmitToOwnFile(sourceFile, compilerResult.program.getCompilerOptions())) {
284284
if (compilerOptions.outDir) {
285-
var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerHost.getCurrentDirectory());
285+
var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program.getCurrentDirectory());
286286
sourceFilePath = sourceFilePath.replace(compilerResult.program.getCommonSourceDirectory(), "");
287287
var emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath));
288288
}

0 commit comments

Comments
 (0)