Skip to content

Commit 8ad2744

Browse files
authored
Refactor baseliners out of compiler runner (#10440)
1 parent def29f6 commit 8ad2744

File tree

3 files changed

+227
-216
lines changed

3 files changed

+227
-216
lines changed

src/harness/compilerRunner.ts

Lines changed: 7 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
/// <reference path="harness.ts" />
22
/// <reference path="runnerbase.ts" />
33
/// <reference path="typeWriter.ts" />
4-
// In harness baselines, null is different than undefined. See `generateActual` in `harness.ts`.
5-
/* tslint:disable:no-null-keyword */
64

75
const enum CompilerTestType {
86
Conformance,
@@ -136,21 +134,10 @@ class CompilerBaselineRunner extends RunnerBase {
136134
otherFiles = undefined;
137135
});
138136

139-
function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
140-
return file.writeByteOrderMark ? "\u00EF\u00BB\u00BF" : "";
141-
}
142-
143-
function getErrorBaseline(toBeCompiled: Harness.Compiler.TestFile[], otherFiles: Harness.Compiler.TestFile[], result: Harness.Compiler.CompilerResult) {
144-
return Harness.Compiler.getErrorBaseline(toBeCompiled.concat(otherFiles), result.errors);
145-
}
146-
147137
// check errors
148138
it("Correct errors for " + fileName, () => {
149139
if (this.errors) {
150-
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".errors.txt"), (): string => {
151-
if (result.errors.length === 0) return null;
152-
return getErrorBaseline(toBeCompiled, otherFiles, result);
153-
});
140+
Harness.Compiler.doErrorBaseline(justName, toBeCompiled.concat(otherFiles), result.errors);
154141
}
155142
});
156143

@@ -168,8 +155,10 @@ class CompilerBaselineRunner extends RunnerBase {
168155
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => {
169156
const record = result.getSourceMapRecord();
170157
if (options.noEmitOnError && result.errors.length !== 0 && record === undefined) {
171-
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn"t required.
158+
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required.
159+
/* tslint:disable:no-null-keyword */
172160
return null;
161+
/* tslint:enable:no-null-keyword */
173162
}
174163
return record;
175164
});
@@ -178,217 +167,20 @@ class CompilerBaselineRunner extends RunnerBase {
178167

179168
it("Correct JS output for " + fileName, () => {
180169
if (hasNonDtsFiles && this.emit) {
181-
if (!options.noEmit && result.files.length === 0 && result.errors.length === 0) {
182-
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
183-
}
184-
185-
// check js output
186-
Harness.Baseline.runBaseline(justName.replace(/\.tsx?/, ".js"), () => {
187-
let tsCode = "";
188-
const tsSources = otherFiles.concat(toBeCompiled);
189-
if (tsSources.length > 1) {
190-
tsCode += "//// [" + fileName + "] ////\r\n\r\n";
191-
}
192-
for (let i = 0; i < tsSources.length; i++) {
193-
tsCode += "//// [" + Harness.Path.getFileName(tsSources[i].unitName) + "]\r\n";
194-
tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? "\r\n" : "");
195-
}
196-
197-
let jsCode = "";
198-
for (let i = 0; i < result.files.length; i++) {
199-
jsCode += "//// [" + Harness.Path.getFileName(result.files[i].fileName) + "]\r\n";
200-
jsCode += getByteOrderMarkText(result.files[i]);
201-
jsCode += result.files[i].code;
202-
}
203-
204-
if (result.declFilesCode.length > 0) {
205-
jsCode += "\r\n\r\n";
206-
for (let i = 0; i < result.declFilesCode.length; i++) {
207-
jsCode += "//// [" + Harness.Path.getFileName(result.declFilesCode[i].fileName) + "]\r\n";
208-
jsCode += getByteOrderMarkText(result.declFilesCode[i]);
209-
jsCode += result.declFilesCode[i].code;
210-
}
211-
}
212-
213-
const declFileCompilationResult =
214-
Harness.Compiler.compileDeclarationFiles(
215-
toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined);
216-
217-
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
218-
jsCode += "\r\n\r\n//// [DtsFileErrors]\r\n";
219-
jsCode += "\r\n\r\n";
220-
jsCode += getErrorBaseline(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles, declFileCompilationResult.declResult);
221-
}
222-
223-
if (jsCode.length > 0) {
224-
return tsCode + "\r\n\r\n" + jsCode;
225-
}
226-
else {
227-
return null;
228-
}
229-
});
170+
Harness.Compiler.doJsEmitBaseline(justName, fileName, options, result, toBeCompiled, otherFiles, harnessSettings);
230171
}
231172
});
232173

233174
it("Correct Sourcemap output for " + fileName, () => {
234-
if (options.inlineSourceMap) {
235-
if (result.sourceMaps.length > 0) {
236-
throw new Error("No sourcemap files should be generated if inlineSourceMaps was set.");
237-
}
238-
return null;
239-
}
240-
else if (options.sourceMap) {
241-
if (result.sourceMaps.length !== result.files.length) {
242-
throw new Error("Number of sourcemap files should be same as js files.");
243-
}
244-
245-
Harness.Baseline.runBaseline(justName.replace(/\.tsx?/, ".js.map"), () => {
246-
if (options.noEmitOnError && result.errors.length !== 0 && result.sourceMaps.length === 0) {
247-
// We need to return null here or the runBaseLine will actually create a empty file.
248-
// Baselining isn't required here because there is no output.
249-
return null;
250-
}
251-
252-
let sourceMapCode = "";
253-
for (let i = 0; i < result.sourceMaps.length; i++) {
254-
sourceMapCode += "//// [" + Harness.Path.getFileName(result.sourceMaps[i].fileName) + "]\r\n";
255-
sourceMapCode += getByteOrderMarkText(result.sourceMaps[i]);
256-
sourceMapCode += result.sourceMaps[i].code;
257-
}
258-
259-
return sourceMapCode;
260-
});
261-
}
175+
Harness.Compiler.doSourcemapBaseline(justName, options, result);
262176
});
263177

264178
it("Correct type/symbol baselines for " + fileName, () => {
265179
if (fileName.indexOf("APISample") >= 0) {
266180
return;
267181
}
268182

269-
// NEWTODO: Type baselines
270-
if (result.errors.length !== 0) {
271-
return;
272-
}
273-
274-
// The full walker simulates the types that you would get from doing a full
275-
// compile. The pull walker simulates the types you get when you just do
276-
// a type query for a random node (like how the LS would do it). Most of the
277-
// time, these will be the same. However, occasionally, they can be different.
278-
// Specifically, when the compiler internally depends on symbol IDs to order
279-
// things, then we may see different results because symbols can be created in a
280-
// different order with 'pull' operations, and thus can produce slightly differing
281-
// output.
282-
//
283-
// For example, with a full type check, we may see a type displayed as: number | string
284-
// But with a pull type check, we may see it as: string | number
285-
//
286-
// These types are equivalent, but depend on what order the compiler observed
287-
// certain parts of the program.
288-
289-
const program = result.program;
290-
const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
291-
292-
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
293-
294-
const fullResults = ts.createMap<TypeWriterResult[]>();
295-
const pullResults = ts.createMap<TypeWriterResult[]>();
296-
297-
for (const sourceFile of allFiles) {
298-
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
299-
pullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
300-
}
301-
302-
// Produce baselines. The first gives the types for all expressions.
303-
// The second gives symbols for all identifiers.
304-
let e1: Error, e2: Error;
305-
try {
306-
checkBaseLines(/*isSymbolBaseLine*/ false);
307-
}
308-
catch (e) {
309-
e1 = e;
310-
}
311-
312-
try {
313-
checkBaseLines(/*isSymbolBaseLine*/ true);
314-
}
315-
catch (e) {
316-
e2 = e;
317-
}
318-
319-
if (e1 || e2) {
320-
throw e1 || e2;
321-
}
322-
323-
return;
324-
325-
function checkBaseLines(isSymbolBaseLine: boolean) {
326-
const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
327-
const pullBaseLine = generateBaseLine(pullResults, isSymbolBaseLine);
328-
329-
const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
330-
const pullExtension = isSymbolBaseLine ? ".symbols.pull" : ".types.pull";
331-
332-
if (fullBaseLine !== pullBaseLine) {
333-
Harness.Baseline.runBaseline(justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
334-
Harness.Baseline.runBaseline(justName.replace(/\.tsx?/, pullExtension), () => pullBaseLine);
335-
}
336-
else {
337-
Harness.Baseline.runBaseline(justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
338-
}
339-
}
340-
341-
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
342-
const typeLines: string[] = [];
343-
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
344-
345-
allFiles.forEach(file => {
346-
const codeLines = file.content.split("\n");
347-
typeWriterResults[file.unitName].forEach(result => {
348-
if (isSymbolBaseline && !result.symbol) {
349-
return;
350-
}
351-
352-
const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
353-
const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
354-
if (!typeMap[file.unitName]) {
355-
typeMap[file.unitName] = {};
356-
}
357-
358-
let typeInfo = [formattedLine];
359-
const existingTypeInfo = typeMap[file.unitName][result.line];
360-
if (existingTypeInfo) {
361-
typeInfo = existingTypeInfo.concat(typeInfo);
362-
}
363-
typeMap[file.unitName][result.line] = typeInfo;
364-
});
365-
366-
typeLines.push("=== " + file.unitName + " ===\r\n");
367-
for (let i = 0; i < codeLines.length; i++) {
368-
const currentCodeLine = codeLines[i];
369-
typeLines.push(currentCodeLine + "\r\n");
370-
if (typeMap[file.unitName]) {
371-
const typeInfo = typeMap[file.unitName][i];
372-
if (typeInfo) {
373-
typeInfo.forEach(ty => {
374-
typeLines.push(">" + ty + "\r\n");
375-
});
376-
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === "")) {
377-
}
378-
else {
379-
typeLines.push("\r\n");
380-
}
381-
}
382-
}
383-
else {
384-
typeLines.push("No type information for this code.");
385-
}
386-
}
387-
});
388-
389-
return typeLines.join("");
390-
}
391-
183+
Harness.Compiler.doTypeAndSymbolBaseline(justName, result, toBeCompiled.concat(otherFiles).filter(file => !!result.program.getSourceFile(file.unitName)));
392184
});
393185
});
394186
}

0 commit comments

Comments
 (0)