Merge pull request #1482 from Microsoft/typingHighFidelity
Move test helpers into the harness Utils module.
This commit is contained in:
commit
5237ed7bed
29 changed files with 172 additions and 296 deletions
2
Jakefile
2
Jakefile
|
@ -485,7 +485,7 @@ function deleteTemporaryProjectOutput() {
|
|||
}
|
||||
}
|
||||
|
||||
var testTimeout = 5000;
|
||||
var testTimeout = 20000;
|
||||
desc("Runs the tests using the built run.js file. Syntax is jake runtests. Optional parameters 'host=', 'tests=[regex], reporter=[list|spec|json|<more>]'.");
|
||||
task("runtests", ["tests", builtLocalDirectory], function() {
|
||||
cleanTestDirs();
|
||||
|
|
|
@ -96,19 +96,6 @@ module FourSlash {
|
|||
end: number;
|
||||
}
|
||||
|
||||
export enum IncrementalEditValidation {
|
||||
None,
|
||||
SyntacticOnly,
|
||||
Complete
|
||||
}
|
||||
|
||||
export enum TypingFidelity {
|
||||
/// Performs typing and formatting (if formatting is enabled)
|
||||
Low,
|
||||
/// Performs typing, checks completion lists, signature help, and formatting (if enabled)
|
||||
High
|
||||
}
|
||||
|
||||
var entityMap: ts.Map<string> = {
|
||||
'&': '&',
|
||||
'"': '"',
|
||||
|
@ -126,22 +113,22 @@ module FourSlash {
|
|||
// To add additional option, add property into the testOptMetadataNames, refer the property in either globalMetadataNames or fileMetadataNames
|
||||
// Add cases into convertGlobalOptionsToCompilationsSettings function for the compiler to acknowledge such option from meta data
|
||||
var testOptMetadataNames = {
|
||||
baselineFile: 'BaselineFile',
|
||||
declaration: 'declaration',
|
||||
emitThisFile: 'emitThisFile', // This flag is used for testing getEmitOutput feature. It allows test-cases to indicate what file to be output in multiple files project
|
||||
filename: 'Filename',
|
||||
mapRoot: 'mapRoot',
|
||||
module: 'module',
|
||||
out: 'out',
|
||||
outDir: 'outDir',
|
||||
sourceMap: 'sourceMap',
|
||||
sourceRoot: 'sourceRoot',
|
||||
resolveReference: 'ResolveReference', // This flag is used to specify entry file for resolve file references. The flag is only allow once per test file
|
||||
baselineFile: 'BaselineFile',
|
||||
declaration: 'declaration',
|
||||
emitThisFile: 'emitThisFile', // This flag is used for testing getEmitOutput feature. It allows test-cases to indicate what file to be output in multiple files project
|
||||
filename: 'Filename',
|
||||
mapRoot: 'mapRoot',
|
||||
module: 'module',
|
||||
out: 'out',
|
||||
outDir: 'outDir',
|
||||
sourceMap: 'sourceMap',
|
||||
sourceRoot: 'sourceRoot',
|
||||
resolveReference: 'ResolveReference', // This flag is used to specify entry file for resolve file references. The flag is only allow once per test file
|
||||
};
|
||||
|
||||
// List of allowed metadata names
|
||||
var fileMetadataNames = [testOptMetadataNames.filename, testOptMetadataNames.emitThisFile, testOptMetadataNames.resolveReference];
|
||||
var globalMetadataNames = [testOptMetadataNames.baselineFile, testOptMetadataNames.declaration,
|
||||
var globalMetadataNames = [testOptMetadataNames.baselineFile, testOptMetadataNames.declaration,
|
||||
testOptMetadataNames.mapRoot, testOptMetadataNames.module, testOptMetadataNames.out,
|
||||
testOptMetadataNames.outDir, testOptMetadataNames.sourceMap, testOptMetadataNames.sourceRoot]
|
||||
|
||||
|
@ -160,16 +147,16 @@ module FourSlash {
|
|||
case testOptMetadataNames.module:
|
||||
// create appropriate external module target for CompilationSettings
|
||||
switch (globalOptions[prop]) {
|
||||
case "AMD":
|
||||
settings.module = ts.ModuleKind.AMD;
|
||||
break;
|
||||
case "CommonJS":
|
||||
settings.module = ts.ModuleKind.CommonJS;
|
||||
break;
|
||||
default:
|
||||
ts.Debug.assert(globalOptions[prop] === undefined || globalOptions[prop] === "None");
|
||||
settings.module = ts.ModuleKind.None;
|
||||
break;
|
||||
case "AMD":
|
||||
settings.module = ts.ModuleKind.AMD;
|
||||
break;
|
||||
case "CommonJS":
|
||||
settings.module = ts.ModuleKind.CommonJS;
|
||||
break;
|
||||
default:
|
||||
ts.Debug.assert(globalOptions[prop] === undefined || globalOptions[prop] === "None");
|
||||
settings.module = ts.ModuleKind.None;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case testOptMetadataNames.out:
|
||||
|
@ -279,9 +266,6 @@ module FourSlash {
|
|||
|
||||
public cancellationToken: TestCancellationToken;
|
||||
|
||||
public editValidation = IncrementalEditValidation.Complete;
|
||||
public typingFidelity = TypingFidelity.Low;
|
||||
|
||||
private scenarioActions: string[] = [];
|
||||
private taoInvalidReason: string = null;
|
||||
|
||||
|
@ -771,7 +755,7 @@ module FourSlash {
|
|||
}
|
||||
|
||||
public verifyQuickInfoString(negative: boolean, expectedText?: string, expectedDocumentation?: string) {
|
||||
[expectedText, expectedDocumentation].forEach(str => {
|
||||
[expectedText, expectedDocumentation].forEach(str => {
|
||||
if (str) {
|
||||
this.scenarioActions.push('<ShowQuickInfo />');
|
||||
this.scenarioActions.push('<VerifyQuickInfoTextContains IgnoreSpacing="true" Text="' + escapeXmlAttributeValue(str) + '" ' + (negative ? 'ExpectsFailure="true"' : '') + ' />');
|
||||
|
@ -816,7 +800,7 @@ module FourSlash {
|
|||
result = "[\n ";
|
||||
}
|
||||
result += JSON.stringify(part);
|
||||
});
|
||||
});
|
||||
if (result) {
|
||||
result += "\n]";
|
||||
}
|
||||
|
@ -885,8 +869,8 @@ module FourSlash {
|
|||
|
||||
var help = this.getActiveSignatureHelpItem();
|
||||
assert.equal(
|
||||
ts.displayPartsToString(help.prefixDisplayParts) +
|
||||
help.parameters.map(p => ts.displayPartsToString(p.displayParts)).join(ts.displayPartsToString(help.separatorDisplayParts)) +
|
||||
ts.displayPartsToString(help.prefixDisplayParts) +
|
||||
help.parameters.map(p => ts.displayPartsToString(p.displayParts)).join(ts.displayPartsToString(help.separatorDisplayParts)) +
|
||||
ts.displayPartsToString(help.suffixDisplayParts), expected);
|
||||
}
|
||||
|
||||
|
@ -1233,11 +1217,6 @@ module FourSlash {
|
|||
ts.forEach(fileNames, Harness.IO.log);
|
||||
}
|
||||
|
||||
private editCheckpoint(filename: string) {
|
||||
// TODO: What's this for? It is being called by deleteChar
|
||||
// this.languageService.getScriptLexicalStructure(filename);
|
||||
}
|
||||
|
||||
public deleteChar(count = 1) {
|
||||
this.scenarioActions.push('<DeleteCharNext Count="' + count + '" />');
|
||||
|
||||
|
@ -1248,7 +1227,7 @@ module FourSlash {
|
|||
// Make the edit
|
||||
this.languageServiceShimHost.editScript(this.activeFile.fileName, offset, offset + 1, ch);
|
||||
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
this.checkPostEditInvariants();
|
||||
|
||||
// Handle post-keystroke formatting
|
||||
if (this.enableFormatting) {
|
||||
|
@ -1269,7 +1248,7 @@ module FourSlash {
|
|||
|
||||
this.languageServiceShimHost.editScript(this.activeFile.fileName, start, start + length, text);
|
||||
this.updateMarkersForEdit(this.activeFile.fileName, start, start + length, text);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
this.checkPostEditInvariants();
|
||||
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
|
@ -1285,13 +1264,13 @@ module FourSlash {
|
|||
// Make the edit
|
||||
this.languageServiceShimHost.editScript(this.activeFile.fileName, offset, offset + 1, ch);
|
||||
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
this.checkPostEditInvariants();
|
||||
|
||||
// Handle post-keystroke formatting
|
||||
if (this.enableFormatting) {
|
||||
var edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
|
||||
offset += this.applyEdits(this.activeFile.fileName, edits, true);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1299,7 +1278,6 @@ module FourSlash {
|
|||
this.currentCaretPosition = offset;
|
||||
|
||||
this.fixCaretPosition();
|
||||
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
|
||||
|
@ -1311,37 +1289,7 @@ module FourSlash {
|
|||
this.scenarioActions.push('<InsertText><![CDATA[' + text + ']]></InsertText>');
|
||||
}
|
||||
|
||||
if (this.typingFidelity === TypingFidelity.Low) {
|
||||
return this.typeLowFidelity(text);
|
||||
} else {
|
||||
return this.typeHighFidelity(text);
|
||||
}
|
||||
}
|
||||
|
||||
private typeLowFidelity(text: string) {
|
||||
var offset = this.currentCaretPosition;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
// Make the edit
|
||||
var ch = text.charAt(i);
|
||||
this.languageServiceShimHost.editScript(this.activeFile.fileName, offset, offset, ch);
|
||||
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, ch);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
offset++;
|
||||
|
||||
// Handle post-keystroke formatting
|
||||
if (this.enableFormatting) {
|
||||
var edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
|
||||
offset += this.applyEdits(this.activeFile.fileName, edits, true);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
}
|
||||
}
|
||||
|
||||
// Move the caret to wherever we ended up
|
||||
this.currentCaretPosition = offset;
|
||||
|
||||
this.fixCaretPosition();
|
||||
|
||||
this.checkPostEditInvariants();
|
||||
return this.typeHighFidelity(text);
|
||||
}
|
||||
|
||||
// Enters lines of text at the current caret position, invoking
|
||||
|
@ -1357,7 +1305,7 @@ module FourSlash {
|
|||
this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset);
|
||||
|
||||
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, ch);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
this.checkPostEditInvariants();
|
||||
offset++;
|
||||
|
||||
if (ch === '(' || ch === ',') {
|
||||
|
@ -1377,7 +1325,7 @@ module FourSlash {
|
|||
if (this.enableFormatting) {
|
||||
var edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions);
|
||||
offset += this.applyEdits(this.activeFile.fileName, edits, true);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1385,7 +1333,6 @@ module FourSlash {
|
|||
this.currentCaretPosition = offset;
|
||||
|
||||
this.fixCaretPosition();
|
||||
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
|
||||
|
@ -1397,14 +1344,14 @@ module FourSlash {
|
|||
var offset = this.currentCaretPosition;
|
||||
this.languageServiceShimHost.editScript(this.activeFile.fileName, offset, offset, text);
|
||||
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, text);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
this.checkPostEditInvariants();
|
||||
offset += text.length;
|
||||
|
||||
// Handle formatting
|
||||
if (this.enableFormatting) {
|
||||
var edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions);
|
||||
offset += this.applyEdits(this.activeFile.fileName, edits, true);
|
||||
this.editCheckpoint(this.activeFile.fileName);
|
||||
this.checkPostEditInvariants();
|
||||
}
|
||||
|
||||
// Move the caret to wherever we ended up
|
||||
|
@ -1415,11 +1362,9 @@ module FourSlash {
|
|||
}
|
||||
|
||||
private checkPostEditInvariants() {
|
||||
if (this.editValidation === IncrementalEditValidation.None) {
|
||||
return;
|
||||
}
|
||||
|
||||
var incrementalSourceFile = this.languageService.getSourceFile(this.activeFile.fileName);
|
||||
Utils.assertInvariants(incrementalSourceFile, /*parent:*/ undefined);
|
||||
|
||||
var incrementalSyntaxDiagnostics = JSON.stringify(Utils.convertDiagnostics(incrementalSourceFile.getSyntacticDiagnostics()));
|
||||
|
||||
// Check syntactic structure
|
||||
|
@ -1434,31 +1379,26 @@ module FourSlash {
|
|||
this.raiseError('Mismatched incremental/reference syntactic diagnostics for file ' + this.activeFile.fileName + '.\n=== Incremental diagnostics ===\n' + incrementalSyntaxDiagnostics + '\n=== Reference Diagnostics ===\n' + referenceSyntaxDiagnostics);
|
||||
}
|
||||
|
||||
var incrementalSourceFileJSON = Utils.sourceFileToJSON(incrementalSourceFile);
|
||||
var referenceSourceFileJSON = Utils.sourceFileToJSON(referenceSourceFile);
|
||||
Utils.assertStructuralEquals(incrementalSourceFile, referenceSourceFile);
|
||||
|
||||
if (incrementalSyntaxDiagnostics !== referenceSyntaxDiagnostics) {
|
||||
this.raiseError('Mismatched incremental/reference ast for file ' + this.activeFile.fileName + '.\n=== Incremental AST ===\n' + incrementalSourceFileJSON + '\n=== Reference AST ===\n' + referenceSourceFileJSON);
|
||||
}
|
||||
//if (this.editValidation !== IncrementalEditValidation.SyntacticOnly) {
|
||||
// var compiler = new TypeScript.TypeScriptCompiler();
|
||||
// for (var i = 0; i < this.testData.files.length; i++) {
|
||||
// snapshot = this.languageServiceShimHost.getScriptSnapshot(this.testData.files[i].fileName);
|
||||
// compiler.addFile(this.testData.files[i].fileName, TypeScript.ScriptSnapshot.fromString(snapshot.getText(0, snapshot.getLength())), ts.ByteOrderMark.None, 0, true);
|
||||
// }
|
||||
|
||||
//if (this.editValidation !== IncrementalEditValidation.SyntacticOnly) {
|
||||
// var compiler = new TypeScript.TypeScriptCompiler();
|
||||
// for (var i = 0; i < this.testData.files.length; i++) {
|
||||
// snapshot = this.languageServiceShimHost.getScriptSnapshot(this.testData.files[i].fileName);
|
||||
// compiler.addFile(this.testData.files[i].fileName, TypeScript.ScriptSnapshot.fromString(snapshot.getText(0, snapshot.getLength())), ts.ByteOrderMark.None, 0, true);
|
||||
// }
|
||||
// compiler.addFile('lib.d.ts', TypeScript.ScriptSnapshot.fromString(Harness.Compiler.libTextMinimal), ts.ByteOrderMark.None, 0, true);
|
||||
|
||||
// compiler.addFile('lib.d.ts', TypeScript.ScriptSnapshot.fromString(Harness.Compiler.libTextMinimal), ts.ByteOrderMark.None, 0, true);
|
||||
// for (var i = 0; i < this.testData.files.length; i++) {
|
||||
// var refSemanticErrs = JSON.stringify(compiler.getSemanticDiagnostics(this.testData.files[i].fileName));
|
||||
// var incrSemanticErrs = JSON.stringify(this.languageService.getSemanticDiagnostics(this.testData.files[i].fileName));
|
||||
|
||||
// for (var i = 0; i < this.testData.files.length; i++) {
|
||||
// var refSemanticErrs = JSON.stringify(compiler.getSemanticDiagnostics(this.testData.files[i].fileName));
|
||||
// var incrSemanticErrs = JSON.stringify(this.languageService.getSemanticDiagnostics(this.testData.files[i].fileName));
|
||||
|
||||
// if (incrSemanticErrs !== refSemanticErrs) {
|
||||
// this.raiseError('Mismatched incremental/full semantic errors for file ' + this.testData.files[i].fileName + '\n=== Incremental errors ===\n' + incrSemanticErrs + '\n=== Full Errors ===\n' + refSemanticErrs);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
// if (incrSemanticErrs !== refSemanticErrs) {
|
||||
// this.raiseError('Mismatched incremental/full semantic errors for file ' + this.testData.files[i].fileName + '\n=== Incremental errors ===\n' + incrSemanticErrs + '\n=== Full Errors ===\n' + refSemanticErrs);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
private fixCaretPosition() {
|
||||
|
@ -1714,8 +1654,8 @@ module FourSlash {
|
|||
private verifyClassifications(expected: { classificationType: string; text: string; textSpan?: TextSpan }[], actual: ts.ClassifiedSpan[]) {
|
||||
if (actual.length !== expected.length) {
|
||||
this.raiseError('verifyClassifications failed - expected total classifications to be ' + expected.length +
|
||||
', but was ' + actual.length +
|
||||
jsonMismatchString());
|
||||
', but was ' + actual.length +
|
||||
jsonMismatchString());
|
||||
}
|
||||
|
||||
for (var i = 0; i < expected.length; i++) {
|
||||
|
@ -1755,8 +1695,8 @@ module FourSlash {
|
|||
|
||||
function jsonMismatchString() {
|
||||
return ts.sys.newLine +
|
||||
"expected: '" + ts.sys.newLine + JSON.stringify(expected, (k,v) => v, 2) + "'" + ts.sys.newLine +
|
||||
"actual: '" + ts.sys.newLine + JSON.stringify(actual, (k, v) => v, 2) + "'";
|
||||
"expected: '" + ts.sys.newLine + JSON.stringify(expected,(k, v) => v, 2) + "'" + ts.sys.newLine +
|
||||
"actual: '" + ts.sys.newLine + JSON.stringify(actual,(k, v) => v, 2) + "'";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1768,7 +1708,7 @@ module FourSlash {
|
|||
}
|
||||
|
||||
public verifySyntacticClassifications(expected: { classificationType: string; text: string }[]) {
|
||||
var actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName,
|
||||
var actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName,
|
||||
new ts.TextSpan(0, this.activeFile.content.length));
|
||||
|
||||
this.verifyClassifications(expected, actual);
|
||||
|
@ -2650,4 +2590,4 @@ module FourSlash {
|
|||
fileName: fileName
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -290,6 +290,64 @@ module Utils {
|
|||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
export function assertStructuralEquals(node1: ts.Node, node2: ts.Node) {
|
||||
if (node1 === node2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(node1, "node1");
|
||||
assert(node2, "node2");
|
||||
assert.equal(node1.pos, node2.pos, "node1.pos !== node2.pos");
|
||||
assert.equal(node1.end, node2.end, "node1.end !== node2.end");
|
||||
assert.equal(node1.kind, node2.kind, "node1.kind !== node2.kind");
|
||||
assert.equal(node1.flags, node2.flags, "node1.flags !== node2.flags");
|
||||
|
||||
// call this on both nodes to ensure all propagated flags have been set (and thus can be
|
||||
// compared).
|
||||
assert.equal(ts.containsParseError(node1), ts.containsParseError(node2));
|
||||
assert.equal(node1.parserContextFlags, node2.parserContextFlags, "node1.parserContextFlags !== node2.parserContextFlags");
|
||||
|
||||
ts.forEachChild(node1,
|
||||
child1 => {
|
||||
var childName = findChildName(node1, child1);
|
||||
var child2: ts.Node = (<any>node2)[childName];
|
||||
|
||||
assertStructuralEquals(child1, child2);
|
||||
},
|
||||
(array1: ts.NodeArray<ts.Node>) => {
|
||||
var childName = findChildName(node1, array1);
|
||||
var array2: ts.NodeArray<ts.Node> = (<any>node2)[childName];
|
||||
|
||||
assertArrayStructuralEquals(array1, array2);
|
||||
});
|
||||
}
|
||||
|
||||
function assertArrayStructuralEquals(array1: ts.NodeArray<ts.Node>, array2: ts.NodeArray<ts.Node>) {
|
||||
if (array1 === array2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(array1, "array1");
|
||||
assert(array2, "array2");
|
||||
assert.equal(array1.pos, array2.pos, "array1.pos !== array2.pos");
|
||||
assert.equal(array1.end, array2.end, "array1.end !== array2.end");
|
||||
assert.equal(array1.length, array2.length, "array1.length !== array2.length");
|
||||
|
||||
for (var i = 0, n = array1.length; i < n; i++) {
|
||||
assertStructuralEquals(array1[i], array2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function findChildName(parent: any, child: any) {
|
||||
for (var name in parent) {
|
||||
if (parent.hasOwnProperty(name) && parent[name] === child) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Could not find child in parent");
|
||||
}
|
||||
}
|
||||
|
||||
module Harness.Path {
|
||||
|
@ -772,7 +830,7 @@ module Harness {
|
|||
writeFile,
|
||||
getCanonicalFileName,
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
getNewLine: ()=> ts.sys.newLine
|
||||
getNewLine: () => ts.sys.newLine
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -814,7 +872,7 @@ module Harness {
|
|||
}
|
||||
|
||||
public emitAll(ioHost?: IEmitterIOHost) {
|
||||
this.compileFiles(this.inputFiles, [], (result) => {
|
||||
this.compileFiles(this.inputFiles, [],(result) => {
|
||||
result.files.forEach(file => {
|
||||
ioHost.writeFile(file.fileName, file.code, false);
|
||||
});
|
||||
|
@ -824,7 +882,7 @@ module Harness {
|
|||
result.sourceMaps.forEach(file => {
|
||||
ioHost.writeFile(file.fileName, file.code, false);
|
||||
});
|
||||
}, () => { }, this.compileOptions);
|
||||
},() => { }, this.compileOptions);
|
||||
}
|
||||
|
||||
public compileFiles(inputFiles: { unitName: string; content: string }[],
|
||||
|
@ -962,7 +1020,7 @@ module Harness {
|
|||
break;
|
||||
|
||||
case 'includebuiltfile':
|
||||
inputFiles.push({ unitName: setting.value, content: IO.readFile(libFolder + setting.value)});
|
||||
inputFiles.push({ unitName: setting.value, content: IO.readFile(libFolder + setting.value) });
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1071,7 +1129,7 @@ module Harness {
|
|||
return ts.removeFileExtension(sourceFileName) + ".d.ts";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined);
|
||||
}
|
||||
|
||||
|
@ -1584,4 +1642,4 @@ module Harness {
|
|||
}
|
||||
|
||||
// TODO: not sure why Utils.evalFile isn't working with this, eventually will concat it like old compiler instead of eval
|
||||
eval(Harness.tcServicesFile);
|
||||
eval(Harness.tcServicesFile);
|
|
@ -9,7 +9,6 @@
|
|||
//// }
|
||||
|
||||
edit.disableFormatting();
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.SyntacticOnly);
|
||||
|
||||
goTo.marker('check');
|
||||
verify.quickInfoIs('module Mod');
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////module A {
|
||||
//// /*var*/
|
||||
////}
|
||||
////module /*check*/A {
|
||||
//// var p;
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.SyntacticOnly);
|
||||
|
||||
goTo.marker('check');
|
||||
verify.quickInfoExists();
|
||||
|
||||
goTo.marker('var');
|
||||
edit.insert('var o;');
|
||||
|
||||
goTo.marker('check');
|
||||
verify.quickInfoExists();
|
||||
|
||||
////}
|
||||
|
||||
goTo.marker('check');
|
||||
verify.quickInfoExists();
|
||||
|
||||
goTo.marker('var');
|
||||
edit.insert('var o;');
|
||||
|
||||
goTo.marker('check');
|
||||
verify.quickInfoExists();
|
||||
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
////second.start();
|
||||
////second.stop();
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
goTo.file("findAllRefsOnDefinition-import.ts");
|
||||
goTo.marker("1");
|
||||
|
||||
|
@ -38,4 +36,3 @@ verifyOperationIsCancelled(() => verify.referencesCountIs(0) );
|
|||
cancellation.resetCancelled();
|
||||
goTo.marker("1");
|
||||
verify.referencesCountIs(2);
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
// this line triggers a semantic/syntactic error check, remove line when 788570 is fixed
|
||||
edit.insert('');
|
||||
|
||||
diagnostics.setTypingFidelity(TypingFidelity.High);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.completionListContains('foo');
|
||||
verify.completionListContains('foo2');
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
// this line triggers a semantic/syntactic error check, remove line when 788570 is fixed
|
||||
edit.insert('');
|
||||
diagnostics.setTypingFidelity(TypingFidelity.High);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.completionListContains('foo');
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
//// var f4 = <T>(x: T/**/ ) => {
|
||||
//// }
|
||||
|
||||
// Turn off edit validation. We don't want semantic diagnostics to run until we explicit call it.
|
||||
fs.diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
fs.goTo.marker();
|
||||
|
||||
// Replace the "T" type with the non-existent type 'V'.
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
////var x = Object.create(/**/
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
goTo.marker();
|
||||
verify.not.completionListIsEmpty();
|
||||
edit.insert("nu");
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
//// }
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
verify.numberOfErrorsInCurrentFile(0);
|
||||
|
||||
// Edit and bind and resolve only var decl
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
////second.start();
|
||||
////second.stop();
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
goTo.file("findAllRefsOnDefinition-import.ts");
|
||||
goTo.marker("1");
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
////var start: Second.Test.start;
|
||||
////var stop: Second.Test.stop;
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
goTo.file("findAllRefsOnDefinition2-import.ts");
|
||||
goTo.marker("1");
|
||||
|
||||
|
|
|
@ -31,19 +31,6 @@
|
|||
|
||||
declare var FourSlash;
|
||||
|
||||
enum IncrementalEditValidation {
|
||||
None = FourSlash.IncrementalEditValidation.None,
|
||||
SyntacticOnly = FourSlash.IncrementalEditValidation.SyntacticOnly,
|
||||
Complete = FourSlash.IncrementalEditValidation.Complete
|
||||
}
|
||||
|
||||
enum TypingFidelity {
|
||||
/** Performs typing and formatting (if formatting is enabled) */
|
||||
Low = FourSlash.TypingFidelity.Low,
|
||||
/** Performs typing, checks completion lists, signature help, and formatting (if enabled) */
|
||||
High = FourSlash.TypingFidelity.High
|
||||
}
|
||||
|
||||
// Return code used by getEmitOutput function to indicate status of the function
|
||||
// It is a duplicate of the one in types.ts to expose it to testcases in fourslash
|
||||
enum EmitReturnStatus {
|
||||
|
@ -101,14 +88,6 @@ module FourSlashInterface {
|
|||
public validateTypesAtPositions(...positions: number[]) {
|
||||
return FourSlash.currentTestState.verifyTypesAgainstFullCheckAtPositions(positions);
|
||||
}
|
||||
|
||||
public setEditValidation(validation: IncrementalEditValidation) {
|
||||
FourSlash.currentTestState.editValidation = validation;
|
||||
}
|
||||
|
||||
public setTypingFidelity(fidelity: TypingFidelity) {
|
||||
FourSlash.currentTestState.typingFidelity = fidelity;
|
||||
}
|
||||
}
|
||||
|
||||
export class goTo {
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
////var bbb: string;
|
||||
/////*1*/
|
||||
|
||||
// Disable test triggered type check
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
goTo.marker("1");
|
||||
verify.completionListContains("aaa");
|
||||
verify.completionListContains("bbb");
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
/////*1*/
|
||||
////interface Foo {
|
||||
//// setISO8601(dString): Date;
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
////}
|
||||
|
||||
// Do resolve without typeCheck
|
||||
goTo.marker('1');
|
||||
|
@ -14,4 +12,4 @@ edit.insert("alert(");
|
|||
verify.currentSignatureHelpIs("alert(message?: any): void");
|
||||
|
||||
// TypeCheck
|
||||
verify.errorExistsAfterMarker('1');
|
||||
verify.errorExistsAfterMarker('1');
|
|
@ -20,7 +20,5 @@
|
|||
// Force a syntax tree ot be created.
|
||||
verify.noMatchingBracePositionInCurrentFile(0);
|
||||
|
||||
// make sure we check the tree after every edit.
|
||||
diagnostics.setTypingFidelity(TypingFidelity.High);
|
||||
goTo.marker('1');
|
||||
edit.insert('Fo');
|
||||
|
|
|
@ -9,10 +9,8 @@
|
|||
//// }
|
||||
////}
|
||||
////var val = new c1();
|
||||
////var b = val.p1;
|
||||
/////*1*/b;
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
////var b = val.p1;
|
||||
/////*1*/b;
|
||||
|
||||
// Resolve without typeCheck
|
||||
goTo.marker('1');
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
//// }
|
||||
////}
|
||||
////var val = new c1("hello");
|
||||
/////*1*/val;
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
/////*1*/val;
|
||||
|
||||
// Do resolve without typeCheck
|
||||
goTo.marker('1');
|
||||
|
|
|
@ -19,13 +19,10 @@
|
|||
//// });
|
||||
////}
|
||||
////var val = foo(["myString1", "myString2"]);
|
||||
/////*1*/val;
|
||||
/////*1*/val;
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
// Do resolve without typeCheck
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs("(var) val: string");
|
||||
|
||||
// TypeCheck
|
||||
verify.numberOfErrorsInCurrentFile(1);
|
||||
verify.numberOfErrorsInCurrentFile(1);
|
|
@ -16,7 +16,5 @@
|
|||
//// var /*1*/r4 = a(1, true);
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs("(var) r4: number");
|
||||
verify.quickInfoIs("(var) r4: number");
|
|
@ -12,8 +12,6 @@
|
|||
//// var r/*2*/4 = b.b/*1*/ar; // string
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs("(property) B<string>.bar: string", undefined);
|
||||
edit.deleteAtCaret(1);
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
//// var r = a.fo/*1*/o + a.bar;
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs("(property) M2.A.foo: string", undefined);
|
||||
verify.numberOfErrorsInCurrentFile(0);
|
|
@ -10,6 +10,5 @@
|
|||
////}
|
||||
////new class/*1*/InheritingSpecializedClass();
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
goTo.marker('1');
|
||||
verify.quickInfoExists();
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
// @Filename: signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles_file0.ts
|
||||
////declare function fn(x: string, y: number);
|
||||
|
||||
|
||||
// @Filename: signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles_file1.ts
|
||||
////declare function fn(x: string);
|
||||
|
||||
|
||||
// @Filename: signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles_file2.ts
|
||||
////fn(/*1*/
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
goTo.marker('1');
|
||||
////fn(/*1*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.signatureHelpCountIs(2);
|
|
@ -8,7 +8,6 @@
|
|||
//// }
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
goTo.marker("1");
|
||||
edit.insert("super(");
|
||||
verify.currentSignatureHelpIs("B(x: string): B");
|
|
@ -13,8 +13,6 @@
|
|||
//// }
|
||||
////
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.SyntacticOnly);
|
||||
|
||||
goTo.marker('addParam');
|
||||
|
||||
edit.insert(", X");
|
||||
|
|
|
@ -1,28 +1,25 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
/////*start*/class Point implements /*IPointRef*/IPoint {
|
||||
//// getDist() {
|
||||
//// ssss;
|
||||
//// }
|
||||
////}/*end*/
|
||||
|
||||
// make sure no typeCheck is triggered after edit
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
// Edit to invalidate the intial typeCheck state
|
||||
goTo.eof();
|
||||
edit.insertLine("");
|
||||
|
||||
// Attempt to resolve a symbol
|
||||
goTo.marker("IPointRef");
|
||||
verify.quickInfoIs(""); // not found
|
||||
|
||||
// trigger typecheck after the partial resolve, we should see errors
|
||||
verify.errorExistsAfterMarker("IPointRef");
|
||||
|
||||
goTo.eof();
|
||||
edit.insertLine("");
|
||||
|
||||
// one more time with full typecheck
|
||||
verify.errorExistsAfterMarker("IPointRef");
|
||||
|
||||
////}/*end*/
|
||||
|
||||
// Edit to invalidate the intial typeCheck state
|
||||
goTo.eof();
|
||||
edit.insertLine("");
|
||||
|
||||
// Attempt to resolve a symbol
|
||||
goTo.marker("IPointRef");
|
||||
verify.quickInfoIs(""); // not found
|
||||
|
||||
// trigger typecheck after the partial resolve, we should see errors
|
||||
verify.errorExistsAfterMarker("IPointRef");
|
||||
|
||||
goTo.eof();
|
||||
edit.insertLine("");
|
||||
|
||||
// one more time with full typecheck
|
||||
verify.errorExistsAfterMarker("IPointRef");
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ module ts {
|
|||
Utils.assertInvariants(incrementalNewTree, /*parent:*/ undefined);
|
||||
|
||||
// We should get the same tree when doign a full or incremental parse.
|
||||
assertStructuralEquals(newTree, incrementalNewTree);
|
||||
Utils.assertStructuralEquals(newTree, incrementalNewTree);
|
||||
|
||||
// There should be no reused nodes between two trees that are fully parsed.
|
||||
assert.isTrue(reusedElements(oldTree, newTree) === 0);
|
||||
|
@ -52,60 +52,6 @@ module ts {
|
|||
return incrementalNewTree;
|
||||
}
|
||||
|
||||
function assertStructuralEquals(node1: Node, node2: Node) {
|
||||
if (node1 === node2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(node1, "node1");
|
||||
assert(node2, "node2");
|
||||
assert.equal(node1.pos, node2.pos, "node1.pos !== node2.pos");
|
||||
assert.equal(node1.end, node2.end, "node1.end !== node2.end");
|
||||
assert.equal(node1.kind, node2.kind, "node1.kind !== node2.kind");
|
||||
assert.equal(node1.flags, node2.flags, "node1.flags !== node2.flags");
|
||||
assert.equal(node1.parserContextFlags, node2.parserContextFlags, "node1.parserContextFlags !== node2.parserContextFlags");
|
||||
|
||||
forEachChild(node1,
|
||||
child1 => {
|
||||
var childName = findChildName(node1, child1);
|
||||
var child2: Node = (<any>node2)[childName];
|
||||
|
||||
assertStructuralEquals(child1, child2);
|
||||
},
|
||||
(array1: NodeArray<Node>) => {
|
||||
var childName = findChildName(node1, array1);
|
||||
var array2: NodeArray<Node> = (<any>node2)[childName];
|
||||
|
||||
assertArrayStructuralEquals(array1, array2);
|
||||
});
|
||||
}
|
||||
|
||||
function assertArrayStructuralEquals(array1: NodeArray<Node>, array2: NodeArray<Node>) {
|
||||
if (array1 === array2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(array1, "array1");
|
||||
assert(array2, "array2");
|
||||
assert.equal(array1.pos, array2.pos, "array1.pos !== array2.pos");
|
||||
assert.equal(array1.end, array2.end, "array1.end !== array2.end");
|
||||
assert.equal(array1.length, array2.length, "array1.length !== array2.length");
|
||||
|
||||
for (var i = 0, n = array1.length; i < n; i++) {
|
||||
assertStructuralEquals(array1[i], array2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function findChildName(parent: any, child: any) {
|
||||
for (var name in parent) {
|
||||
if (parent.hasOwnProperty(name) && parent[name] === child) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Could not find child in parent");
|
||||
}
|
||||
|
||||
function reusedElements(oldNode: SourceFile, newNode: SourceFile): number {
|
||||
var allOldElements = collectElements(oldNode);
|
||||
var allNewElements = collectElements(newNode);
|
||||
|
|
Loading…
Reference in a new issue