From bfef4a03658d6d5ac2519aac38b4fcbae4223437 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 4 Feb 2015 15:36:13 -0800 Subject: [PATCH] Add new tests for shims --- src/harness/fourslash.ts | 45 +++++-- src/harness/fourslashRunner.ts | 36 ++++-- src/harness/harnessLanguageService.ts | 8 +- src/harness/runner.ts | 10 +- .../getBreakpointStatementAtPosition.baseline | 71 +++++++++++ .../reference/getEmitOutput.baseline | 30 +++++ tests/cases/fourslash/indentation.ts | 2 +- ...cellationWhenfindingAllRefsOnDefinition.ts | 38 ++++++ .../shims/getBraceMatchingAtPosition.ts | 43 +++++++ .../shims/getBreakpointStatementAtPosition.ts | 17 +++ .../shims/getCompletionsAtPosition.ts | 20 ++++ .../shims/getDefinitionAtPosition.ts | 29 +++++ tests/cases/fourslash/shims/getEmitOutput.ts | 22 ++++ .../shims/getIndentationAtPosition.ts | 21 ++++ .../fourslash/shims/getNavigateToItems.ts | 27 +++++ .../fourslash/shims/getNavigationBarItems.ts | 13 ++ .../shims/getOccurrencesAtPosition.ts | 18 +++ .../fourslash/shims/getOutliningSpans.ts | 113 ++++++++++++++++++ .../fourslash/shims/getPreProcessedFile.ts | 32 +++++ .../fourslash/shims/getQuickInfoAtPosition.ts | 16 +++ .../shims/getReferencesAtPosition.ts | 29 +++++ tests/cases/fourslash/shims/getRenameInfo.ts | 11 ++ .../shims/getSemanticClassifications.ts | 15 +++ .../fourslash/shims/getSemanticDiagnostics.ts | 11 ++ .../fourslash/shims/getSignatureHelpItems.ts | 13 ++ .../shims/getSyntacticClassifications.ts | 35 ++++++ .../cases/fourslash/shims/getTodoComments.ts | 3 + .../shims/quickInfoDisplayPartsVar.ts | 76 ++++++++++++ 28 files changed, 776 insertions(+), 28 deletions(-) create mode 100644 tests/baselines/reference/getBreakpointStatementAtPosition.baseline create mode 100644 tests/baselines/reference/getEmitOutput.baseline create mode 100644 tests/cases/fourslash/shims/cancellationWhenfindingAllRefsOnDefinition.ts create mode 100644 tests/cases/fourslash/shims/getBraceMatchingAtPosition.ts create mode 100644 tests/cases/fourslash/shims/getBreakpointStatementAtPosition.ts create mode 100644 tests/cases/fourslash/shims/getCompletionsAtPosition.ts create mode 100644 tests/cases/fourslash/shims/getDefinitionAtPosition.ts create mode 100644 tests/cases/fourslash/shims/getEmitOutput.ts create mode 100644 tests/cases/fourslash/shims/getIndentationAtPosition.ts create mode 100644 tests/cases/fourslash/shims/getNavigateToItems.ts create mode 100644 tests/cases/fourslash/shims/getNavigationBarItems.ts create mode 100644 tests/cases/fourslash/shims/getOccurrencesAtPosition.ts create mode 100644 tests/cases/fourslash/shims/getOutliningSpans.ts create mode 100644 tests/cases/fourslash/shims/getPreProcessedFile.ts create mode 100644 tests/cases/fourslash/shims/getQuickInfoAtPosition.ts create mode 100644 tests/cases/fourslash/shims/getReferencesAtPosition.ts create mode 100644 tests/cases/fourslash/shims/getRenameInfo.ts create mode 100644 tests/cases/fourslash/shims/getSemanticClassifications.ts create mode 100644 tests/cases/fourslash/shims/getSemanticDiagnostics.ts create mode 100644 tests/cases/fourslash/shims/getSignatureHelpItems.ts create mode 100644 tests/cases/fourslash/shims/getSyntacticClassifications.ts create mode 100644 tests/cases/fourslash/shims/getTodoComments.ts create mode 100644 tests/cases/fourslash/shims/quickInfoDisplayPartsVar.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 5b46ec32a1c..cccbc448213 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -275,11 +275,26 @@ module FourSlash { } } - constructor(public testData: FourSlashData) { + private getLanguageServiceAdaptor(testType: FourSlashTestType): + { new (cancellationToken?: ts.CancellationToken, options?: ts.CompilerOptions): Harness.LanguageService.LanguageServiceAdaptor } { + switch (testType) { + case FourSlashTestType.Native: + return Harness.LanguageService.NativeLanugageServiceAdaptor; + break; + case FourSlashTestType.Shims: + return Harness.LanguageService.ShimLanugageServiceAdaptor; + break; + default: + throw new Error("Unknown FourSlash test type: "); + } + } + + constructor(private basePath: string, private testType: FourSlashTestType, public testData: FourSlashData) { // Create a new Services Adaptor this.cancellationToken = new TestCancellationToken(); var compilationOptions = convertGlobalOptionsToCompilerOptions(this.testData.globalOptions); - var languageServiceAdaptor = new Harness.LanguageService.NativeLanugageServiceAdaptor(this.cancellationToken, compilationOptions); + var languageserviceAdaptorFactory = this.getLanguageServiceAdaptor(testType); + var languageServiceAdaptor = new languageserviceAdaptorFactory(this.cancellationToken, compilationOptions); this.languageServiceAdaptorHost = languageServiceAdaptor.getHost(); this.languageService = languageServiceAdaptor.getLanguageService(); @@ -308,7 +323,7 @@ module FourSlash { // Add triple reference files into language-service host ts.forEach(referencedFiles, referenceFile => { // Fourslash insert tests/cases/fourslash into inputFile.unitName so we will properly append the same base directory to refFile path - var referenceFilePath = "tests/cases/fourslash/" + referenceFile.filename; + var referenceFilePath = this.basePath+ '/' + referenceFile.filename; this.addMatchedInputFile(referenceFilePath); }); @@ -316,7 +331,7 @@ module FourSlash { ts.forEach(importedFiles, importedFile => { // Fourslash insert tests/cases/fourslash into inputFile.unitName and import statement doesn't require ".ts" // so convert them before making appropriate comparison - var importedFilePath = "tests/cases/fourslash/" + importedFile.filename + ".ts"; + var importedFilePath = this.basePath + '/' + importedFile.filename + ".ts"; this.addMatchedInputFile(importedFilePath); }); @@ -1382,6 +1397,12 @@ module FourSlash { } private checkPostEditInvariants() { + if (this.testType !== FourSlashTestType.Native) { + // getSourcefile() results can not be serialized. Only perform these verifications + // if running against a native LS object. + return; + } + var incrementalSourceFile = this.languageService.getSourceFile(this.activeFile.fileName); Utils.assertInvariants(incrementalSourceFile, /*parent:*/ undefined); @@ -2052,7 +2073,7 @@ module FourSlash { } else if (typeof indexOrName === 'string') { var name = indexOrName; // names are stored in the compiler with this relative path, this allows people to use goTo.file on just the filename - name = name.indexOf('/') === -1 ? 'tests/cases/fourslash/' + name : name; + name = name.indexOf('/') === -1 ? (this.basePath + '/' + name) : name; var availableNames: string[] = []; var foundIt = false; for (var i = 0; i < this.testData.files.length; i++) { @@ -2118,17 +2139,17 @@ module FourSlash { var fsOutput = new Harness.Compiler.WriterAggregator(); var fsErrors = new Harness.Compiler.WriterAggregator(); export var xmlData: TestXmlData[] = []; - export function runFourSlashTest(fileName: string) { + export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) { var content = Harness.IO.readFile(fileName); - var xml = runFourSlashTestContent(content, fileName); + var xml = runFourSlashTestContent(basePath, testType, content, fileName); xmlData.push(xml); } - export function runFourSlashTestContent(content: string, fileName: string): TestXmlData { + export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): TestXmlData { // Parse out the files and their metadata - var testData = parseTestData(content, fileName); + var testData = parseTestData(basePath, content, fileName); - currentTestState = new TestState(testData); + currentTestState = new TestState(basePath, testType, testData); var result = ''; var host = Harness.Compiler.createCompilerHost([{ unitName: Harness.Compiler.fourslashFilename, content: undefined }, @@ -2171,7 +2192,7 @@ module FourSlash { return lines.map(s => s.substr(1)).join('\n'); } - function parseTestData(contents: string, fileName: string): FourSlashData { + function parseTestData(basePath: string, contents: string, fileName: string): FourSlashData { // Regex for parsing options in the format "@Alpha: Value of any sort" var optionRegex = /^\s*@(\w+): (.*)\s*/; @@ -2239,7 +2260,7 @@ module FourSlash { currentFileName = fileName; } - currentFileName = 'tests/cases/fourslash/' + match[2]; + currentFileName = basePath + '/' + match[2]; currentFileOptions[match[1]] = match[2]; } else { // Add other fileMetadata flag diff --git a/src/harness/fourslashRunner.ts b/src/harness/fourslashRunner.ts index 1ecb02df292..fe3b6c7a91f 100644 --- a/src/harness/fourslashRunner.ts +++ b/src/harness/fourslashRunner.ts @@ -2,19 +2,35 @@ /// /// -class FourslashRunner extends RunnerBase { - public basePath = 'tests/cases/fourslash'; +const enum FourSlashTestType { + Native, + Shims +} - constructor() { +class FourSlashRunner extends RunnerBase { + protected basePath: string; + protected testSuiteName: string; + + constructor(private testType: FourSlashTestType) { super(); + switch (testType) { + case FourSlashTestType.Native: + this.basePath = 'tests/cases/fourslash'; + this.testSuiteName = 'fourslash'; + break; + case FourSlashTestType.Shims: + this.basePath = 'tests/cases/fourslash/shims'; + this.testSuiteName = 'fourslash-shims'; + break; + } } public initializeTests() { if (this.tests.length === 0) { - this.tests = this.enumerateFiles(this.basePath, /\.ts/i); + this.tests = this.enumerateFiles(this.basePath, /\.ts/i, { recursive: false }); } - describe("fourslash tests", () => { + describe(this.testSuiteName, () => { this.tests.forEach((fn: string) => { fn = ts.normalizeSlashes(fn); var justName = fn.replace(/^.*[\\\/]/, ''); @@ -24,8 +40,8 @@ class FourslashRunner extends RunnerBase { if (testIndex >= 0) fn = fn.substr(testIndex); if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) { - it('FourSlash test ' + justName + ' runs correctly', function () { - FourSlash.runFourSlashTest(fn); + it(this.testSuiteName + ' test ' + justName + ' runs correctly',() => { + FourSlash.runFourSlashTest(this.basePath, this.testType, fn); }); } }); @@ -82,9 +98,9 @@ class FourslashRunner extends RunnerBase { } } -class GeneratedFourslashRunner extends FourslashRunner { - constructor() { - super(); +class GeneratedFourslashRunner extends FourSlashRunner { + constructor(testType: FourSlashTestType) { + super(testType); this.basePath += '/generated/'; } } \ No newline at end of file diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 4b188cf96f6..2fce141bbf3 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -56,9 +56,13 @@ module Harness.LanguageService { } class ScriptSnapshot implements ts.IScriptSnapshot { - public textSnapshot: string; public version: number; + public textSnapshot: string; + public version: number; + constructor(public scriptInfo: ScriptInfo) { - this.textSnapshot = scriptInfo.content; this.version = scriptInfo.version; } + this.textSnapshot = scriptInfo.content; + this.version = scriptInfo.version; + } public getText(start: number, end: number): string { return this.textSnapshot.substring(start, end); diff --git a/src/harness/runner.ts b/src/harness/runner.ts index 24349ada3fd..942ae56bf6f 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -61,10 +61,13 @@ if (testConfigFile !== '') { runners.push(new ProjectRunner()); break; case 'fourslash': - runners.push(new FourslashRunner()); + runners.push(new FourSlashRunner(FourSlashTestType.Native)); + break; + case 'fourslash-shims': + runners.push(new FourSlashRunner(FourSlashTestType.Shims)); break; case 'fourslash-generated': - runners.push(new GeneratedFourslashRunner()); + runners.push(new GeneratedFourslashRunner(FourSlashTestType.Native)); break; case 'rwc': runners.push(new RWCRunner()); @@ -90,7 +93,8 @@ if (runners.length === 0) { } // language services - runners.push(new FourslashRunner()); + runners.push(new FourSlashRunner(FourSlashTestType.Native)); + runners.push(new FourSlashRunner(FourSlashTestType.Shims)); //runners.push(new GeneratedFourslashRunner()); } diff --git a/tests/baselines/reference/getBreakpointStatementAtPosition.baseline b/tests/baselines/reference/getBreakpointStatementAtPosition.baseline new file mode 100644 index 00000000000..617589b9047 --- /dev/null +++ b/tests/baselines/reference/getBreakpointStatementAtPosition.baseline @@ -0,0 +1,71 @@ + +1 >while (true) { + + ~~~~~~~~~~~~~~~ => Pos: (0 to 14) SpanInfo: {"start":0,"length":12} + >while (true) + >:=> (line 1, col 0) to (line 1, col 12) +-------------------------------- +2 > break; + + ~~~~~~~~~~~ => Pos: (15 to 25) SpanInfo: {"start":19,"length":5} + >break + >:=> (line 2, col 4) to (line 2, col 9) +-------------------------------- +3 >} + + ~~ => Pos: (26 to 27) SpanInfo: {"start":19,"length":5} + >break + >:=> (line 2, col 4) to (line 2, col 9) +-------------------------------- +4 >y: while (true) { + + ~~~~~~~~~~~~~~~~~~ => Pos: (28 to 45) SpanInfo: {"start":31,"length":12} + >while (true) + >:=> (line 4, col 3) to (line 4, col 15) +-------------------------------- +5 > break y; + + ~~~~~~~~~~~~~ => Pos: (46 to 58) SpanInfo: {"start":50,"length":7} + >break y + >:=> (line 5, col 4) to (line 5, col 11) +-------------------------------- +6 >} + + ~~ => Pos: (59 to 60) SpanInfo: {"start":50,"length":7} + >break y + >:=> (line 5, col 4) to (line 5, col 11) +-------------------------------- +7 >while (true) { + + ~~~~~~~~~~~~~~~ => Pos: (61 to 75) SpanInfo: {"start":61,"length":12} + >while (true) + >:=> (line 7, col 0) to (line 7, col 12) +-------------------------------- +8 > continue; + + ~~~~~~~~~~~~~~ => Pos: (76 to 89) SpanInfo: {"start":80,"length":8} + >continue + >:=> (line 8, col 4) to (line 8, col 12) +-------------------------------- +9 >} + + ~~ => Pos: (90 to 91) SpanInfo: {"start":80,"length":8} + >continue + >:=> (line 8, col 4) to (line 8, col 12) +-------------------------------- +10 >z: while (true) { + + ~~~~~~~~~~~~~~~~~~ => Pos: (92 to 109) SpanInfo: {"start":95,"length":12} + >while (true) + >:=> (line 10, col 3) to (line 10, col 15) +-------------------------------- +11 > continue z; + + ~~~~~~~~~~~~~~~~ => Pos: (110 to 125) SpanInfo: {"start":114,"length":10} + >continue z + >:=> (line 11, col 4) to (line 11, col 14) +-------------------------------- +12 >} + ~ => Pos: (126 to 126) SpanInfo: {"start":114,"length":10} + >continue z + >:=> (line 11, col 4) to (line 11, col 14) \ No newline at end of file diff --git a/tests/baselines/reference/getEmitOutput.baseline b/tests/baselines/reference/getEmitOutput.baseline new file mode 100644 index 00000000000..8ca4f6a4100 --- /dev/null +++ b/tests/baselines/reference/getEmitOutput.baseline @@ -0,0 +1,30 @@ +EmitOutputStatus : Succeeded +Filename : tests/cases/fourslash/shims/inputFile1.js +var x = 5; +var Bar = (function () { + function Bar() { + } + return Bar; +})(); +Filename : tests/cases/fourslash/shims/inputFile1.d.ts +declare var x: number; +declare class Bar { + x: string; + y: number; +} + +EmitOutputStatus : Succeeded +Filename : tests/cases/fourslash/shims/inputFile2.js +var x1 = "hello world"; +var Foo = (function () { + function Foo() { + } + return Foo; +})(); +Filename : tests/cases/fourslash/shims/inputFile2.d.ts +declare var x1: string; +declare class Foo { + x: string; + y: number; +} + diff --git a/tests/cases/fourslash/indentation.ts b/tests/cases/fourslash/indentation.ts index 32319ae282d..2a2090c1d87 100644 --- a/tests/cases/fourslash/indentation.ts +++ b/tests/cases/fourslash/indentation.ts @@ -179,5 +179,5 @@ ////{| "indent": 0 |} test.markers().forEach((marker) => { - verify.indentationAtPositionIs('tests/cases/fourslash/indentation.ts', marker.position, marker.data.indent); + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); }); diff --git a/tests/cases/fourslash/shims/cancellationWhenfindingAllRefsOnDefinition.ts b/tests/cases/fourslash/shims/cancellationWhenfindingAllRefsOnDefinition.ts new file mode 100644 index 00000000000..09f580bb965 --- /dev/null +++ b/tests/cases/fourslash/shims/cancellationWhenfindingAllRefsOnDefinition.ts @@ -0,0 +1,38 @@ +/// + +//@Filename: findAllRefsOnDefinition-import.ts +////export class Test{ +//// +//// constructor(){ +//// +//// } +//// +//// public /*1*/start(){ +//// return this; +//// } +//// +//// public stop(){ +//// return this; +//// } +////} + +//@Filename: findAllRefsOnDefinition.ts +////import Second = require("findAllRefsOnDefinition-import"); +//// +////var second = new Second.Test() +////second.start(); +////second.stop(); + +goTo.file("findAllRefsOnDefinition-import.ts"); +goTo.marker("1"); + +verify.referencesCountIs(2); + +cancellation.setCancelled(); +goTo.marker("1"); +verifyOperationIsCancelled(() => verify.referencesCountIs(0) ); + +// verify that internal state is still correct +cancellation.resetCancelled(); +goTo.marker("1"); +verify.referencesCountIs(2); diff --git a/tests/cases/fourslash/shims/getBraceMatchingAtPosition.ts b/tests/cases/fourslash/shims/getBraceMatchingAtPosition.ts new file mode 100644 index 00000000000..fc8a71197db --- /dev/null +++ b/tests/cases/fourslash/shims/getBraceMatchingAtPosition.ts @@ -0,0 +1,43 @@ +/// + +//////curly braces +////module Foo [|{ +//// class Bar [|{ +//// private f() [|{ +//// }|] +//// +//// private f2() [|{ +//// if (true) [|{ }|] [|{ }|]; +//// }|] +//// }|] +////}|] +//// +//////parenthesis +////class FooBar { +//// private f[|()|] { +//// return [|([|(1 + 1)|])|]; +//// } +//// +//// private f2[|()|] { +//// if [|(true)|] { } +//// } +////} +//// +//////square brackets +////class Baz { +//// private f() { +//// var a: any[|[]|] = [|[[|[1, 2]|], [|[3, 4]|], 5]|]; +//// } +////} +//// +////// angular brackets +////class TemplateTest [||] { +//// public foo(a, b) { +//// return [||] a; +//// } +////} + +test.ranges().forEach((range) => { + verify.matchingBracePositionInCurrentFile(range.start, range.end - 1); + verify.matchingBracePositionInCurrentFile(range.end - 1, range.start); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getBreakpointStatementAtPosition.ts b/tests/cases/fourslash/shims/getBreakpointStatementAtPosition.ts new file mode 100644 index 00000000000..9e1d075a17f --- /dev/null +++ b/tests/cases/fourslash/shims/getBreakpointStatementAtPosition.ts @@ -0,0 +1,17 @@ +/// + +// @BaselineFile: getBreakpointStatementAtPosition.baseline +// @Filename: getBreakpointStatementAtPosition.ts +////while (true) { +//// break; +////} +////y: while (true) { +//// break y; +////} +////while (true) { +//// continue; +////} +////z: while (true) { +//// continue z; +////} +verify.baselineCurrentFileBreakpointLocations(); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getCompletionsAtPosition.ts b/tests/cases/fourslash/shims/getCompletionsAtPosition.ts new file mode 100644 index 00000000000..714d3390e76 --- /dev/null +++ b/tests/cases/fourslash/shims/getCompletionsAtPosition.ts @@ -0,0 +1,20 @@ +/// + +////function foo(strOrNum: string | number) { +//// /*1*/ +//// if (typeof strOrNum === "number") { +//// /*2*/ +//// } +//// else { +//// /*3*/ +//// } +////} + +goTo.marker('1'); +verify.completionListContains("strOrNum", "(parameter) strOrNum: string | number"); + +goTo.marker('2'); +verify.completionListContains("strOrNum", "(parameter) strOrNum: number"); + +goTo.marker('3'); +verify.completionListContains("strOrNum", "(parameter) strOrNum: string"); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getDefinitionAtPosition.ts b/tests/cases/fourslash/shims/getDefinitionAtPosition.ts new file mode 100644 index 00000000000..54b799ba65f --- /dev/null +++ b/tests/cases/fourslash/shims/getDefinitionAtPosition.ts @@ -0,0 +1,29 @@ +/// + +// @Filename: goToDefinitionDifferentFile_Definition.ts +////var /*remoteVariableDefinition*/remoteVariable; +/////*remoteFunctionDefinition*/function remoteFunction() { } +/////*remoteClassDefinition*/class remoteClass { } +/////*remoteInterfaceDefinition*/interface remoteInterface{ } +/////*remoteModuleDefinition*/module remoteModule{ export var foo = 1;} + +// @Filename: goToDefinitionDifferentFile_Consumption.ts +/////*remoteVariableReference*/remoteVariable = 1; +/////*remoteFunctionReference*/remoteFunction(); +////var foo = new /*remoteClassReference*/remoteClass(); +////class fooCls implements /*remoteInterfaceReference*/remoteInterface { } +////var fooVar = /*remoteModuleReference*/remoteModule.foo; + +var markerList = [ + "remoteVariable", + "remoteFunction", + "remoteClass", + "remoteInterface", + "remoteModule", +]; + +markerList.forEach((marker) => { + goTo.marker(marker + 'Reference'); + goTo.definition(); + verify.caretAtMarker(marker + 'Definition'); +}); diff --git a/tests/cases/fourslash/shims/getEmitOutput.ts b/tests/cases/fourslash/shims/getEmitOutput.ts new file mode 100644 index 00000000000..699514521ed --- /dev/null +++ b/tests/cases/fourslash/shims/getEmitOutput.ts @@ -0,0 +1,22 @@ +/// + +// @BaselineFile: getEmitOutput.baseline +// @declaration: true + +// @Filename: inputFile1.ts +// @emitThisFile: true +//// var x: number = 5; +//// class Bar { +//// x : string; +//// y : number +//// } + +// @Filename: inputFile2.ts +// @emitThisFile: true +//// var x1: string = "hello world"; +//// class Foo{ +//// x : string; +//// y : number; +//// } + +verify.baselineGetEmitOutput(); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getIndentationAtPosition.ts b/tests/cases/fourslash/shims/getIndentationAtPosition.ts new file mode 100644 index 00000000000..5e26781357e --- /dev/null +++ b/tests/cases/fourslash/shims/getIndentationAtPosition.ts @@ -0,0 +1,21 @@ +/// + +////class Bar { +//// {| "indentation": 4|} +//// private foo: string = ""; +//// {| "indentation": 4|} +//// private f() { +//// var a: any[] = [[1, 2], [3, 4], 5]; +//// {| "indentation": 8|} +//// return ((1 + 1)); +//// } +//// {| "indentation": 4|} +//// private f2() { +//// if (true) { } { }; +//// } +////} +////{| "indentation": 0|} + +test.markers().forEach((marker) => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indentation); +}); diff --git a/tests/cases/fourslash/shims/getNavigateToItems.ts b/tests/cases/fourslash/shims/getNavigateToItems.ts new file mode 100644 index 00000000000..9658c52324c --- /dev/null +++ b/tests/cases/fourslash/shims/getNavigateToItems.ts @@ -0,0 +1,27 @@ +/// + +/////// Module +////{| "itemName": "Shapes", "kind": "module", "parentName": "" |}module Shapes { +//// +//// // Class +//// {| "itemName": "Point", "kind": "class", "parentName": "Shapes" |}export class Point { +//// // Instance member +//// {| "itemName": "origin", "kind": "property", "parentName": "Point", "matchKind": "exact"|}private origin = 0.0; +//// +//// {| "itemName": "distFromZero", "kind": "property", "parentName": "Point", "matchKind": "exact"|}private distFromZero = 0.0; +//// +//// // Getter +//// {| "itemName": "distance", "kind": "getter", "parentName": "Point", "matchKind": "exact" |}get distance(): number { return 0; } +//// } +////} +//// +////// Local variables +////{| "itemName": "point", "kind": "var", "parentName": "", "matchKind": "exact"|}var point = new Shapes.Point(); + +//// Testing for exact matching of navigationItems + +test.markers().forEach((marker) => { + if (marker.data) { + verify.navigationItemsListContains(marker.data.itemName, marker.data.kind, marker.data.itemName, marker.data.matchKind, marker.fileName, marker.data.parentName); + } +}); diff --git a/tests/cases/fourslash/shims/getNavigationBarItems.ts b/tests/cases/fourslash/shims/getNavigationBarItems.ts new file mode 100644 index 00000000000..6c0738747f3 --- /dev/null +++ b/tests/cases/fourslash/shims/getNavigationBarItems.ts @@ -0,0 +1,13 @@ +/// + +//// {| "itemName": "c", "kind": "const", "parentName": "" |}const c = 0; + +test.markers().forEach(marker => { + verify.getScriptLexicalStructureListContains( + marker.data.itemName, + marker.data.kind, + marker.fileName, + marker.data.parentName, + marker.data.isAdditionalRange, + marker.position); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getOccurrencesAtPosition.ts b/tests/cases/fourslash/shims/getOccurrencesAtPosition.ts new file mode 100644 index 00000000000..0654cc3962c --- /dev/null +++ b/tests/cases/fourslash/shims/getOccurrencesAtPosition.ts @@ -0,0 +1,18 @@ +/// + +/////*0*/ +////interface A { +//// foo: string; +////} +////function foo(x: A) { +//// x.f/*1*/oo +////} + +goTo.marker("1"); +verify.occurrencesAtPositionCount(2); + +goTo.marker("0"); +edit.insert("\r\n"); + +goTo.marker("1"); +verify.occurrencesAtPositionCount(2); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getOutliningSpans.ts b/tests/cases/fourslash/shims/getOutliningSpans.ts new file mode 100644 index 00000000000..93665889eb4 --- /dev/null +++ b/tests/cases/fourslash/shims/getOutliningSpans.ts @@ -0,0 +1,113 @@ +/// + +////// interface +////interface IFoo[| { +//// getDist(): number; +////}|] +//// +////// class members +////class Foo[| { +//// constructor()[| { +//// }|] +//// +//// public foo(): number[| { +//// return 0; +//// }|] +//// +//// public get X()[| { +//// return 1; +//// }|] +//// +//// public set X(v: number)[| { +//// }|] +//// +//// public member = function f()[| { +//// +//// }|] +////}|] +////switch(1)[| { +//// case 1: break; +////}|] +//// +////var array =[| [ +//// 1, +//// 2 +////]|] +//// +////// modules +////module m1[| { +//// module m2[| { }|] +//// module m3[| { +//// function foo()[| { +//// +//// }|] +//// +//// interface IFoo2[| { +//// +//// }|] +//// +//// class foo2 implements IFoo2[| { +//// +//// }|] +//// }|] +////}|] +//// +////// function declaration +////function foo(): number[| { +//// return 0; +////}|] +//// +////// function expressions +////(function f()[| { +//// +////}|]) +//// +////// trivia handeling +////class ClassFooWithTrivia[| /* some comments */ +//// /* more trivia */ { +//// +//// +//// /*some trailing trivia */ +////}|] /* even more */ +//// +////// object literals +////var x =[|{ +//// a:1, +//// b:2, +//// get foo()[| { +//// return 1; +//// }|] +////}|] +//////outline with deep nesting +////module m1[|{ +//// module m2[| { +//// module m3[| { +//// module m4[| { +//// module m5[| { +//// module m6[| { +//// module m7[| { +//// module m8[| { +//// module m9[| { +//// module m10[| { +//// module m11 { +//// module m12 { +//// export interface IFoo { +//// } +//// } +//// } +//// }|] +//// }|] +//// }|] +//// }|] +//// }|] +//// }|] +//// }|] +//// }|] +//// }|] +////}|] +//// +//////outline after a deeply nested node +////class AfterNestedNodes[| { +////}|] + +verify.outliningSpansInCurrentFile(test.ranges()); diff --git a/tests/cases/fourslash/shims/getPreProcessedFile.ts b/tests/cases/fourslash/shims/getPreProcessedFile.ts new file mode 100644 index 00000000000..abd26bb6e4b --- /dev/null +++ b/tests/cases/fourslash/shims/getPreProcessedFile.ts @@ -0,0 +1,32 @@ +/// + +// @Filename: refFile1.ts +//// class D { } + +// @Filename: refFile2.ts +//// export class E {} + +// @Filename: main.ts +// @ResolveReference: true +//// /// +//// /*1*/////*2*/ +//// /*3*/////*4*/ +//// import ref2 = require("refFile2"); +//// import noExistref2 = require(/*5*/"NotExistRefFile2"/*6*/); +//// import invalidRef1 /*7*/require/*8*/("refFile2"); +//// /*9*/import invalidRef2 = requi/*10*/("refFile2"); +//// var obj: /*11*/C/*12*/; +//// var obj1: D; +//// var obj2: ref2.E; + +goTo.file("main.ts"); +verify.numberOfErrorsInCurrentFile(7); +verify.errorExistsBetweenMarkers("1", "2"); +verify.errorExistsBetweenMarkers("3", "4"); +verify.errorExistsBetweenMarkers("5", "6"); +verify.errorExistsBetweenMarkers("7", "8"); +verify.errorExistsBetweenMarkers("9", "10"); // At this position, there are two diagnostic messages: ';' expected, Cannot find name 'requi' +verify.errorExistsBetweenMarkers("11", "12"); + + + diff --git a/tests/cases/fourslash/shims/getQuickInfoAtPosition.ts b/tests/cases/fourslash/shims/getQuickInfoAtPosition.ts new file mode 100644 index 00000000000..6c9fc7cf795 --- /dev/null +++ b/tests/cases/fourslash/shims/getQuickInfoAtPosition.ts @@ -0,0 +1,16 @@ +/// + +////class SS{} +//// +////var x/*1*/1 = new SS(); +////var x/*2*/2 = new SS(); +////var x/*3*/3 = new SS; + +goTo.marker('1'); +verify.quickInfoIs('(var) x1: SS'); + +goTo.marker('2'); +verify.quickInfoIs('(var) x2: SS<{}>'); + +goTo.marker('3'); +verify.quickInfoIs('(var) x3: SS<{}>'); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getReferencesAtPosition.ts b/tests/cases/fourslash/shims/getReferencesAtPosition.ts new file mode 100644 index 00000000000..34144b74899 --- /dev/null +++ b/tests/cases/fourslash/shims/getReferencesAtPosition.ts @@ -0,0 +1,29 @@ +/// + +//@Filename: findAllRefsOnDefinition-import.ts +////export class Test{ +//// +//// constructor(){ +//// +//// } +//// +//// public /*1*/start(){ +//// return this; +//// } +//// +//// public stop(){ +//// return this; +//// } +////} + +//@Filename: findAllRefsOnDefinition.ts +////import Second = require("findAllRefsOnDefinition-import"); +//// +////var second = new Second.Test() +////second.start(); +////second.stop(); + +goTo.file("findAllRefsOnDefinition-import.ts"); +goTo.marker("1"); + +verify.referencesCountIs(2); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getRenameInfo.ts b/tests/cases/fourslash/shims/getRenameInfo.ts new file mode 100644 index 00000000000..b5c8ac6aacc --- /dev/null +++ b/tests/cases/fourslash/shims/getRenameInfo.ts @@ -0,0 +1,11 @@ +/// + +/////// + +////function /**/[|Bar|]() { +//// // This is a reference to Bar in a comment. +//// "this is a reference to Bar in a string" +////} + +goTo.marker(); +verify.renameLocations(/*findInStrings:*/ false, /*findInComments:*/ false); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getSemanticClassifications.ts b/tests/cases/fourslash/shims/getSemanticClassifications.ts new file mode 100644 index 00000000000..4eb7f2a32ed --- /dev/null +++ b/tests/cases/fourslash/shims/getSemanticClassifications.ts @@ -0,0 +1,15 @@ +/// + +//// module /*0*/M { +//// export interface /*1*/I { +//// } +//// } +//// interface /*2*/X extends /*3*/M./*4*/I { } + +var c = classification; +verify.semanticClassificationsAre( + c.moduleName("M", test.marker("0").position), + c.interfaceName("I", test.marker("1").position), + c.interfaceName("X", test.marker("2").position), + c.moduleName("M", test.marker("3").position), + c.interfaceName("I", test.marker("4").position)); diff --git a/tests/cases/fourslash/shims/getSemanticDiagnostics.ts b/tests/cases/fourslash/shims/getSemanticDiagnostics.ts new file mode 100644 index 00000000000..6345c464213 --- /dev/null +++ b/tests/cases/fourslash/shims/getSemanticDiagnostics.ts @@ -0,0 +1,11 @@ +/// + +// @module: CommonJS +// @declaration: true +//// interface privateInterface {} +//// export class Bar implements /*1*/privateInterface/*2*/{ } + +verify.errorExistsBetweenMarkers("1", "2"); +verify.numberOfErrorsInCurrentFile(1); + + diff --git a/tests/cases/fourslash/shims/getSignatureHelpItems.ts b/tests/cases/fourslash/shims/getSignatureHelpItems.ts new file mode 100644 index 00000000000..846c2d5244a --- /dev/null +++ b/tests/cases/fourslash/shims/getSignatureHelpItems.ts @@ -0,0 +1,13 @@ +/// + +// @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*/ + +goTo.marker('1'); +verify.signatureHelpCountIs(2); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getSyntacticClassifications.ts b/tests/cases/fourslash/shims/getSyntacticClassifications.ts new file mode 100644 index 00000000000..88f655683a3 --- /dev/null +++ b/tests/cases/fourslash/shims/getSyntacticClassifications.ts @@ -0,0 +1,35 @@ +/// + +//// // comment +//// module M { +//// var v = 0 + 1; +//// var s = "string"; +//// +//// class C { +//// } +//// +//// enum E { +//// } +//// +//// interface I { +//// } +//// +//// module M1.M2 { +//// } +//// } + +var c = classification; +verify.syntacticClassificationsAre( + c.comment("// comment"), + c.keyword("module"), c.moduleName("M"), c.punctuation("{"), + c.keyword("var"), c.text("v"), c.operator("="), c.numericLiteral("0"), c.operator("+"), c.numericLiteral("1"), c.punctuation(";"), + c.keyword("var"), c.text("s"), c.operator("="), c.stringLiteral('"string"'), c.punctuation(";"), + c.keyword("class"), c.className("C"), c.punctuation("<"), c.typeParameterName("T"), c.punctuation(">"), c.punctuation("{"), + c.punctuation("}"), + c.keyword("enum"), c.enumName("E"), c.punctuation("{"), + c.punctuation("}"), + c.keyword("interface"), c.interfaceName("I"), c.punctuation("{"), + c.punctuation("}"), + c.keyword("module"), c.moduleName("M1"), c.punctuation("."), c.moduleName("M2"), c.punctuation("{"), + c.punctuation("}"), + c.punctuation("}")); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getTodoComments.ts b/tests/cases/fourslash/shims/getTodoComments.ts new file mode 100644 index 00000000000..b1e0086b93f --- /dev/null +++ b/tests/cases/fourslash/shims/getTodoComments.ts @@ -0,0 +1,3 @@ +//// // [|TODO|] + +verify.todoCommentsInCurrentFile(["TODO"]); \ No newline at end of file diff --git a/tests/cases/fourslash/shims/quickInfoDisplayPartsVar.ts b/tests/cases/fourslash/shims/quickInfoDisplayPartsVar.ts new file mode 100644 index 00000000000..56ccceb3ab3 --- /dev/null +++ b/tests/cases/fourslash/shims/quickInfoDisplayPartsVar.ts @@ -0,0 +1,76 @@ +/// + +////var /*1*/a = 10; +////function foo() { +//// var /*2*/b = /*3*/a; +////} +////module m { +//// var /*4*/c = 10; +//// export var /*5*/d = 10; +////} +////var /*6*/f: () => number; +////var /*7*/g = /*8*/f; +/////*9*/f(); +////var /*10*/h: { (a: string): number; (a: number): string; }; +////var /*11*/i = /*12*/h; +/////*13*/h(10); +/////*14*/h("hello"); + +var marker = 0; +function verifyVar(name: string, isLocal: boolean, typeDisplay: ts.SymbolDisplayPart[], optionalNameDisplay?: ts.SymbolDisplayPart[], optionalKindModifiers?: string) { + marker++; + goTo.marker(marker.toString()); + var kind = isLocal ? "local var" : "var"; + verify.verifyQuickInfoDisplayParts(kind, optionalKindModifiers || "", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "(", kind: "punctuation" }, { text: kind, kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }].concat(optionalNameDisplay || [{ text: name, kind: "localName" }]).concat( + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }).concat(typeDisplay), + []); +} + +var numberTypeDisplay: ts.SymbolDisplayPart[] = [{ text: "number", kind: "keyword" }]; + +verifyVar("a", /*isLocal*/false, numberTypeDisplay); +verifyVar("b", /*isLocal*/true, numberTypeDisplay); +verifyVar("a", /*isLocal*/false, numberTypeDisplay); +verifyVar("c", /*isLocal*/false, numberTypeDisplay); +verifyVar("d", /*isLocal*/false, numberTypeDisplay, [{ text: "m", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "d", kind: "localName" }], "export"); + +var functionTypeReturningNumber: ts.SymbolDisplayPart[] = [{ text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "number", kind: "keyword" }]; +verifyVar("f", /*isLocal*/ false, functionTypeReturningNumber); +verifyVar("g", /*isLocal*/ false, functionTypeReturningNumber); +verifyVar("f", /*isLocal*/ false, functionTypeReturningNumber); +verifyVar("f", /*isLocal*/ false, functionTypeReturningNumber); + + +function getFunctionType(parametertype: string, returnType: string, isArrow?: boolean): ts.SymbolDisplayPart[] { + var functionTypeDisplay = [{ text: "(", kind: "punctuation" }, { text: "a", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: parametertype, kind: "keyword" }, { text: ")", kind: "punctuation" }]; + + if (isArrow) { + functionTypeDisplay = functionTypeDisplay.concat({ text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }); + } + else { + functionTypeDisplay = functionTypeDisplay.concat({ text: ":", kind: "punctuation" }); + } + + return functionTypeDisplay.concat({ text: " ", kind: "space" }, { text: returnType, kind: "keyword" }); +} + +var typeLiteralWithOverloadCall: ts.SymbolDisplayPart[] = [{ text: "{", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, + { text: " ", kind: "space" }].concat(getFunctionType("string", "number")).concat( + { text: ";", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, + { text: " ", kind: "space" }).concat(getFunctionType("number", "string")).concat( + { text: ";", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, { text: "}", kind: "punctuation" }); + +verifyVar("h", /*isLocal*/ false, typeLiteralWithOverloadCall); +verifyVar("i", /*isLocal*/ false, typeLiteralWithOverloadCall); +verifyVar("h", /*isLocal*/ false, typeLiteralWithOverloadCall); + +var overloadDisplay: ts.SymbolDisplayPart[] = [{ text: " ", kind: "space" }, { text: "(", kind: "punctuation" }, + { text: "+", kind: "operator" }, { text: "1", kind: "numericLiteral" }, + { text: " ", kind: "space" }, { text: "overload", kind: "text" }, { text: ")", kind: "punctuation" }]; + +verifyVar("h", /*isLocal*/ false, getFunctionType("number", "string", /*isArrow*/true).concat(overloadDisplay)); +verifyVar("h", /*isLocal*/ false, getFunctionType("string", "number", /*isArrow*/true).concat(overloadDisplay)); \ No newline at end of file