Speed up fourslash tests

This commit is contained in:
Ryan Cavanaugh 2016-08-08 13:15:25 -07:00
parent f6a850b988
commit ce7f554090

View file

@ -249,6 +249,7 @@ namespace FourSlash {
if (compilationOptions.typeRoots) {
compilationOptions.typeRoots = compilationOptions.typeRoots.map(p => ts.getNormalizedAbsolutePath(p, this.basePath));
}
compilationOptions.skipDefaultLibCheck = true;
const languageServiceAdapter = this.getLanguageServiceAdapter(testType, this.cancellationToken, compilationOptions);
this.languageServiceAdapterHost = languageServiceAdapter.getHost();
@ -376,7 +377,7 @@ namespace FourSlash {
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) {
const startMarker = this.getMarkerByName(startMarkerName);
const endMarker = this.getMarkerByName(endMarkerName);
const predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
const predicate = function(errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
return ((errorMinChar === startPos) && (errorLimChar === endPos)) ? true : false;
};
@ -428,12 +429,12 @@ namespace FourSlash {
let predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean;
if (after) {
predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
predicate = function(errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
return ((errorMinChar >= startPos) && (errorLimChar >= startPos)) ? true : false;
};
}
else {
predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
predicate = function(errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) {
return ((errorMinChar <= startPos) && (errorLimChar <= startPos)) ? true : false;
};
}
@ -458,7 +459,7 @@ namespace FourSlash {
endPos = endMarker.position;
}
errors.forEach(function (error: ts.Diagnostic) {
errors.forEach(function(error: ts.Diagnostic) {
if (predicate(error.start, error.start + error.length, startPos, endPos)) {
exists = true;
}
@ -475,7 +476,7 @@ namespace FourSlash {
Harness.IO.log("Unexpected error(s) found. Error list is:");
}
errors.forEach(function (error: ts.Diagnostic) {
errors.forEach(function(error: ts.Diagnostic) {
Harness.IO.log(" minChar: " + error.start +
", limChar: " + (error.start + error.length) +
", message: " + ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine()) + "\n");
@ -1348,14 +1349,7 @@ namespace FourSlash {
}
// Enters lines of text at the current caret position
public type(text: string) {
return this.typeHighFidelity(text);
}
// Enters lines of text at the current caret position, invoking
// language service APIs to mimic Visual Studio's behavior
// as much as possible
private typeHighFidelity(text: string) {
public type(text: string, highFidelity = false) {
let offset = this.currentCaretPosition;
const prevChar = " ";
const checkCadence = (text.length >> 2) + 1;
@ -1364,24 +1358,26 @@ namespace FourSlash {
// Make the edit
const ch = text.charAt(i);
this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset, ch);
this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset);
if (highFidelity) {
this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset);
}
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, ch);
offset++;
if (ch === "(" || ch === ",") {
/* Signature help*/
this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset);
}
else if (prevChar === " " && /A-Za-z_/.test(ch)) {
/* Completions */
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset);
}
if (highFidelity) {
if (ch === "(" || ch === ",") {
/* Signature help*/
this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset);
}
else if (prevChar === " " && /A-Za-z_/.test(ch)) {
/* Completions */
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset);
}
if (i % checkCadence === 0) {
this.checkPostEditInvariants();
// this.languageService.getSyntacticDiagnostics(this.activeFile.fileName);
// this.languageService.getSemanticDiagnostics(this.activeFile.fileName);
if (i % checkCadence === 0) {
this.checkPostEditInvariants();
}
}
// Handle post-keystroke formatting
@ -1389,14 +1385,12 @@ namespace FourSlash {
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
// this.checkPostEditInvariants();
}
}
}
// Move the caret to wherever we ended up
this.currentCaretPosition = offset;
this.fixCaretPosition();
this.checkPostEditInvariants();
}
@ -1415,7 +1409,6 @@ namespace FourSlash {
const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions);
if (edits.length) {
offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
this.checkPostEditInvariants();
}
}
@ -1433,20 +1426,22 @@ namespace FourSlash {
return;
}
const incrementalSourceFile = this.languageService.getNonBoundSourceFile(this.activeFile.fileName);
Utils.assertInvariants(incrementalSourceFile, /*parent:*/ undefined);
if (1 + 1 === 2) {
const incrementalSourceFile = this.languageService.getNonBoundSourceFile(this.activeFile.fileName);
Utils.assertInvariants(incrementalSourceFile, /*parent:*/ undefined);
const incrementalSyntaxDiagnostics = incrementalSourceFile.parseDiagnostics;
const incrementalSyntaxDiagnostics = incrementalSourceFile.parseDiagnostics;
// Check syntactic structure
const content = this.getFileContent(this.activeFile.fileName);
// Check syntactic structure
const content = this.getFileContent(this.activeFile.fileName);
const referenceSourceFile = ts.createLanguageServiceSourceFile(
this.activeFile.fileName, createScriptSnapShot(content), ts.ScriptTarget.Latest, /*version:*/ "0", /*setNodeParents:*/ false);
const referenceSyntaxDiagnostics = referenceSourceFile.parseDiagnostics;
const referenceSourceFile = ts.createLanguageServiceSourceFile(
this.activeFile.fileName, createScriptSnapShot(content), ts.ScriptTarget.Latest, /*version:*/ "0", /*setNodeParents:*/ false);
const referenceSyntaxDiagnostics = referenceSourceFile.parseDiagnostics;
Utils.assertDiagnosticsEquals(incrementalSyntaxDiagnostics, referenceSyntaxDiagnostics);
Utils.assertStructuralEquals(incrementalSourceFile, referenceSourceFile);
Utils.assertDiagnosticsEquals(incrementalSyntaxDiagnostics, referenceSyntaxDiagnostics);
Utils.assertStructuralEquals(incrementalSourceFile, referenceSourceFile);
}
}
private fixCaretPosition() {
@ -2269,40 +2264,8 @@ namespace FourSlash {
export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void {
// Parse out the files and their metadata
const testData = parseTestData(basePath, content, fileName);
const state = new TestState(basePath, testType, testData);
let result = "";
const fourslashFile: Harness.Compiler.TestFile = {
unitName: Harness.Compiler.fourslashFileName,
content: undefined,
};
const testFile: Harness.Compiler.TestFile = {
unitName: fileName,
content: content
};
const host = Harness.Compiler.createCompilerHost(
[fourslashFile, testFile],
(fn, contents) => result = contents,
ts.ScriptTarget.Latest,
Harness.IO.useCaseSensitiveFileNames(),
Harness.IO.getCurrentDirectory());
const program = ts.createProgram([Harness.Compiler.fourslashFileName, fileName], { outFile: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host);
const sourceFile = host.getSourceFile(fileName, ts.ScriptTarget.ES3);
const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);
if (diagnostics.length > 0) {
throw new Error(`Error compiling ${fileName}: ` +
diagnostics.map(e => ts.flattenDiagnosticMessageText(e.messageText, Harness.IO.newLine())).join("\r\n"));
}
program.emit(sourceFile);
ts.Debug.assert(!!result);
runCode(result, state);
runCode(ts.transpile(content), state);
}
function runCode(code: string, state: TestState): void {