From ea3e509154efd42fc30c5198c34aefe229aa02e2 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 12 Dec 2014 15:29:52 -0800 Subject: [PATCH 01/13] Make utility mehtod names clearer. --- src/compiler/types.ts | 10 ++++------ src/compiler/utilities.ts | 17 ++++++++++------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 2c5376e744f..48288628a17 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -325,14 +325,12 @@ module ts { // Context flags computed by aggregating child flags upwards. - // If this node, or any of it's children (transitively) contain an error. + // Used during incremental parsing to determine if this node or any of its children had an + // error. Computed only once and then cached. ThisNodeOrAnySubNodesHasError = 1 << 5, - // Used during incremental parsing to determine if we need to visit this node to see if - // any of its children had an error. Once we compute that once, we can set this bit on the - // node to know that we never have to do it again. From that point on, we can just check - // the node directly for 'ContainsError'. - HasComputedThisNodeOrAnySubNodesHasError = 1 << 6 + // Used to know if we've computed data from children and cached it in this node. + HasAggregatedChildData = 1 << 6 } export interface Node extends TextRange { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index d35364009b6..8e0a02b2be6 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -62,31 +62,34 @@ module ts { return node.end - node.pos; } - export function hasFlag(val: number, flag: number): boolean { + function hasFlag(val: number, flag: number): boolean { return (val & flag) !== 0; } // Returns true if this node contains a parse error anywhere underneath it. export function containsParseError(node: Node): boolean { - if (!hasFlag(node.parserContextFlags, ParserContextFlags.HasComputedThisNodeOrAnySubNodesHasError)) { + aggregateChildData(node); + return hasFlag(node.parserContextFlags, ParserContextFlags.ThisNodeOrAnySubNodesHasError); + } + + function aggregateChildData(node: Node): void { + if (!hasFlag(node.parserContextFlags, ParserContextFlags.HasAggregatedChildData)) { // A node is considered to contain a parse error if: // a) the parser explicitly marked that it had an error // b) any of it's children reported that it had an error. - var val = hasFlag(node.parserContextFlags, ParserContextFlags.ThisNodeHasError) || + var thisNodeOrAnySubNodesHasError = hasFlag(node.parserContextFlags, ParserContextFlags.ThisNodeHasError) || forEachChild(node, containsParseError); // If so, mark ourselves accordingly. - if (val) { + if (thisNodeOrAnySubNodesHasError) { node.parserContextFlags |= ParserContextFlags.ThisNodeOrAnySubNodesHasError; } // Also mark that we've propogated the child information to this node. This way we can // always consult the bit directly on this node without needing to check its children // again. - node.parserContextFlags |= ParserContextFlags.HasComputedThisNodeOrAnySubNodesHasError; + node.parserContextFlags |= ParserContextFlags.HasAggregatedChildData; } - - return hasFlag(node.parserContextFlags, ParserContextFlags.ThisNodeOrAnySubNodesHasError); } export function getSourceFileOfNode(node: Node): SourceFile { From f5d622f0c912c2b8857dec246cf3487ed9f19ba8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 10:57:34 -0800 Subject: [PATCH 02/13] Move test helpers into the harness Utils module. --- src/harness/harness.ts | 54 +++++++++++++++++++++ tests/cases/unittests/incrementalParser.ts | 56 +--------------------- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 64d8b87350d..edc0aa49025 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -290,6 +290,60 @@ 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"); + assert.equal(node1.parserContextFlags, node2.parserContextFlags, "node1.parserContextFlags !== node2.parserContextFlags"); + + ts.forEachChild(node1, + child1 => { + var childName = findChildName(node1, child1); + var child2: ts.Node = (node2)[childName]; + + assertStructuralEquals(child1, child2); + }, + (array1: ts.NodeArray) => { + var childName = findChildName(node1, array1); + var array2: ts.NodeArray = (node2)[childName]; + + assertArrayStructuralEquals(array1, array2); + }); + } + + function assertArrayStructuralEquals(array1: ts.NodeArray, array2: ts.NodeArray) { + 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 { diff --git a/tests/cases/unittests/incrementalParser.ts b/tests/cases/unittests/incrementalParser.ts index 74b67810d26..e89f35aa93f 100644 --- a/tests/cases/unittests/incrementalParser.ts +++ b/tests/cases/unittests/incrementalParser.ts @@ -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 = (node2)[childName]; - - assertStructuralEquals(child1, child2); - }, - (array1: NodeArray) => { - var childName = findChildName(node1, array1); - var array2: NodeArray = (node2)[childName]; - - assertArrayStructuralEquals(array1, array2); - }); - } - - function assertArrayStructuralEquals(array1: NodeArray, array2: NodeArray) { - 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); From bd4aed25da30995abcc5969ad7d14d9c6dd869a5 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 11:16:50 -0800 Subject: [PATCH 03/13] Don't convert the tree to JSON before checking it. Just check it directly. --- src/harness/fourslash.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 18d34e94b03..69bc2962625 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1434,12 +1434,7 @@ 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); - - if (incrementalSyntaxDiagnostics !== referenceSyntaxDiagnostics) { - this.raiseError('Mismatched incremental/reference ast for file ' + this.activeFile.fileName + '.\n=== Incremental AST ===\n' + incrementalSourceFileJSON + '\n=== Reference AST ===\n' + referenceSourceFileJSON); - } + Utils.assertStructuralEquals(incrementalSourceFile, referenceSourceFile); //if (this.editValidation !== IncrementalEditValidation.SyntacticOnly) { // var compiler = new TypeScript.TypeScriptCompiler(); From 6d9bfda3e522dec09bc5d657b2679c30817e6080 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 11:20:50 -0800 Subject: [PATCH 04/13] Check post edit invariants after every edit. --- src/harness/fourslash.ts | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 69bc2962625..5b55f731376 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1233,11 +1233,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(''); @@ -1248,7 +1243,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 +1264,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 +1280,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 +1294,6 @@ module FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInvariants(); } @@ -1325,14 +1319,16 @@ module FourSlash { 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); + this.checkPostEditInvariants(); 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); + if (edits.length) { + offset += this.applyEdits(this.activeFile.fileName, edits, true); + this.checkPostEditInvariants(); + } } } @@ -1340,7 +1336,6 @@ module FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInvariants(); } @@ -1357,7 +1352,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 +1372,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(); } } @@ -1397,14 +1392,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 From 0e01e48d0e1af1d46898c66cd1f59a5998ab3f7d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 11:34:15 -0800 Subject: [PATCH 05/13] Always run all fourslash tests in high fidelity typing mode. We want to verify after every edit that our incremental data is correct. --- src/harness/fourslash.ts | 54 +------------------ tests/cases/fourslash/addMemberToInterface.ts | 1 - tests/cases/fourslash/addMemberToModule.ts | 28 +++++----- ...cellationWhenfindingAllRefsOnDefinition.ts | 3 -- tests/cases/fourslash/cloduleAsBaseClass.ts | 2 - tests/cases/fourslash/cloduleAsBaseClass2.ts | 1 - ...foreSemanticDiagnosticsInArrowFunction1.ts | 3 -- .../fourslash/completionEntryForPrimitive.ts | 1 - ...ariableDeclOfMergedVariableAndClassDecl.ts | 2 - .../fourslash/findAllRefsOnDefinition.ts | 2 - .../fourslash/findAllRefsOnDefinition2.ts | 2 - tests/cases/fourslash/fourslash.ts | 21 -------- .../fourslash/getCompletionEntryDetails.ts | 3 -- ...tionExpressionAboveInterfaceDeclaration.ts | 6 +-- tests/cases/fourslash/incrementalParsing1.ts | 2 - .../fourslash/incrementalResolveAccessor.ts | 6 +-- ...ncrementalResolveConstructorDeclaration.ts | 4 +- ...mentalResolveFunctionPropertyAssignment.ts | 7 +-- .../fourslash/quickInfoOnMergedInterfaces.ts | 4 +- ...oOnMergedInterfacesWithIncrementalEdits.ts | 2 - .../fourslash/quickInfoOnMergedModule.ts | 2 - ...nfoOnUnResolvedBaseConstructorSignature.ts | 1 - ...allOnFunctionDeclarationInMultipleFiles.ts | 11 ++-- ...ureHelpOnSuperWhenMembersAreNotResolved.ts | 1 - .../typeCheckAfterAddingGenericParameter.ts | 2 - .../cases/fourslash/typeCheckAfterResolve.ts | 45 ++++++++-------- 26 files changed, 48 insertions(+), 168 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 5b55f731376..0eca1981292 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -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 = { '&': '&', '"': '"', @@ -279,9 +266,6 @@ module FourSlash { public cancellationToken: TestCancellationToken; - public editValidation = IncrementalEditValidation.Complete; - public typingFidelity = TypingFidelity.Low; - private scenarioActions: string[] = []; private taoInvalidReason: string = null; @@ -1305,38 +1289,7 @@ module FourSlash { this.scenarioActions.push(''); } - 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.checkPostEditInvariants(); - offset++; - - // Handle post-keystroke formatting - if (this.enableFormatting) { - var edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); - if (edits.length) { - offset += this.applyEdits(this.activeFile.fileName, edits, true); - this.checkPostEditInvariants(); - } - } - } - - // 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 @@ -1380,7 +1333,6 @@ module FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInvariants(); } @@ -1410,10 +1362,6 @@ module FourSlash { } private checkPostEditInvariants() { - if (this.editValidation === IncrementalEditValidation.None) { - return; - } - var incrementalSourceFile = this.languageService.getSourceFile(this.activeFile.fileName); var incrementalSyntaxDiagnostics = JSON.stringify(Utils.convertDiagnostics(incrementalSourceFile.getSyntacticDiagnostics())); diff --git a/tests/cases/fourslash/addMemberToInterface.ts b/tests/cases/fourslash/addMemberToInterface.ts index e961c6a0cb3..cc0ecbdb361 100644 --- a/tests/cases/fourslash/addMemberToInterface.ts +++ b/tests/cases/fourslash/addMemberToInterface.ts @@ -9,7 +9,6 @@ //// } edit.disableFormatting(); -diagnostics.setEditValidation(IncrementalEditValidation.SyntacticOnly); goTo.marker('check'); verify.quickInfoIs('module Mod'); diff --git a/tests/cases/fourslash/addMemberToModule.ts b/tests/cases/fourslash/addMemberToModule.ts index 6b0e0d0eef5..b67d1827a41 100644 --- a/tests/cases/fourslash/addMemberToModule.ts +++ b/tests/cases/fourslash/addMemberToModule.ts @@ -1,20 +1,18 @@ -/// - +/// + ////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(); + diff --git a/tests/cases/fourslash/cancellationWhenfindingAllRefsOnDefinition.ts b/tests/cases/fourslash/cancellationWhenfindingAllRefsOnDefinition.ts index 0ec7c9bcf25..09f580bb965 100644 --- a/tests/cases/fourslash/cancellationWhenfindingAllRefsOnDefinition.ts +++ b/tests/cases/fourslash/cancellationWhenfindingAllRefsOnDefinition.ts @@ -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); - diff --git a/tests/cases/fourslash/cloduleAsBaseClass.ts b/tests/cases/fourslash/cloduleAsBaseClass.ts index c1ecc4aa44b..19bd3bb53e3 100644 --- a/tests/cases/fourslash/cloduleAsBaseClass.ts +++ b/tests/cases/fourslash/cloduleAsBaseClass.ts @@ -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'); diff --git a/tests/cases/fourslash/cloduleAsBaseClass2.ts b/tests/cases/fourslash/cloduleAsBaseClass2.ts index 775b00939f3..be2072afc43 100644 --- a/tests/cases/fourslash/cloduleAsBaseClass2.ts +++ b/tests/cases/fourslash/cloduleAsBaseClass2.ts @@ -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'); diff --git a/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts b/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts index bc0aa713880..16d2efcd6d4 100644 --- a/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts +++ b/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts @@ -3,9 +3,6 @@ //// var f4 = (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'. diff --git a/tests/cases/fourslash/completionEntryForPrimitive.ts b/tests/cases/fourslash/completionEntryForPrimitive.ts index c749379c862..9562e879266 100644 --- a/tests/cases/fourslash/completionEntryForPrimitive.ts +++ b/tests/cases/fourslash/completionEntryForPrimitive.ts @@ -2,7 +2,6 @@ ////var x = Object.create(/**/ -diagnostics.setEditValidation(IncrementalEditValidation.None); goTo.marker(); verify.not.completionListIsEmpty(); edit.insert("nu"); diff --git a/tests/cases/fourslash/errorsAfterResolvingVariableDeclOfMergedVariableAndClassDecl.ts b/tests/cases/fourslash/errorsAfterResolvingVariableDeclOfMergedVariableAndClassDecl.ts index 9287414584e..58cddff3dfb 100644 --- a/tests/cases/fourslash/errorsAfterResolvingVariableDeclOfMergedVariableAndClassDecl.ts +++ b/tests/cases/fourslash/errorsAfterResolvingVariableDeclOfMergedVariableAndClassDecl.ts @@ -10,8 +10,6 @@ //// } ////} -diagnostics.setEditValidation(IncrementalEditValidation.None); - verify.numberOfErrorsInCurrentFile(0); // Edit and bind and resolve only var decl diff --git a/tests/cases/fourslash/findAllRefsOnDefinition.ts b/tests/cases/fourslash/findAllRefsOnDefinition.ts index b1a7552c8d0..34144b74899 100644 --- a/tests/cases/fourslash/findAllRefsOnDefinition.ts +++ b/tests/cases/fourslash/findAllRefsOnDefinition.ts @@ -23,8 +23,6 @@ ////second.start(); ////second.stop(); -diagnostics.setEditValidation(IncrementalEditValidation.None); - goTo.file("findAllRefsOnDefinition-import.ts"); goTo.marker("1"); diff --git a/tests/cases/fourslash/findAllRefsOnDefinition2.ts b/tests/cases/fourslash/findAllRefsOnDefinition2.ts index 2b1d1668bb2..1c03d392e4d 100644 --- a/tests/cases/fourslash/findAllRefsOnDefinition2.ts +++ b/tests/cases/fourslash/findAllRefsOnDefinition2.ts @@ -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"); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 85197dd3ccb..f5a582868e5 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -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 { diff --git a/tests/cases/fourslash/getCompletionEntryDetails.ts b/tests/cases/fourslash/getCompletionEntryDetails.ts index 47465464576..078e84cf553 100644 --- a/tests/cases/fourslash/getCompletionEntryDetails.ts +++ b/tests/cases/fourslash/getCompletionEntryDetails.ts @@ -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"); diff --git a/tests/cases/fourslash/incrementalEditInvocationExpressionAboveInterfaceDeclaration.ts b/tests/cases/fourslash/incrementalEditInvocationExpressionAboveInterfaceDeclaration.ts index 8a06efbaa44..78152983dfd 100644 --- a/tests/cases/fourslash/incrementalEditInvocationExpressionAboveInterfaceDeclaration.ts +++ b/tests/cases/fourslash/incrementalEditInvocationExpressionAboveInterfaceDeclaration.ts @@ -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'); \ No newline at end of file diff --git a/tests/cases/fourslash/incrementalParsing1.ts b/tests/cases/fourslash/incrementalParsing1.ts index 4d9078bf10c..e09e96c9e0d 100644 --- a/tests/cases/fourslash/incrementalParsing1.ts +++ b/tests/cases/fourslash/incrementalParsing1.ts @@ -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'); diff --git a/tests/cases/fourslash/incrementalResolveAccessor.ts b/tests/cases/fourslash/incrementalResolveAccessor.ts index 92c00f353c8..812146398f1 100644 --- a/tests/cases/fourslash/incrementalResolveAccessor.ts +++ b/tests/cases/fourslash/incrementalResolveAccessor.ts @@ -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'); diff --git a/tests/cases/fourslash/incrementalResolveConstructorDeclaration.ts b/tests/cases/fourslash/incrementalResolveConstructorDeclaration.ts index fd0c9efd8ab..3eb51631244 100644 --- a/tests/cases/fourslash/incrementalResolveConstructorDeclaration.ts +++ b/tests/cases/fourslash/incrementalResolveConstructorDeclaration.ts @@ -7,9 +7,7 @@ //// } ////} ////var val = new c1("hello"); -/////*1*/val; - -diagnostics.setEditValidation(IncrementalEditValidation.None); +/////*1*/val; // Do resolve without typeCheck goTo.marker('1'); diff --git a/tests/cases/fourslash/incrementalResolveFunctionPropertyAssignment.ts b/tests/cases/fourslash/incrementalResolveFunctionPropertyAssignment.ts index 0799279c6e7..c7a9c28c574 100644 --- a/tests/cases/fourslash/incrementalResolveFunctionPropertyAssignment.ts +++ b/tests/cases/fourslash/incrementalResolveFunctionPropertyAssignment.ts @@ -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); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoOnMergedInterfaces.ts b/tests/cases/fourslash/quickInfoOnMergedInterfaces.ts index 7d6e7ef3f2d..a8e6e292d44 100644 --- a/tests/cases/fourslash/quickInfoOnMergedInterfaces.ts +++ b/tests/cases/fourslash/quickInfoOnMergedInterfaces.ts @@ -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"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoOnMergedInterfacesWithIncrementalEdits.ts b/tests/cases/fourslash/quickInfoOnMergedInterfacesWithIncrementalEdits.ts index 5f6b3483084..c08c16f1b66 100644 --- a/tests/cases/fourslash/quickInfoOnMergedInterfacesWithIncrementalEdits.ts +++ b/tests/cases/fourslash/quickInfoOnMergedInterfacesWithIncrementalEdits.ts @@ -12,8 +12,6 @@ //// var r/*2*/4 = b.b/*1*/ar; // string ////} -diagnostics.setEditValidation(IncrementalEditValidation.None); - goTo.marker('1'); verify.quickInfoIs("(property) B.bar: string", undefined); edit.deleteAtCaret(1); diff --git a/tests/cases/fourslash/quickInfoOnMergedModule.ts b/tests/cases/fourslash/quickInfoOnMergedModule.ts index abf12a65dbf..d9682832349 100644 --- a/tests/cases/fourslash/quickInfoOnMergedModule.ts +++ b/tests/cases/fourslash/quickInfoOnMergedModule.ts @@ -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); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoOnUnResolvedBaseConstructorSignature.ts b/tests/cases/fourslash/quickInfoOnUnResolvedBaseConstructorSignature.ts index 224803110b0..d76f9906df5 100644 --- a/tests/cases/fourslash/quickInfoOnUnResolvedBaseConstructorSignature.ts +++ b/tests/cases/fourslash/quickInfoOnUnResolvedBaseConstructorSignature.ts @@ -10,6 +10,5 @@ ////} ////new class/*1*/InheritingSpecializedClass(); -diagnostics.setEditValidation(IncrementalEditValidation.None); goTo.marker('1'); verify.quickInfoExists(); \ No newline at end of file diff --git a/tests/cases/fourslash/signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles.ts b/tests/cases/fourslash/signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles.ts index 2339af02529..846c2d5244a 100644 --- a/tests/cases/fourslash/signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles.ts +++ b/tests/cases/fourslash/signatureHelpInFunctionCallOnFunctionDeclarationInMultipleFiles.ts @@ -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); \ No newline at end of file diff --git a/tests/cases/fourslash/signatureHelpOnSuperWhenMembersAreNotResolved.ts b/tests/cases/fourslash/signatureHelpOnSuperWhenMembersAreNotResolved.ts index 5613ca71a70..dcb14635101 100644 --- a/tests/cases/fourslash/signatureHelpOnSuperWhenMembersAreNotResolved.ts +++ b/tests/cases/fourslash/signatureHelpOnSuperWhenMembersAreNotResolved.ts @@ -8,7 +8,6 @@ //// } ////} -diagnostics.setEditValidation(IncrementalEditValidation.None); goTo.marker("1"); edit.insert("super("); verify.currentSignatureHelpIs("B(x: string): B"); \ No newline at end of file diff --git a/tests/cases/fourslash/typeCheckAfterAddingGenericParameter.ts b/tests/cases/fourslash/typeCheckAfterAddingGenericParameter.ts index 3ee2b00fe35..e2e978dd7ea 100644 --- a/tests/cases/fourslash/typeCheckAfterAddingGenericParameter.ts +++ b/tests/cases/fourslash/typeCheckAfterAddingGenericParameter.ts @@ -13,8 +13,6 @@ //// } //// -diagnostics.setEditValidation(IncrementalEditValidation.SyntacticOnly); - goTo.marker('addParam'); edit.insert(", X"); diff --git a/tests/cases/fourslash/typeCheckAfterResolve.ts b/tests/cases/fourslash/typeCheckAfterResolve.ts index 21ea8f88356..788721c072e 100644 --- a/tests/cases/fourslash/typeCheckAfterResolve.ts +++ b/tests/cases/fourslash/typeCheckAfterResolve.ts @@ -1,28 +1,25 @@ -/// - +/// + /////*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"); + From 2bb0eb604bb95db67aaf55f800a228207a75d95a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 12:04:18 -0800 Subject: [PATCH 06/13] Ensure the 'hasParseErrors' bit is the same between trees. --- src/harness/harness.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index edc0aa49025..471261ef1f2 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -302,6 +302,10 @@ module Utils { 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, From b4a21686c17b618c9c249dc4e104990269ea1559 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 12:22:36 -0800 Subject: [PATCH 07/13] Remove calls to "debugger;" in our fourslash tests. --- tests/cases/fourslash/autoFormattingOnPasting.ts | 1 - tests/cases/fourslash/commentsFunction.ts | 1 - .../fourslash/findAllRefsWithShorthandPropertyAssignment2.ts | 3 +-- tests/cases/fourslash/forceIndentAfterNewLineInsert.ts | 2 -- tests/cases/fourslash/getEmitOutputWithDeclarationFile.ts | 1 - tests/cases/fourslash/getEmitOutputWithDeclarationFile2.ts | 1 - tests/cases/fourslash/getEmitOutputWithDeclarationFile3.ts | 1 - tests/cases/fourslash/localFunction.ts | 1 - tests/cases/fourslash/multilineCommentBeforeOpenBrace.ts | 2 +- tests/cases/fourslash/spaceAfterReturn.ts | 2 +- 10 files changed, 3 insertions(+), 12 deletions(-) diff --git a/tests/cases/fourslash/autoFormattingOnPasting.ts b/tests/cases/fourslash/autoFormattingOnPasting.ts index 98efcc02ab3..cee2be4bec8 100644 --- a/tests/cases/fourslash/autoFormattingOnPasting.ts +++ b/tests/cases/fourslash/autoFormattingOnPasting.ts @@ -3,7 +3,6 @@ ////module TestModule { /////**/ ////} -debugger; goTo.marker(""); edit.paste(" class TestClass{\r\n\ private foo;\r\n\ diff --git a/tests/cases/fourslash/commentsFunction.ts b/tests/cases/fourslash/commentsFunction.ts index 3af718fc967..4cd750d6039 100644 --- a/tests/cases/fourslash/commentsFunction.ts +++ b/tests/cases/fourslash/commentsFunction.ts @@ -126,7 +126,6 @@ verify.quickInfoIs('(local var) localVar: string', ''); goTo.marker('30'); verify.quickInfoIs('(parameter) b: string', ''); goTo.marker('31'); -debugger; verify.quickInfoIs('(local var) lambdaVar: (b: string) => string', ''); goTo.marker('32'); verify.quickInfoIs('(parameter) a: number', ''); diff --git a/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment2.ts b/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment2.ts index e9bb7bf02a8..b3f283f1272 100644 --- a/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment2.ts +++ b/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment2.ts @@ -10,7 +10,6 @@ //// M.y./*4*/dx; goTo.marker('1'); -debugger; verify.referencesCountIs(1); goTo.marker('2'); @@ -20,4 +19,4 @@ goTo.marker('3'); verify.referencesCountIs(3); goTo.marker('4'); -verify.referencesCountIs(2); +verify.referencesCountIs(2); \ No newline at end of file diff --git a/tests/cases/fourslash/forceIndentAfterNewLineInsert.ts b/tests/cases/fourslash/forceIndentAfterNewLineInsert.ts index af6a21e97ea..a076213ebb6 100644 --- a/tests/cases/fourslash/forceIndentAfterNewLineInsert.ts +++ b/tests/cases/fourslash/forceIndentAfterNewLineInsert.ts @@ -6,7 +6,6 @@ ////{ function h() { ////return 0; ////}} -debugger; format.document(); verify.currentFileContentIs( "function f()\n" + @@ -17,4 +16,3 @@ verify.currentFileContentIs( " }\n" + "}" ); - diff --git a/tests/cases/fourslash/getEmitOutputWithDeclarationFile.ts b/tests/cases/fourslash/getEmitOutputWithDeclarationFile.ts index b45b2eff467..d15b49755d3 100644 --- a/tests/cases/fourslash/getEmitOutputWithDeclarationFile.ts +++ b/tests/cases/fourslash/getEmitOutputWithDeclarationFile.ts @@ -14,5 +14,4 @@ //// y : number; //// } -debugger; verify.baselineGetEmitOutput(); \ No newline at end of file diff --git a/tests/cases/fourslash/getEmitOutputWithDeclarationFile2.ts b/tests/cases/fourslash/getEmitOutputWithDeclarationFile2.ts index a36ac606189..f80fa777296 100644 --- a/tests/cases/fourslash/getEmitOutputWithDeclarationFile2.ts +++ b/tests/cases/fourslash/getEmitOutputWithDeclarationFile2.ts @@ -14,5 +14,4 @@ // @emitThisFile: true //// var x:string = "hello"; -debugger; verify.baselineGetEmitOutput(); \ No newline at end of file diff --git a/tests/cases/fourslash/getEmitOutputWithDeclarationFile3.ts b/tests/cases/fourslash/getEmitOutputWithDeclarationFile3.ts index 1fce5434c1f..e363d6b53fd 100644 --- a/tests/cases/fourslash/getEmitOutputWithDeclarationFile3.ts +++ b/tests/cases/fourslash/getEmitOutputWithDeclarationFile3.ts @@ -19,5 +19,4 @@ // @Filename: inputFile5.js //// var x2 = 1000; -debugger; verify.baselineGetEmitOutput(); \ No newline at end of file diff --git a/tests/cases/fourslash/localFunction.ts b/tests/cases/fourslash/localFunction.ts index d0227c83a8c..bf6d7636beb 100644 --- a/tests/cases/fourslash/localFunction.ts +++ b/tests/cases/fourslash/localFunction.ts @@ -12,7 +12,6 @@ goTo.marker("1"); verify.quickInfoIs('(function) foo(): void'); goTo.marker("2"); -debugger; verify.quickInfoIs('(local function) bar2(): void'); goTo.marker("3"); verify.quickInfoIs('(local function) bar3(): void'); diff --git a/tests/cases/fourslash/multilineCommentBeforeOpenBrace.ts b/tests/cases/fourslash/multilineCommentBeforeOpenBrace.ts index 63813c12288..7b784445486 100644 --- a/tests/cases/fourslash/multilineCommentBeforeOpenBrace.ts +++ b/tests/cases/fourslash/multilineCommentBeforeOpenBrace.ts @@ -8,7 +8,7 @@ ////} ////function a() { //// /* %^ */ }/*3*/ -debugger; + format.document(); goTo.marker('1'); verify.currentLineContentIs('function test() /* %^ */ {'); diff --git a/tests/cases/fourslash/spaceAfterReturn.ts b/tests/cases/fourslash/spaceAfterReturn.ts index e59b604f976..16b44d81024 100644 --- a/tests/cases/fourslash/spaceAfterReturn.ts +++ b/tests/cases/fourslash/spaceAfterReturn.ts @@ -5,7 +5,7 @@ ////return[1];/*2*/ ////return ;/*3*/ ////} -debugger; + format.document(); goTo.marker("1"); verify.currentLineContentIs(" return 1;"); From 0ec9f0d3bb2ab8ce55e7bbbf131ef6d022cd44c6 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 22:43:26 -0800 Subject: [PATCH 08/13] Check tree invariants during fourslash tests. --- src/harness/fourslash.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 0eca1981292..9147ffbc7c0 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1363,6 +1363,8 @@ module FourSlash { private checkPostEditInvariants() { var incrementalSourceFile = this.languageService.getSourceFile(this.activeFile.fileName); + Utils.assertInvariants(incrementalSourceFile, /*parent:*/ undefined); + var incrementalSyntaxDiagnostics = JSON.stringify(Utils.convertDiagnostics(incrementalSourceFile.getSyntacticDiagnostics())); // Check syntactic structure From 1bfe500897d8c4aedd927684f6b19e431e421649 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 23:22:19 -0800 Subject: [PATCH 09/13] Formatting. --- src/harness/fourslash.ts | 94 ++++++++++++++++++++-------------------- src/harness/harness.ts | 12 ++--- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 9147ffbc7c0..624b73c68a9 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -113,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] @@ -147,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: @@ -755,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(''); this.scenarioActions.push(''); @@ -800,7 +800,7 @@ module FourSlash { result = "[\n "; } result += JSON.stringify(part); - }); + }); if (result) { result += "\n]"; } @@ -869,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); } @@ -1381,24 +1381,24 @@ module FourSlash { Utils.assertStructuralEquals(incrementalSourceFile, referenceSourceFile); - //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() { @@ -1654,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++) { @@ -1695,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) + "'"; } } @@ -1708,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); @@ -2590,4 +2590,4 @@ module FourSlash { fileName: fileName }; } -} +} \ No newline at end of file diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 471261ef1f2..311e2db93ee 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -830,7 +830,7 @@ module Harness { writeFile, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, - getNewLine: ()=> ts.sys.newLine + getNewLine: () => ts.sys.newLine }; } @@ -872,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); }); @@ -882,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 }[], @@ -1020,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: @@ -1129,7 +1129,7 @@ module Harness { return ts.removeFileExtension(sourceFileName) + ".d.ts"; } }); - + return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined); } @@ -1642,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); \ No newline at end of file From 115a2d33b7f7093aea47e44347cd2ab7ad59de8c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 23:23:18 -0800 Subject: [PATCH 10/13] Update timeout to 6 seconds. --- Jakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jakefile b/Jakefile index 11dd7c048df..003cdb8feba 100644 --- a/Jakefile +++ b/Jakefile @@ -485,7 +485,7 @@ function deleteTemporaryProjectOutput() { } } -var testTimeout = 5000; +var testTimeout = 6000; desc("Runs the tests using the built run.js file. Syntax is jake runtests. Optional parameters 'host=', 'tests=[regex], reporter=[list|spec|json|]'."); task("runtests", ["tests", builtLocalDirectory], function() { cleanTestDirs(); From b09e92e8486d183954383073f9b159ba335d3964 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 15 Dec 2014 00:24:03 -0800 Subject: [PATCH 11/13] Up timeout to 20 seconds. A specific test "genericRespecialization1" takes quite some time on travis (though only a couple of seconds locally). --- Jakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jakefile b/Jakefile index 003cdb8feba..2c919cd20b8 100644 --- a/Jakefile +++ b/Jakefile @@ -485,7 +485,7 @@ function deleteTemporaryProjectOutput() { } } -var testTimeout = 6000; +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|]'."); task("runtests", ["tests", builtLocalDirectory], function() { cleanTestDirs(); From d3bfed13f8cc1ca1de972ed200bd5bb3012111ba Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 14 Dec 2014 10:03:54 -0800 Subject: [PATCH 12/13] Simplify the binder so it does not need to double recurse down constructor parameter nodes. --- src/compiler/binder.ts | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index dfb5482b09c..19ee45a419a 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -292,15 +292,6 @@ module ts { bindChildren(node, symbolKind, isBlockScopeContainer); } - function bindConstructorDeclaration(node: ConstructorDeclaration) { - bindDeclaration(node, SymbolFlags.Constructor, 0, /*isBlockScopeContainer*/ true); - forEach(node.parameters, p => { - if (p.flags & (NodeFlags.Public | NodeFlags.Private | NodeFlags.Protected)) { - bindDeclaration(p, SymbolFlags.Property, SymbolFlags.PropertyExcludes, /*isBlockScopeContainer*/ false); - } - }); - } - function bindModuleDeclaration(node: ModuleDeclaration) { if (node.name.kind === SyntaxKind.StringLiteral) { bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true); @@ -389,12 +380,7 @@ module ts { bindDeclaration(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes, /*isBlockScopeContainer*/ false); break; case SyntaxKind.Parameter: - if (isBindingPattern((node).name)) { - bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, getDestructuringParameterName(node), /*isBlockScopeContainer*/ false); - } - else { - bindDeclaration(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes, /*isBlockScopeContainer*/ false); - } + bindParameter(node); break; case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: @@ -437,7 +423,7 @@ module ts { bindDeclaration(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes, /*isBlockScopeContainer*/ true); break; case SyntaxKind.Constructor: - bindConstructorDeclaration(node); + bindDeclaration(node, SymbolFlags.Constructor, /*symbolExcludes:*/ 0, /*isBlockScopeContainer:*/ true); break; case SyntaxKind.GetAccessor: bindDeclaration(node, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes, /*isBlockScopeContainer*/ true); @@ -508,5 +494,24 @@ module ts { parent = saveParent; } } + + function bindParameter(node: ParameterDeclaration) { + if (isBindingPattern(node.name)) { + bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, getDestructuringParameterName(node), /*isBlockScopeContainer*/ false); + } + else { + bindDeclaration(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes, /*isBlockScopeContainer*/ false); + } + + // If this is a property-parameter, then also declare the property symbol into the + // containing class. + if (node.flags & NodeFlags.AccessibilityModifier && + node.parent.kind === SyntaxKind.Constructor && + node.parent.parent.kind === SyntaxKind.ClassDeclaration) { + + var classDeclaration = node.parent.parent; + declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + } + } } } From cb8d2f28ae7127878aea38609cad8d98782eb150 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 15 Dec 2014 14:43:31 -0800 Subject: [PATCH 13/13] Simplify how we set container.nextContainer now that we don't double recurse. --- src/compiler/binder.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 19ee45a419a..4f8141fd866 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -227,23 +227,27 @@ module ts { if (symbolKind & SymbolFlags.HasLocals) { node.locals = {}; } + var saveParent = parent; var saveContainer = container; var savedBlockScopeContainer = blockScopeContainer; parent = node; if (symbolKind & SymbolFlags.IsContainer) { container = node; - // If container is not on container list, add it to the list - if (lastContainer !== container && !container.nextContainer) { - if (lastContainer) { - lastContainer.nextContainer = container; - } - lastContainer = container; + Debug.assert(container.nextContainer === undefined); + + if (lastContainer) { + Debug.assert(lastContainer.nextContainer === undefined); + lastContainer.nextContainer = container; } + + lastContainer = container; } + if (isBlockScopeContainer) { blockScopeContainer = node; } + forEachChild(node, bind); container = saveContainer; parent = saveParent;