From 762e1eb0a886a13de3b62b771c1778ae506ccbd0 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 14 Nov 2015 13:57:11 -0800 Subject: [PATCH 1/4] cleanup harness code --- src/harness/compilerRunner.ts | 13 +- src/harness/fourslash.ts | 36 ++- src/harness/harness.ts | 330 ++++++++++---------------- src/harness/harnessLanguageService.ts | 10 +- src/harness/rwcRunner.ts | 4 +- src/harness/test262Runner.ts | 11 +- 6 files changed, 161 insertions(+), 243 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index fd8b248dfe2..85a51b8f2a4 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -55,7 +55,6 @@ class CompilerBaselineRunner extends RunnerBase { let rootDir: string; let result: Harness.Compiler.CompilerResult; - let program: ts.Program; let options: ts.CompilerOptions; // equivalent to the files that will be passed on the command line let toBeCompiled: Harness.Compiler.TestFile[]; @@ -89,12 +88,11 @@ class CompilerBaselineRunner extends RunnerBase { }); } - const output = Harness.Compiler.HarnessCompiler.compileFiles( + const output = Harness.Compiler.compileFiles( toBeCompiled, otherFiles, harnessSettings, /* options */ undefined, /* currentDirectory */ undefined); options = output.options; result = output.result; - program = output.program; }); after(() => { @@ -108,7 +106,6 @@ class CompilerBaselineRunner extends RunnerBase { lastUnit = undefined; rootDir = undefined; result = undefined; - program = undefined; options = undefined; toBeCompiled = undefined; otherFiles = undefined; @@ -181,7 +178,7 @@ class CompilerBaselineRunner extends RunnerBase { } const declFileCompilationResult = - Harness.Compiler.HarnessCompiler.compileDeclarationFiles( + Harness.Compiler.compileDeclarationFiles( toBeCompiled, otherFiles, result, harnessSettings, options, /*currentDirectory*/ undefined); if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) { @@ -253,10 +250,10 @@ class CompilerBaselineRunner extends RunnerBase { // These types are equivalent, but depend on what order the compiler observed // certain parts of the program. - const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName)); + const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!result.program.getSourceFile(file.unitName)); - const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true); - const pullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ false); + const fullWalker = new TypeWriterWalker(result.program, /*fullTypeCheck*/ true); + const pullWalker = new TypeWriterWalker(result.program, /*fullTypeCheck*/ false); const fullResults: ts.Map = {}; const pullResults: ts.Map = {}; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ebc58096d6f..f62e1c58412 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2383,10 +2383,9 @@ namespace FourSlash { // here we cache the JS output and reuse it for every test. let fourslashJsOutput: string; { - const fourslashFile: Harness.Compiler.TestFileWithPath = { + const fourslashFile: Harness.Compiler.TestFile = { unitName: Harness.Compiler.fourslashFileName, - content: undefined, - path: ts.toPath(Harness.Compiler.fourslashFileName, Harness.IO.getCurrentDirectory(), Harness.Compiler.getCanonicalFileName) + content: undefined }; const host = Harness.Compiler.createCompilerHost([fourslashFile], (fn, contents) => fourslashJsOutput = contents, @@ -2399,35 +2398,28 @@ namespace FourSlash { program.emit(host.getSourceFile(Harness.Compiler.fourslashFileName, ts.ScriptTarget.ES3)); } - export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): TestXmlData { // Parse out the files and their metadata const testData = parseTestData(basePath, content, fileName); currentTestState = new TestState(basePath, testType, testData); - const currentDirectory = Harness.IO.getCurrentDirectory(); - const useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames(); - const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); - let result = ""; - const fourslashFile: Harness.Compiler.TestFileWithPath = { + const fourslashFile: Harness.Compiler.TestFile = { unitName: Harness.Compiler.fourslashFileName, content: undefined, - path: ts.toPath(Harness.Compiler.fourslashFileName, currentDirectory, getCanonicalFileName) }; - const testFile: Harness.Compiler.TestFileWithPath = { + const testFile: Harness.Compiler.TestFile = { unitName: fileName, - content: content, - path: ts.toPath(fileName, currentDirectory, getCanonicalFileName) + content: content }; const host = Harness.Compiler.createCompilerHost( [ fourslashFile, testFile ], (fn, contents) => result = contents, ts.ScriptTarget.Latest, - useCaseSensitiveFileNames, - currentDirectory); + Harness.IO.useCaseSensitiveFileNames(), + Harness.IO.getCurrentDirectory()); const program = ts.createProgram([Harness.Compiler.fourslashFileName, fileName], { outFile: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host); @@ -2444,18 +2436,22 @@ namespace FourSlash { result = fourslashJsOutput + "\r\n" + result; + runCode(result); + + const xmlData = currentTestState.getTestXmlData(); + xmlData.originalName = fileName; + return xmlData; + } + + function runCode(code: string): void { // Compile and execute the test try { - eval(result); + eval(code); } catch (err) { // Debugging: FourSlash.currentTestState.printCurrentFileState(); throw err; } - - const xmlData = currentTestState.getTestXmlData(); - xmlData.originalName = fileName; - return xmlData; } function chompLeadingSpace(content: string) { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 9bc36e257ad..e58e6635434 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -767,25 +767,8 @@ namespace Harness { } namespace Harness { - let tcServicesFileName = "typescriptServices.js"; - - export let libFolder: string; - switch (Utils.getExecutionEnvironment()) { - case Utils.ExecutionEnvironment.CScript: - libFolder = "built/local/"; - tcServicesFileName = "built/local/typescriptServices.js"; - break; - case Utils.ExecutionEnvironment.Node: - libFolder = "built/local/"; - tcServicesFileName = "built/local/typescriptServices.js"; - break; - case Utils.ExecutionEnvironment.Browser: - libFolder = "built/local/"; - tcServicesFileName = "built/local/typescriptServices.js"; - break; - default: - throw new Error("Unknown context"); - } + const tcServicesFileName = "built/local/typescriptServices.js"; + export const libFolder = "built/local/"; export let tcServicesFile = IO.readFile(tcServicesFileName); export interface SourceMapEmitterCallback { @@ -827,57 +810,14 @@ namespace Harness { } } - export interface IEmitterIOHost { - writeFile(path: string, contents: string, writeByteOrderMark: boolean): void; - resolvePath(path: string): string; - } - - /** Mimics having multiple files, later concatenated to a single file. */ - export class EmitterIOHost implements IEmitterIOHost { - private fileCollection: any = {}; - - /** create file gets the whole path to create, so this works as expected with the --out parameter */ - public writeFile(s: string, contents: string, writeByteOrderMark: boolean): void { - let writer: ITextWriter; - if (this.fileCollection[s]) { - writer = this.fileCollection[s]; - } - else { - writer = new Harness.Compiler.WriterAggregator(); - this.fileCollection[s] = writer; - } - - writer.Write(contents); - writer.Close(); - } - - public resolvePath(s: string) { return s; } - - public reset() { this.fileCollection = {}; } - - public toArray(): { fileName: string; file: WriterAggregator; }[] { - const result: { fileName: string; file: WriterAggregator; }[] = []; - for (const p in this.fileCollection) { - if (this.fileCollection.hasOwnProperty(p)) { - const current = this.fileCollection[p]; - if (current.lines.length > 0) { - if (p.indexOf(".d.ts") !== -1) { current.lines.unshift(["////[", Path.getFileName(p), "]"].join("")); } - result.push({ fileName: p, file: this.fileCollection[p] }); - } - } - } - return result; - } - } - export function createSourceFileAndAssertInvariants( fileName: string, sourceText: string, languageVersion: ts.ScriptTarget) { - // We'll only assert inletiants outside of light mode. + // We'll only assert invariants outside of light mode. const shouldAssertInvariants = !Harness.lightMode; - // Only set the parent nodes if we're asserting inletiants. We don't need them otherwise. + // Only set the parent nodes if we're asserting invariants. We don't need them otherwise. const result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ shouldAssertInvariants); if (shouldAssertInvariants) { @@ -890,12 +830,12 @@ namespace Harness { const carriageReturnLineFeed = "\r\n"; const lineFeed = "\n"; - export let defaultLibFileName = "lib.d.ts"; - export let defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); - export let defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.es6.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); + export const defaultLibFileName = "lib.d.ts"; + export const defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); + export const defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.core.es6.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); // Cache these between executions so we don't have to re-parse them for every test - export let fourslashFileName = "fourslash.ts"; + export const fourslashFileName = "fourslash.ts"; export let fourslashSourceFile: ts.SourceFile; export function getCanonicalFileName(fileName: string): string { @@ -903,7 +843,7 @@ namespace Harness { } export function createCompilerHost( - inputFiles: TestFileWithPath[], + inputFiles: TestFile[], writeFile: (fn: string, contents: string, writeByteOrderMark: boolean) => void, scriptTarget: ts.ScriptTarget, useCaseSensitiveFileNames: boolean, @@ -915,16 +855,14 @@ namespace Harness { const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); const fileMap: ts.FileMap = ts.createFileMap(); - - // Register input files - function register(file: TestFileWithPath) { + for (const file of inputFiles) { if (file.content !== undefined) { const fileName = ts.normalizePath(file.unitName); const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget); - fileMap.set(file.path, sourceFile); + const path = ts.toPath(file.unitName, currentDirectory, getCanonicalFileName); + fileMap.set(path, sourceFile); } - }; - inputFiles.forEach(register); + } function getSourceFile(fn: string, languageVersion: ts.ScriptTarget) { fn = ts.normalizePath(fn); @@ -1031,147 +969,133 @@ namespace Harness { unitName: string; content: string; } - export interface TestFileWithPath extends TestFile { - path: ts.Path; - } export interface CompilationOutput { result: CompilerResult; - program: ts.Program; options: ts.CompilerOptions & HarnessOptions; } - export namespace HarnessCompiler { - export function compileFiles( - inputFiles: TestFile[], - otherFiles: TestFile[], - harnessSettings: TestCaseParser.CompilerSettings, - compilerOptions: ts.CompilerOptions, - // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file - currentDirectory: string): CompilationOutput { + export function compileFiles( + inputFiles: TestFile[], + otherFiles: TestFile[], + harnessSettings: TestCaseParser.CompilerSettings, + compilerOptions: ts.CompilerOptions, + // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file + currentDirectory: string): CompilationOutput { - const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.clone(compilerOptions) : { noResolve: false }; - options.target = options.target || ts.ScriptTarget.ES3; - options.module = options.module || ts.ModuleKind.None; - options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed; - options.noErrorTruncation = true; - options.skipDefaultLibCheck = true; + const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.clone(compilerOptions) : { noResolve: false }; + options.target = options.target || ts.ScriptTarget.ES3; + options.module = options.module || ts.ModuleKind.None; + options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed; + options.noErrorTruncation = true; + options.skipDefaultLibCheck = true; - const newLine = "\r\n"; - currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory(); + const newLine = "\r\n"; + currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory(); - // Parse settings - let useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames(); - if (harnessSettings) { - setCompilerOptionsFromHarnessSetting(harnessSettings, options); - } - if (options.useCaseSensitiveFileNames !== undefined) { - useCaseSensitiveFileNames = options.useCaseSensitiveFileNames; - } - const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); - const inputFilesWithPath = inputFiles.map(f => { - return { unitName: f.unitName, content: f.content, path: ts.toPath(f.unitName, currentDirectory, getCanonicalFileName) }; - }); - const otherFilesWithPath = otherFiles.map(f => { - return { unitName: f.unitName, content: f.content, path: ts.toPath(f.unitName, currentDirectory, getCanonicalFileName) }; - }); - - // Files from built\local that are requested by test "@includeBuiltFiles" to be in the context. - // Treat them as library files, so include them in build, but not in baselines. - const includeBuiltFiles: TestFileWithPath[] = []; - if (options.includeBuiltFile) { - const builtFileName = libFolder + options.includeBuiltFile; - const builtFile: TestFileWithPath = { - unitName: builtFileName, - content: normalizeLineEndings(IO.readFile(builtFileName), newLine), - path: ts.toPath(builtFileName, currentDirectory, getCanonicalFileName) - }; - includeBuiltFiles.push(builtFile); - } - - const fileOutputs: GeneratedFile[] = []; - - const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); - - const compilerHost = createCompilerHost( - inputFilesWithPath.concat(includeBuiltFiles).concat(otherFilesWithPath), - (fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }), - options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine); - const program = ts.createProgram(programFiles, options, compilerHost); - - const emitResult = program.emit(); - - const errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); - - const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps); - return { result, program, options }; + // Parse settings + let useCaseSensitiveFileNames = Harness.IO.useCaseSensitiveFileNames(); + if (harnessSettings) { + setCompilerOptionsFromHarnessSetting(harnessSettings, options); + } + if (options.useCaseSensitiveFileNames !== undefined) { + useCaseSensitiveFileNames = options.useCaseSensitiveFileNames; } - export function compileDeclarationFiles(inputFiles: TestFile[], - otherFiles: TestFile[], - result: CompilerResult, - harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions, - options: ts.CompilerOptions, - // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file - currentDirectory: string) { - if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) { - throw new Error("There were no errors and declFiles generated did not match number of js files generated"); + // Files from built\local that are requested by test "@includeBuiltFiles" to be in the context. + // Treat them as library files, so include them in build, but not in baselines. + const includeBuiltFiles: TestFile[] = []; + if (options.includeBuiltFile) { + const builtFileName = libFolder + options.includeBuiltFile; + const builtFile: TestFile = { + unitName: builtFileName, + content: normalizeLineEndings(IO.readFile(builtFileName), newLine), + }; + includeBuiltFiles.push(builtFile); + } + + const fileOutputs: GeneratedFile[] = []; + + const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); + + const compilerHost = createCompilerHost( + inputFiles.concat(includeBuiltFiles).concat(otherFiles), + (fileName, code, writeByteOrderMark) => fileOutputs.push({ fileName, code, writeByteOrderMark }), + options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine); + const program = ts.createProgram(programFiles, options, compilerHost); + + const emitResult = program.emit(); + + const errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + + const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps); + return { result, options }; + } + + export function compileDeclarationFiles(inputFiles: TestFile[], + otherFiles: TestFile[], + result: CompilerResult, + harnessSettings: TestCaseParser.CompilerSettings & HarnessOptions, + options: ts.CompilerOptions, + // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file + currentDirectory: string) { + if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) { + throw new Error("There were no errors and declFiles generated did not match number of js files generated"); + } + + const declInputFiles: TestFile[] = []; + const declOtherFiles: TestFile[] = []; + + // if the .d.ts is non-empty, confirm it compiles correctly as well + if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) { + ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); + ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles)); + const output = compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory); + + return { declInputFiles, declOtherFiles, declResult: output.result }; + } + + function addDtsFile(file: TestFile, dtsFiles: TestFile[]) { + if (isDTS(file.unitName)) { + dtsFiles.push(file); } - - const declInputFiles: TestFile[] = []; - const declOtherFiles: TestFile[] = []; - - // if the .d.ts is non-empty, confirm it compiles correctly as well - if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) { - ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); - ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles)); - const output = this.compileFiles(declInputFiles, declOtherFiles, harnessSettings, options, currentDirectory); - - return { declInputFiles, declOtherFiles, declResult: output.result }; - } - - function addDtsFile(file: TestFile, dtsFiles: TestFile[]) { - if (isDTS(file.unitName)) { - dtsFiles.push(file); - } - else if (isTS(file.unitName)) { - const declFile = findResultCodeFile(file.unitName); - if (declFile && !findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) { - dtsFiles.push({ unitName: declFile.fileName, content: declFile.code }); - } - } - - function findResultCodeFile(fileName: string) { - const sourceFile = result.program.getSourceFile(fileName); - assert(sourceFile, "Program has no source file with name '" + fileName + "'"); - // Is this file going to be emitted separately - let sourceFileName: string; - const outFile = options.outFile || options.out; - if (ts.isExternalModule(sourceFile) || !outFile) { - if (options.outDir) { - let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram); - sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), ""); - sourceFileName = ts.combinePaths(options.outDir, sourceFilePath); - } - else { - sourceFileName = sourceFile.fileName; - } - } - else { - // Goes to single --out file - sourceFileName = outFile; - } - - const dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts"; - - return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined); - } - - function findUnit(fileName: string, units: TestFile[]) { - return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined); + else if (isTS(file.unitName)) { + const declFile = findResultCodeFile(file.unitName); + if (declFile && !findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) { + dtsFiles.push({ unitName: declFile.fileName, content: declFile.code }); } } } + + function findResultCodeFile(fileName: string) { + const sourceFile = result.program.getSourceFile(fileName); + assert(sourceFile, "Program has no source file with name '" + fileName + "'"); + // Is this file going to be emitted separately + let sourceFileName: string; + const outFile = options.outFile || options.out; + if (ts.isExternalModule(sourceFile) || !outFile) { + if (options.outDir) { + let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram); + sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), ""); + sourceFileName = ts.combinePaths(options.outDir, sourceFilePath); + } + else { + sourceFileName = sourceFile.fileName; + } + } + else { + // Goes to single --out file + sourceFileName = outFile; + } + + const dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts"; + + return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined); + } + + function findUnit(fileName: string, units: TestFile[]) { + return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined); + } } function normalizeLineEndings(text: string, lineEnding: string): string { @@ -1388,7 +1312,7 @@ namespace Harness { constructor(fileResults: GeneratedFile[], errors: ts.Diagnostic[], public program: ts.Program, public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[]) { - fileResults.forEach(emittedFile => { + for (const emittedFile of fileResults) { if (isDTS(emittedFile.fileName)) { // .d.ts file, add to declFiles emit this.declFilesCode.push(emittedFile); @@ -1403,7 +1327,7 @@ namespace Harness { else { throw new Error("Unrecognized file extension for file " + emittedFile.fileName); } - }); + } this.errors = errors; } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 0c267c38f14..3c7814df562 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -7,7 +7,7 @@ namespace Harness.LanguageService { export class ScriptInfo { public version: number = 1; public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = []; - public lineMap: number[] = undefined; + private lineMap: number[] = undefined; constructor(public fileName: string, public content: string) { this.setContent(content); @@ -15,7 +15,11 @@ namespace Harness.LanguageService { private setContent(content: string): void { this.content = content; - this.lineMap = ts.computeLineStarts(content); + this.lineMap = undefined; + } + + public getLineMap(): number[] { + return this.lineMap || (this.lineMap = ts.computeLineStarts(this.content)); } public updateContent(content: string): void { @@ -164,7 +168,7 @@ namespace Harness.LanguageService { const script: ScriptInfo = this.fileNameToScript[fileName]; assert.isNotNull(script); - return ts.computeLineAndCharacterOfPosition(script.lineMap, position); + return ts.computeLineAndCharacterOfPosition(script.getLineMap(), position); } } diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index fc1397b294c..ce570a7d6ad 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -126,7 +126,7 @@ namespace RWC { // Emit the results compilerOptions = null; - const output = Harness.Compiler.HarnessCompiler.compileFiles( + const output = Harness.Compiler.compileFiles( inputFiles, otherFiles, /* harnessOptions */ undefined, @@ -202,7 +202,7 @@ namespace RWC { it("has the expected errors in generated declaration files", () => { if (compilerOptions.declaration && !compilerResult.errors.length) { Harness.Baseline.runBaseline("has the expected errors in generated declaration files", baseName + ".dts.errors.txt", () => { - const declFileCompilationResult = Harness.Compiler.HarnessCompiler.compileDeclarationFiles( + const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles( inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined, compilerOptions, currentDirectory); if (declFileCompilationResult.declResult.errors.length === 0) { diff --git a/src/harness/test262Runner.ts b/src/harness/test262Runner.ts index 859f10dc4cc..262145b4764 100644 --- a/src/harness/test262Runner.ts +++ b/src/harness/test262Runner.ts @@ -32,7 +32,6 @@ class Test262BaselineRunner extends RunnerBase { filename: string; compilerResult: Harness.Compiler.CompilerResult; inputFiles: Harness.Compiler.TestFile[]; - program: ts.Program; }; before(() => { @@ -50,10 +49,9 @@ class Test262BaselineRunner extends RunnerBase { filename: testFilename, inputFiles: inputFiles, compilerResult: undefined, - program: undefined, }; - const output = Harness.Compiler.HarnessCompiler.compileFiles( + const output = Harness.Compiler.compileFiles( [Test262BaselineRunner.helperFile].concat(inputFiles), /*otherFiles*/ [], /* harnessOptions */ undefined, @@ -61,7 +59,6 @@ class Test262BaselineRunner extends RunnerBase { /* currentDirectory */ undefined ); testState.compilerResult = output.result; - testState.program = output.program; }); after(() => { @@ -86,14 +83,14 @@ class Test262BaselineRunner extends RunnerBase { }, false, Test262BaselineRunner.baselineOptions); }); - it("satisfies inletiants", () => { - const sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + it("satisfies invariants", () => { + const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); Utils.assertInvariants(sourceFile, /*parent:*/ undefined); }); it("has the expected AST", () => { Harness.Baseline.runBaseline("has the expected AST", testState.filename + ".AST.txt", () => { - const sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + const sourceFile = testState.compilerResult.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); return Utils.sourceFileToJSON(sourceFile); }, false, Test262BaselineRunner.baselineOptions); }); From 8039909913be85531b09cef6cc31a61542cc5408 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Nov 2015 10:36:13 -0800 Subject: [PATCH 2/4] remove Tao generation --- src/harness/fourslash.ts | 282 +++++---------------------------- src/harness/fourslashRunner.ts | 50 ------ 2 files changed, 37 insertions(+), 295 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index f62e1c58412..88458beaba4 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -48,12 +48,6 @@ namespace FourSlash { ranges: Range[]; } - export interface TestXmlData { - invalidReason: string; - originalName: string; - actions: string[]; - } - interface MemberListData { result: { maybeInaccurate: boolean; @@ -84,14 +78,14 @@ namespace FourSlash { marker?: Marker; } - interface ILocationInformation { + interface LocationInformation { position: number; sourcePosition: number; sourceLine: number; sourceColumn: number; } - interface IRangeLocationInformation extends ILocationInformation { + interface RangeLocationInformation extends LocationInformation { marker?: Marker; } @@ -134,11 +128,6 @@ namespace FourSlash { return settings; } - export let currentTestState: TestState = null; - function assertionMessage(msg: string) { - return "\nMarker: " + currentTestState.lastKnownMarker + "\nChecking: " + msg + "\n\n"; - } - export class TestCancellationToken implements ts.HostCancellationToken { // 0 - cancelled // >0 - not cancelled @@ -216,9 +205,6 @@ namespace FourSlash { public formatCodeOptions: ts.FormatCodeOptions; - private scenarioActions: string[] = []; - private taoInvalidReason: string = null; - private inputFiles: ts.Map = {}; // Map between inputFile's fileName and its content for easily looking up when resolving references // Add input file which has matched file name with the given reference-file path. @@ -338,7 +324,6 @@ namespace FourSlash { this.testData.files.forEach(file => { const fileName = file.fileName.replace(Harness.IO.directoryName(file.fileName), "").substr(1); const fileNameWithoutExtension = fileName.substr(0, fileName.lastIndexOf(".")); - this.scenarioActions.push(""); }); // Open the first file by default @@ -367,21 +352,11 @@ namespace FourSlash { public goToPosition(pos: number) { this.currentCaretPosition = pos; - - const lineStarts = ts.computeLineStarts(this.getFileContent(this.activeFile.fileName)); - const lineCharPos = ts.computeLineAndCharacterOfPosition(lineStarts, pos); - this.scenarioActions.push(``); } public moveCaretRight(count = 1) { this.currentCaretPosition += count; this.currentCaretPosition = Math.min(this.currentCaretPosition, this.getFileContent(this.activeFile.fileName).length); - if (count > 0) { - this.scenarioActions.push(``); - } - else { - this.scenarioActions.push(``); - } } // Opens a file given its 0-based index or fileName @@ -391,9 +366,6 @@ namespace FourSlash { const fileToOpen: FourSlashFile = this.findFile(indexOrName); fileToOpen.fileName = ts.normalizeSlashes(fileToOpen.fileName); this.activeFile = fileToOpen; - const fileName = fileToOpen.fileName.replace(Harness.IO.directoryName(fileToOpen.fileName), "").substr(1); - this.scenarioActions.push(``); - // Let the host know that this file is now open this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content); } @@ -407,8 +379,6 @@ namespace FourSlash { const exists = this.anyErrorInRange(predicate, startMarker, endMarker); - this.taoInvalidReason = "verifyErrorExistsBetweenMarkers NYI"; - if (exists !== negative) { this.printErrorLog(negative, this.getAllDiagnostics()); throw new Error("Failure between markers: " + startMarkerName + ", " + endMarkerName); @@ -421,7 +391,11 @@ namespace FourSlash { } private messageAtLastKnownMarker(message: string) { - return "Marker: " + currentTestState.lastKnownMarker + "\n" + message; + return "Marker: " + this.lastKnownMarker + "\n" + message; + } + + private assertionMessageAtLastKnownMarker(msg: string) { + return "\nMarker: " + this.lastKnownMarker + "\nChecking: " + msg + "\n\n"; } private getDiagnostics(fileName: string): ts.Diagnostic[] { @@ -461,8 +435,6 @@ namespace FourSlash { }; } - this.taoInvalidReason = "verifyErrorExistsAfterMarker NYI"; - const exists = this.anyErrorInRange(predicate, marker); const diagnostics = this.getAllDiagnostics(); @@ -511,8 +483,6 @@ namespace FourSlash { const errors = this.getDiagnostics(this.activeFile.fileName); const actual = errors.length; - this.scenarioActions.push(``); - if (actual !== expected) { this.printErrorLog(/*expectErrors*/ false, errors); const errorMsg = "Actual number of errors (" + actual + ") does not match expected number (" + expected + ")"; @@ -527,8 +497,6 @@ namespace FourSlash { throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName); } - this.taoInvalidReason = "verifyEval impossible"; - const evaluation = new Function(`${emit.outputFiles[0].text};\r\nreturn (${expr});`)(); if (evaluation !== value) { this.raiseError(`Expected evaluation of expression "${expr}" to equal "${value}", but got "${evaluation}"`); @@ -540,7 +508,6 @@ namespace FourSlash { if (emit.outputFiles.length !== 1) { throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName); } - this.taoInvalidReason = "verifyGetEmitOutputForCurrentFile impossible"; const actual = emit.outputFiles[0].text; if (actual !== expected) { this.raiseError(`Expected emit output to be "${expected}", but got "${actual}"`); @@ -548,13 +515,6 @@ namespace FourSlash { } public verifyMemberListContains(symbol: string, text?: string, documentation?: string, kind?: string) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - - if (text || documentation || kind) { - this.taoInvalidReason = "verifyMemberListContains only supports the \"symbol\" parameter"; - } - const members = this.getMemberListAtCaret(); if (members) { this.assertItemInCompletionList(members.entries, symbol, text, documentation, kind); @@ -565,18 +525,9 @@ namespace FourSlash { } public verifyMemberListCount(expectedCount: number, negative: boolean) { - if (expectedCount === 0) { - if (negative) { - this.verifyMemberListIsEmpty(/*negative*/ false); - return; - } - else { - this.scenarioActions.push(""); - } - } - else { - this.scenarioActions.push(""); - this.scenarioActions.push(``); + if (expectedCount === 0 && negative) { + this.verifyMemberListIsEmpty(/*negative*/ false); + return; } const members = this.getMemberListAtCaret(); @@ -594,9 +545,6 @@ namespace FourSlash { } public verifyMemberListDoesNotContain(symbol: string) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - const members = this.getMemberListAtCaret(); if (members && members.entries.filter(e => e.name === symbol).length !== 0) { this.raiseError(`Member list did contain ${symbol}`); @@ -604,8 +552,6 @@ namespace FourSlash { } public verifyCompletionListItemsCountIsGreaterThan(count: number, negative: boolean) { - this.taoInvalidReason = "verifyCompletionListItemsCountIsGreaterThan NYI"; - const completions = this.getCompletionListAtCaret(); const itemsCount = completions.entries.length; @@ -622,13 +568,6 @@ namespace FourSlash { } public verifyMemberListIsEmpty(negative: boolean) { - if (negative) { - this.scenarioActions.push(""); - } - else { - this.scenarioActions.push(""); - } - const members = this.getMemberListAtCaret(); if ((!members || members.entries.length === 0) && negative) { this.raiseError("Member list is empty at Caret"); @@ -647,8 +586,6 @@ namespace FourSlash { } public verifyCompletionListIsEmpty(negative: boolean) { - this.scenarioActions.push(""); - const completions = this.getCompletionListAtCaret(); if ((!completions || completions.entries.length === 0) && negative) { this.raiseError("Completion list is empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition); @@ -716,8 +653,6 @@ namespace FourSlash { // and keep it in the list of filtered entry. return true; } - this.scenarioActions.push(""); - this.scenarioActions.push(``); const completions = this.getCompletionListAtCaret(); if (completions) { @@ -745,24 +680,20 @@ namespace FourSlash { } public verifyCompletionEntryDetails(entryName: string, expectedText: string, expectedDocumentation?: string, kind?: string) { - this.taoInvalidReason = "verifyCompletionEntryDetails NYI"; - const details = this.getCompletionEntryDetails(entryName); - assert.equal(ts.displayPartsToString(details.displayParts), expectedText, assertionMessage("completion entry details text")); + assert.equal(ts.displayPartsToString(details.displayParts), expectedText, this.assertionMessageAtLastKnownMarker("completion entry details text")); if (expectedDocumentation !== undefined) { - assert.equal(ts.displayPartsToString(details.documentation), expectedDocumentation, assertionMessage("completion entry documentation")); + assert.equal(ts.displayPartsToString(details.documentation), expectedDocumentation, this.assertionMessageAtLastKnownMarker("completion entry documentation")); } if (kind !== undefined) { - assert.equal(details.kind, kind, assertionMessage("completion entry kind")); + assert.equal(details.kind, kind, this.assertionMessageAtLastKnownMarker("completion entry kind")); } } public verifyReferencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) { - this.taoInvalidReason = "verifyReferencesAtPositionListContains NYI"; - const references = this.getReferencesAtCaret(); if (!references || references.length === 0) { @@ -784,8 +715,6 @@ namespace FourSlash { } public verifyReferencesCountIs(count: number, localFilesOnly = true) { - this.taoInvalidReason = "verifyReferences NYI"; - const references = this.getReferencesAtCaret(); let referencesCount = 0; @@ -845,13 +774,6 @@ namespace FourSlash { } public verifyQuickInfoString(negative: boolean, expectedText?: string, expectedDocumentation?: string) { - [expectedText, expectedDocumentation].forEach(str => { - if (str) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - } - }); - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); const actualQuickInfoText = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.displayParts) : ""; const actualQuickInfoDocumentation = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.documentation) : ""; @@ -871,7 +793,7 @@ namespace FourSlash { } // TODO: should be '==='? if (expectedDocumentation != undefined) { - assert.equal(actualQuickInfoDocumentation, expectedDocumentation, assertionMessage("quick info doc")); + assert.equal(actualQuickInfoDocumentation, expectedDocumentation, this.assertionMessageAtLastKnownMarker("quick info doc")); } } } @@ -879,8 +801,6 @@ namespace FourSlash { public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; }, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); function getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) { let result = ""; @@ -947,8 +867,6 @@ namespace FourSlash { } public verifyQuickInfoExists(negative: boolean) { - this.taoInvalidReason = "verifyQuickInfoExists NYI"; - const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (negative) { if (actualQuickInfo) { @@ -963,8 +881,6 @@ namespace FourSlash { } public verifyCurrentSignatureHelpIs(expected: string) { - this.taoInvalidReason = "verifyCurrentSignatureHelpIs NYI"; - const help = this.getActiveSignatureHelpItem(); assert.equal( ts.displayPartsToString(help.prefixDisplayParts) + @@ -973,75 +889,51 @@ namespace FourSlash { } public verifyCurrentParameterIsletiable(isVariable: boolean) { - this.taoInvalidReason = "verifyCurrentParameterIsletiable NYI"; - const signature = this.getActiveSignatureHelpItem(); assert.isNotNull(signature); assert.equal(isVariable, signature.isVariadic); } public verifyCurrentParameterHelpName(name: string) { - this.taoInvalidReason = "verifyCurrentParameterHelpName NYI"; - const activeParameter = this.getActiveParameter(); const activeParameterName = activeParameter.name; assert.equal(activeParameterName, name); } public verifyCurrentParameterSpanIs(parameter: string) { - this.taoInvalidReason = "verifyCurrentParameterSpanIs NYI"; - const activeSignature = this.getActiveSignatureHelpItem(); const activeParameter = this.getActiveParameter(); assert.equal(ts.displayPartsToString(activeParameter.displayParts), parameter); } public verifyCurrentParameterHelpDocComment(docComment: string) { - this.taoInvalidReason = "verifyCurrentParameterHelpDocComment NYI"; - const activeParameter = this.getActiveParameter(); const activeParameterDocComment = activeParameter.documentation; - assert.equal(ts.displayPartsToString(activeParameterDocComment), docComment, assertionMessage("current parameter Help DocComment")); + assert.equal(ts.displayPartsToString(activeParameterDocComment), docComment, this.assertionMessageAtLastKnownMarker("current parameter Help DocComment")); } public verifyCurrentSignatureHelpParameterCount(expectedCount: number) { - this.taoInvalidReason = "verifyCurrentSignatureHelpParameterCount NYI"; - assert.equal(this.getActiveSignatureHelpItem().parameters.length, expectedCount); } - public verifyCurrentSignatureHelpTypeParameterCount(expectedCount: number) { - this.taoInvalidReason = "verifyCurrentSignatureHelpTypeParameterCount NYI"; - - // assert.equal(this.getActiveSignatureHelpItem().typeParameters.length, expectedCount); - } - public verifyCurrentSignatureHelpDocComment(docComment: string) { - this.taoInvalidReason = "verifyCurrentSignatureHelpDocComment NYI"; - const actualDocComment = this.getActiveSignatureHelpItem().documentation; - assert.equal(ts.displayPartsToString(actualDocComment), docComment, assertionMessage("current signature help doc comment")); + assert.equal(ts.displayPartsToString(actualDocComment), docComment, this.assertionMessageAtLastKnownMarker("current signature help doc comment")); } public verifySignatureHelpCount(expected: number) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); const actual = help && help.items ? help.items.length : 0; assert.equal(actual, expected); } public verifySignatureHelpArgumentCount(expected: number) { - this.taoInvalidReason = "verifySignatureHelpArgumentCount NYI"; const signatureHelpItems = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); const actual = signatureHelpItems.argumentCount; assert.equal(actual, expected); } public verifySignatureHelpPresent(shouldBePresent = true) { - this.taoInvalidReason = "verifySignatureHelpPresent NYI"; - const actual = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); if (shouldBePresent) { if (!actual) { @@ -1184,13 +1076,10 @@ namespace FourSlash { } public getBreakpointStatementLocation(pos: number) { - this.taoInvalidReason = "getBreakpointStatementLocation NYI"; return this.languageService.getBreakpointStatementAtPosition(this.activeFile.fileName, pos); } public baselineCurrentFileBreakpointLocations() { - this.taoInvalidReason = "baselineCurrentFileBreakpointLocations impossible"; - Harness.Baseline.runBaseline( "Breakpoint Locations for " + this.activeFile.fileName, this.testData.globalOptions[metadataOptionNames.baselineFile], @@ -1201,7 +1090,6 @@ namespace FourSlash { } public baselineGetEmitOutput() { - this.taoInvalidReason = "baselineGetEmitOutput impossible"; // Find file to be emitted const emitFiles: FourSlashFile[] = []; // List of FourSlashFile that has emitThisFile flag on @@ -1327,8 +1215,6 @@ namespace FourSlash { } public deleteChar(count = 1) { - this.scenarioActions.push(``); - let offset = this.currentCaretPosition; const ch = ""; @@ -1340,7 +1226,7 @@ namespace FourSlash { this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch); if (i % checkCadence === 0) { - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } // Handle post-keystroke formatting @@ -1357,20 +1243,16 @@ namespace FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } public replace(start: number, length: number, text: string) { - this.taoInvalidReason = "replace NYI"; - this.languageServiceAdapterHost.editScript(this.activeFile.fileName, start, start + length, text); this.updateMarkersForEdit(this.activeFile.fileName, start, start + length, text); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } public deleteCharBehindMarker(count = 1) { - this.scenarioActions.push(``); - let offset = this.currentCaretPosition; const ch = ""; const checkCadence = (count >> 2) + 1; @@ -1382,7 +1264,7 @@ namespace FourSlash { this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch); if (i % checkCadence === 0) { - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } // Handle post-keystroke formatting @@ -1398,18 +1280,11 @@ namespace FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } // Enters lines of text at the current caret position public type(text: string) { - if (text === "") { - this.taoInvalidReason = "Test used empty-insert workaround."; - } - else { - this.scenarioActions.push(``); - } - return this.typeHighFidelity(text); } @@ -1440,7 +1315,7 @@ namespace FourSlash { } if (i % checkCadence === 0) { - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); // this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); // this.languageService.getSemanticDiagnostics(this.activeFile.fileName); } @@ -1459,18 +1334,16 @@ namespace FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } // Enters text as if the user had pasted it public paste(text: string) { - this.scenarioActions.push(``); - const start = this.currentCaretPosition; let offset = this.currentCaretPosition; this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset, text); this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, text); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); offset += text.length; // Handle formatting @@ -1478,7 +1351,7 @@ namespace FourSlash { const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions); if (edits.length) { offset += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } } @@ -1486,10 +1359,10 @@ namespace FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInletiants(); + this.checkPostEditInvariants(); } - private checkPostEditInletiants() { + private checkPostEditInvariants() { if (this.testType !== FourSlashTestType.Native) { // getSourcefile() results can not be serialized. Only perform these verifications // if running against a native LS object. @@ -1560,16 +1433,12 @@ namespace FourSlash { } public formatDocument() { - this.scenarioActions.push(""); - const edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeOptions); this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); this.fixCaretPosition(); } public formatSelection(start: number, end: number) { - this.taoInvalidReason = "formatSelection NYI"; - const edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeOptions); this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true); this.fixCaretPosition(); @@ -1603,13 +1472,6 @@ namespace FourSlash { } public goToDefinition(definitionIndex: number) { - if (definitionIndex === 0) { - this.scenarioActions.push(""); - } - else { - this.taoInvalidReason = "GoToDefinition not supported for non-zero definition indices"; - } - const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (!definitions || !definitions.length) { this.raiseError("goToDefinition failed - expected to at least one definition location but got 0"); @@ -1625,13 +1487,6 @@ namespace FourSlash { } public goToTypeDefinition(definitionIndex: number) { - if (definitionIndex === 0) { - this.scenarioActions.push(""); - } - else { - this.taoInvalidReason = "GoToTypeDefinition not supported for non-zero definition indices"; - } - const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (!definitions || !definitions.length) { this.raiseError("goToTypeDefinition failed - expected to at least one definition location but got 0"); @@ -1647,8 +1502,6 @@ namespace FourSlash { } public verifyDefinitionLocationExists(negative: boolean) { - this.taoInvalidReason = "verifyDefinitionLocationExists NYI"; - const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); const foundDefinitions = definitions && definitions.length; @@ -1680,8 +1533,6 @@ namespace FourSlash { } public verifyDefinitionsName(negative: boolean, expectedName: string, expectedContainerName: string) { - this.taoInvalidReason = "verifyDefinititionsInfo NYI"; - const definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); const actualDefinitionName = definitions && definitions.length ? definitions[0].name : ""; const actualDefinitionContainerName = definitions && definitions.length ? definitions[0].containerName : ""; @@ -1706,8 +1557,6 @@ namespace FourSlash { } public verifyCaretAtMarker(markerName = "") { - this.taoInvalidReason = "verifyCaretAtMarker NYI"; - const pos = this.getMarkerByName(markerName); if (pos.fileName !== this.activeFile.fileName) { throw new Error(`verifyCaretAtMarker failed - expected to be in file "${pos.fileName}", but was in file "${this.activeFile.fileName}"`); @@ -1726,8 +1575,6 @@ namespace FourSlash { } public verifyIndentationAtCurrentPosition(numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart) { - this.taoInvalidReason = "verifyIndentationAtCurrentPosition NYI"; - const actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition, indentStyle); const lineCol = this.getLineColStringAtPosition(this.currentCaretPosition); if (actual !== numberOfSpaces) { @@ -1736,8 +1583,6 @@ namespace FourSlash { } public verifyIndentationAtPosition(fileName: string, position: number, numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart) { - this.taoInvalidReason = "verifyIndentationAtPosition NYI"; - const actual = this.getIndentation(fileName, position, indentStyle); const lineCol = this.getLineColStringAtPosition(position); if (actual !== numberOfSpaces) { @@ -1746,8 +1591,6 @@ namespace FourSlash { } public verifyCurrentLineContent(text: string) { - this.taoInvalidReason = "verifyCurrentLineContent NYI"; - const actual = this.getCurrentLineContent(); if (actual !== text) { throw new Error("verifyCurrentLineContent\n" + @@ -1757,8 +1600,6 @@ namespace FourSlash { } public verifyCurrentFileContent(text: string) { - this.taoInvalidReason = "verifyCurrentFileContent NYI"; - const actual = this.getFileContent(this.activeFile.fileName); const replaceNewlines = (str: string) => str.replace(/\r\n/g, "\n"); if (replaceNewlines(actual) !== replaceNewlines(text)) { @@ -1769,8 +1610,6 @@ namespace FourSlash { } public verifyTextAtCaretIs(text: string) { - this.taoInvalidReason = "verifyCurrentFileContent NYI"; - const actual = this.getFileContent(this.activeFile.fileName).substring(this.currentCaretPosition, this.currentCaretPosition + text.length); if (actual !== text) { throw new Error("verifyTextAtCaretIs\n" + @@ -1780,8 +1619,6 @@ namespace FourSlash { } public verifyCurrentNameOrDottedNameSpanText(text: string) { - this.taoInvalidReason = "verifyCurrentNameOrDottedNameSpanText NYI"; - const span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition); if (!span) { this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" + @@ -1798,13 +1635,10 @@ namespace FourSlash { } private getNameOrDottedNameSpan(pos: number) { - this.taoInvalidReason = "getNameOrDottedNameSpan NYI"; return this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, pos, pos); } public baselineCurrentFileNameOrDottedNameSpans() { - this.taoInvalidReason = "baselineCurrentFileNameOrDottedNameSpans impossible"; - Harness.Baseline.runBaseline( "Name OrDottedNameSpans for " + this.activeFile.fileName, this.testData.globalOptions[metadataOptionNames.baselineFile], @@ -1898,8 +1732,6 @@ namespace FourSlash { } public verifyOutliningSpans(spans: TextSpan[]) { - this.taoInvalidReason = "verifyOutliningSpans NYI"; - const actual = this.languageService.getOutliningSpans(this.activeFile.fileName); if (actual.length !== spans.length) { @@ -1968,8 +1800,6 @@ namespace FourSlash { } public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) { - this.taoInvalidReason = "verifyMatchingBracePosition NYI"; - const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); if (actual.length !== 2) { @@ -1993,8 +1823,6 @@ namespace FourSlash { } public verifyNoMatchingBracePosition(bracePosition: number) { - this.taoInvalidReason = "verifyNoMatchingBracePosition NYI"; - const actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); if (actual.length !== 0) { @@ -2007,8 +1835,6 @@ namespace FourSlash { Report an error if expected value and actual value do not match. */ public verifyNavigationItemsCount(expected: number, searchValue: string, matchKind?: string) { - this.taoInvalidReason = "verifyNavigationItemsCount NYI"; - const items = this.languageService.getNavigateToItems(searchValue); let actual = 0; let item: ts.NavigateToItem = null; @@ -2037,8 +1863,6 @@ namespace FourSlash { matchKind: string, fileName?: string, parentName?: string) { - this.taoInvalidReason = "verifyNavigationItemsListContains NYI"; - const items = this.languageService.getNavigateToItems(searchValue); if (!items || items.length === 0) { @@ -2063,8 +1887,6 @@ namespace FourSlash { } public verifyGetScriptLexicalStructureListCount(expected: number) { - this.taoInvalidReason = "verifyNavigationItemsListContains impossible"; - const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); const actual = this.getNavigationBarItemsCount(items); @@ -2086,8 +1908,6 @@ namespace FourSlash { } public verifyGetScriptLexicalStructureListContains(name: string, kind: string) { - this.taoInvalidReason = "verifyGetScriptLexicalStructureListContains impossible"; - const items = this.languageService.getNavigationBarItems(this.activeFile.fileName); if (!items || items.length === 0) { @@ -2148,8 +1968,6 @@ namespace FourSlash { } public verifyOccurrencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) { - this.taoInvalidReason = "verifyOccurrencesAtPositionListContains NYI"; - const occurrences = this.getOccurrencesAtCurrentPosition(); if (!occurrences || occurrences.length === 0) { @@ -2170,8 +1988,6 @@ namespace FourSlash { } public verifyOccurrencesAtPositionListCount(expectedCount: number) { - this.taoInvalidReason = "verifyOccurrencesAtPositionListCount NYI"; - const occurrences = this.getOccurrencesAtCurrentPosition(); const actualCount = occurrences ? occurrences.length : 0; if (expectedCount !== actualCount) { @@ -2185,8 +2001,6 @@ namespace FourSlash { } public verifyDocumentHighlightsAtPositionListContains(fileName: string, start: number, end: number, fileNamesToSearch: string[], kind?: string) { - this.taoInvalidReason = "verifyDocumentHighlightsAtPositionListContains NYI"; - const documentHighlights = this.getDocumentHighlightsAtCurrentPosition(fileNamesToSearch); if (!documentHighlights || documentHighlights.length === 0) { @@ -2213,8 +2027,6 @@ namespace FourSlash { } public verifyDocumentHighlightsAtPositionListCount(expectedCount: number, fileNamesToSearch: string[]) { - this.taoInvalidReason = "verifyDocumentHighlightsAtPositionListCount NYI"; - const documentHighlights = this.getDocumentHighlightsAtCurrentPosition(fileNamesToSearch); const actualCount = documentHighlights ? documentHighlights.reduce((currentCount, { highlightSpans }) => currentCount + highlightSpans.length, 0) @@ -2255,13 +2067,6 @@ namespace FourSlash { } private assertItemInCompletionList(items: ts.CompletionEntry[], name: string, text?: string, documentation?: string, kind?: string) { - this.scenarioActions.push(""); - this.scenarioActions.push(``); - - if (text || documentation || kind) { - this.taoInvalidReason = "assertItemInCompletionList only supports the \"name\" parameter"; - } - for (let i = 0; i < items.length; i++) { const item = items[i]; if (item.name === name) { @@ -2269,15 +2074,15 @@ namespace FourSlash { const details = this.getCompletionEntryDetails(item.name); if (documentation !== undefined) { - assert.equal(ts.displayPartsToString(details.documentation), documentation, assertionMessage("completion item documentation for " + name)); + assert.equal(ts.displayPartsToString(details.documentation), documentation, this.assertionMessageAtLastKnownMarker("completion item documentation for " + name)); } if (text !== undefined) { - assert.equal(ts.displayPartsToString(details.displayParts), text, assertionMessage("completion item detail text for " + name)); + assert.equal(ts.displayPartsToString(details.displayParts), text, this.assertionMessageAtLastKnownMarker("completion item detail text for " + name)); } } if (kind !== undefined) { - assert.equal(item.kind, kind, assertionMessage("completion item kind for " + name)); + assert.equal(item.kind, kind, this.assertionMessageAtLastKnownMarker("completion item kind for " + name)); } return; @@ -2352,14 +2157,6 @@ namespace FourSlash { return text.replace(/ /g, "\u00B7").replace(/\r/g, "\u00B6").replace(/\n/g, "\u2193\n").replace(/\t/g, "\u2192\ "); } - public getTestXmlData(): TestXmlData { - return { - actions: this.scenarioActions, - invalidReason: this.taoInvalidReason, - originalName: "" - }; - } - public setCancelled(numberOfCalls: number): void { this.cancellationToken.setCancelled(numberOfCalls); } @@ -2372,11 +2169,9 @@ namespace FourSlash { // TOOD: should these just use the Harness's stdout/stderr? const fsOutput = new Harness.Compiler.WriterAggregator(); const fsErrors = new Harness.Compiler.WriterAggregator(); - export let xmlData: TestXmlData[] = []; export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) { const content = Harness.IO.readFile(fileName); - const xml = runFourSlashTestContent(basePath, testType, content, fileName); - xmlData.push(xml); + runFourSlashTestContent(basePath, testType, content, fileName); } // We don't want to recompile 'fourslash.ts' for every test, so @@ -2398,7 +2193,8 @@ namespace FourSlash { program.emit(host.getSourceFile(Harness.Compiler.fourslashFileName, ts.ScriptTarget.ES3)); } - export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): TestXmlData { + export let currentTestState: TestState; + export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void { // Parse out the files and their metadata const testData = parseTestData(basePath, content, fileName); @@ -2437,10 +2233,6 @@ namespace FourSlash { result = fourslashJsOutput + "\r\n" + result; runCode(result); - - const xmlData = currentTestState.getTestXmlData(); - xmlData.originalName = fileName; - return xmlData; } function runCode(code: string): void { @@ -2619,7 +2411,7 @@ namespace FourSlash { throw new Error(errorMessage); } - function recordObjectMarker(fileName: string, location: ILocationInformation, text: string, markerMap: MarkerMap, markers: Marker[]): Marker { + function recordObjectMarker(fileName: string, location: LocationInformation, text: string, markerMap: MarkerMap, markers: Marker[]): Marker { let markerValue: any = undefined; try { // Attempt to parse the marker value as JSON @@ -2650,7 +2442,7 @@ namespace FourSlash { return marker; } - function recordMarker(fileName: string, location: ILocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker { + function recordMarker(fileName: string, location: LocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker { const marker: Marker = { fileName: fileName, position: location.position @@ -2679,10 +2471,10 @@ namespace FourSlash { let output = ""; /// The current marker (or maybe multi-line comment?) we're parsing, possibly - let openMarker: ILocationInformation = null; + let openMarker: LocationInformation = null; /// A stack of the open range markers that are still unclosed - const openRanges: IRangeLocationInformation[] = []; + const openRanges: RangeLocationInformation[] = []; /// A list of ranges we've collected so far */ let localRanges: Range[] = []; diff --git a/src/harness/fourslashRunner.ts b/src/harness/fourslashRunner.ts index 7228f06c20f..84e352359c4 100644 --- a/src/harness/fourslashRunner.ts +++ b/src/harness/fourslashRunner.ts @@ -58,56 +58,6 @@ class FourSlashRunner extends RunnerBase { } }); }); - - describe("Generate Tao XML", () => { - const invalidReasons: any = {}; - FourSlash.xmlData.forEach(xml => { - if (xml.invalidReason !== null) { - invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1; - } - }); - const invalidReport: { reason: string; count: number }[] = []; - for (const reason in invalidReasons) { - if (invalidReasons.hasOwnProperty(reason)) { - invalidReport.push({ reason: reason, count: invalidReasons[reason] }); - } - } - invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1); - - const lines: string[] = []; - lines.push(""); - lines.push(""); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - FourSlash.xmlData.forEach(xml => { - if (xml.invalidReason !== null) { - lines.push(""); - } - else { - lines.push(" "); - xml.actions.forEach(action => { - lines.push(" " + action); - }); - lines.push(" "); - } - }); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(" "); - lines.push(""); - Harness.IO.writeFile("built/local/fourslash.xml", lines.join("\r\n")); - }); }); } } From 31bce223d98ed976542c4d2cd654618f10cdfb9c Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Nov 2015 11:50:42 -0800 Subject: [PATCH 3/4] switch fourslash to use local test state --- src/harness/fourslash.ts | 669 ++++++++++++- ...foreSemanticDiagnosticsInArrowFunction1.ts | 12 +- tests/cases/fourslash/fourslash.ts | 902 +++++------------- tests/cases/fourslash/indentationBlock.ts | 2 +- tests/cases/fourslash/indentationNone.ts | 2 +- .../fourslash/recursiveClassReference.ts | 2 +- tests/cases/fourslash/renameModuleToVar.ts | 8 +- 7 files changed, 909 insertions(+), 688 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 88458beaba4..5f48a885395 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2174,31 +2174,11 @@ namespace FourSlash { runFourSlashTestContent(basePath, testType, content, fileName); } - // We don't want to recompile 'fourslash.ts' for every test, so - // here we cache the JS output and reuse it for every test. - let fourslashJsOutput: string; - { - const fourslashFile: Harness.Compiler.TestFile = { - unitName: Harness.Compiler.fourslashFileName, - content: undefined - }; - const host = Harness.Compiler.createCompilerHost([fourslashFile], - (fn, contents) => fourslashJsOutput = contents, - ts.ScriptTarget.Latest, - Harness.IO.useCaseSensitiveFileNames(), - Harness.IO.getCurrentDirectory()); - - const program = ts.createProgram([Harness.Compiler.fourslashFileName], { noResolve: true, target: ts.ScriptTarget.ES3 }, host); - - program.emit(host.getSourceFile(Harness.Compiler.fourslashFileName, ts.ScriptTarget.ES3)); - } - - export let currentTestState: TestState; export function runFourSlashTestContent(basePath: string, testType: FourSlashTestType, content: string, fileName: string): void { // Parse out the files and their metadata const testData = parseTestData(basePath, content, fileName); - currentTestState = new TestState(basePath, testType, testData); + const state = new TestState(basePath, testType, testData); let result = ""; const fourslashFile: Harness.Compiler.TestFile = { @@ -2228,17 +2208,27 @@ namespace FourSlash { } program.emit(sourceFile); - result = result || ""; // Might have an empty fourslash file - result = fourslashJsOutput + "\r\n" + result; - - runCode(result); + ts.Debug.assert(!!result); + runCode(result, state); } - function runCode(code: string): void { + function runCode(code: string, state: TestState): void { // Compile and execute the test + const wrappedCode = +`(function(test, goTo, verify, edit, debug, format, cancellation, classification, verifyOperationIsCancelled) { +${code} +})`; try { - eval(code); + const test = new FourSlashInterface.Test(state); + const goTo = new FourSlashInterface.GoTo(state); + const verify = new FourSlashInterface.Verify(state); + const edit = new FourSlashInterface.Edit(state); + const debug = new FourSlashInterface.Debug(state); + const format = new FourSlashInterface.Format(state); + const cancellation = new FourSlashInterface.Cancellation(state); + const f = eval(wrappedCode); + f(test, goTo, verify, edit, debug, format, cancellation, FourSlashInterface.Classification, FourSlash.verifyOperationIsCancelled); } catch (err) { // Debugging: FourSlash.currentTestState.printCurrentFileState(); @@ -2660,3 +2650,628 @@ namespace FourSlash { }; } } + +namespace FourSlashInterface { + export class Test { + constructor(private state: FourSlash.TestState) { + } + + public markers(): FourSlash.Marker[] { + return this.state.getMarkers(); + } + + public marker(name?: string): FourSlash.Marker { + return this.state.getMarkerByName(name); + } + + public ranges(): FourSlash.Range[] { + return this.state.getRanges(); + } + + public markerByName(s: string): FourSlash.Marker { + return this.state.getMarkerByName(s); + } + } + + export class GoTo { + constructor(private state: FourSlash.TestState) { + } + // Moves the caret to the specified marker, + // or the anonymous marker ('/**/') if no name + // is given + public marker(name?: string) { + this.state.goToMarker(name); + } + + public bof() { + this.state.goToBOF(); + } + + public eof() { + this.state.goToEOF(); + } + + public definition(definitionIndex = 0) { + this.state.goToDefinition(definitionIndex); + } + + public type(definitionIndex = 0) { + this.state.goToTypeDefinition(definitionIndex); + } + + public position(position: number, fileIndex?: number): void; + public position(position: number, fileName?: string): void; + public position(position: number, fileNameOrIndex?: any): void { + if (fileNameOrIndex !== undefined) { + this.file(fileNameOrIndex); + } + this.state.goToPosition(position); + } + + // Opens a file, given either its index as it + // appears in the test source, or its filename + // as specified in the test metadata + public file(index: number, content?: string): void; + public file(name: string, content?: string): void; + public file(indexOrName: any, content?: string): void { + this.state.openFile(indexOrName, content); + } + } + + export class VerifyNegatable { + public not: VerifyNegatable; + + constructor(protected state: FourSlash.TestState, private negative = false) { + if (!negative) { + this.not = new VerifyNegatable(state, true); + } + } + + // Verifies the member list contains the specified symbol. The + // member list is brought up if necessary + public memberListContains(symbol: string, text?: string, documenation?: string, kind?: string) { + if (this.negative) { + this.state.verifyMemberListDoesNotContain(symbol); + } + else { + this.state.verifyMemberListContains(symbol, text, documenation, kind); + } + } + + public memberListCount(expectedCount: number) { + this.state.verifyMemberListCount(expectedCount, this.negative); + } + + // Verifies the completion list contains the specified symbol. The + // completion list is brought up if necessary + public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string) { + if (this.negative) { + this.state.verifyCompletionListDoesNotContain(symbol, text, documentation, kind); + } + else { + this.state.verifyCompletionListContains(symbol, text, documentation, kind); + } + } + + // Verifies the completion list items count to be greater than the specified amount. The + // completion list is brought up if necessary + public completionListItemsCountIsGreaterThan(count: number) { + this.state.verifyCompletionListItemsCountIsGreaterThan(count, this.negative); + } + + public completionListIsEmpty() { + this.state.verifyCompletionListIsEmpty(this.negative); + } + + public completionListAllowsNewIdentifier() { + this.state.verifyCompletionListAllowsNewIdentifier(this.negative); + } + + public memberListIsEmpty() { + this.state.verifyMemberListIsEmpty(this.negative); + } + + public referencesCountIs(count: number) { + this.state.verifyReferencesCountIs(count, /*localFilesOnly*/ false); + } + + public referencesAtPositionContains(range: FourSlash.Range, isWriteAccess?: boolean) { + this.state.verifyReferencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess); + } + + public signatureHelpPresent() { + this.state.verifySignatureHelpPresent(!this.negative); + } + + public errorExistsBetweenMarkers(startMarker: string, endMarker: string) { + this.state.verifyErrorExistsBetweenMarkers(startMarker, endMarker, !this.negative); + } + + public errorExistsAfterMarker(markerName = "") { + this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ true); + } + + public errorExistsBeforeMarker(markerName = "") { + this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ false); + } + + public quickInfoIs(expectedText?: string, expectedDocumentation?: string) { + this.state.verifyQuickInfoString(this.negative, expectedText, expectedDocumentation); + } + + public quickInfoExists() { + this.state.verifyQuickInfoExists(this.negative); + } + + public definitionCountIs(expectedCount: number) { + this.state.verifyDefinitionsCount(this.negative, expectedCount); + } + + public typeDefinitionCountIs(expectedCount: number) { + this.state.verifyTypeDefinitionsCount(this.negative, expectedCount); + } + + public definitionLocationExists() { + this.state.verifyDefinitionLocationExists(this.negative); + } + + public verifyDefinitionsName(name: string, containerName: string) { + this.state.verifyDefinitionsName(this.negative, name, containerName); + } + } + + export class Verify extends VerifyNegatable { + constructor(state: FourSlash.TestState) { + super(state); + } + + public caretAtMarker(markerName?: string) { + this.state.verifyCaretAtMarker(markerName); + } + + public indentationIs(numberOfSpaces: number) { + this.state.verifyIndentationAtCurrentPosition(numberOfSpaces); + } + + public indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle = ts.IndentStyle.Smart) { + this.state.verifyIndentationAtPosition(fileName, position, numberOfSpaces, indentStyle); + } + + public textAtCaretIs(text: string) { + this.state.verifyTextAtCaretIs(text); + } + + /** + * Compiles the current file and evaluates 'expr' in a context containing + * the emitted output, then compares (using ===) the result of that expression + * to 'value'. Do not use this function with external modules as it is not supported. + */ + public eval(expr: string, value: any) { + this.state.verifyEval(expr, value); + } + + public currentLineContentIs(text: string) { + this.state.verifyCurrentLineContent(text); + } + + public currentFileContentIs(text: string) { + this.state.verifyCurrentFileContent(text); + } + + public verifyGetEmitOutputForCurrentFile(expected: string): void { + this.state.verifyGetEmitOutputForCurrentFile(expected); + } + + public currentParameterHelpArgumentNameIs(name: string) { + this.state.verifyCurrentParameterHelpName(name); + } + + public currentParameterSpanIs(parameter: string) { + this.state.verifyCurrentParameterSpanIs(parameter); + } + + public currentParameterHelpArgumentDocCommentIs(docComment: string) { + this.state.verifyCurrentParameterHelpDocComment(docComment); + } + + public currentSignatureHelpDocCommentIs(docComment: string) { + this.state.verifyCurrentSignatureHelpDocComment(docComment); + } + + public signatureHelpCountIs(expected: number) { + this.state.verifySignatureHelpCount(expected); + } + + public signatureHelpArgumentCountIs(expected: number) { + this.state.verifySignatureHelpArgumentCount(expected); + } + + public currentSignatureParameterCountIs(expected: number) { + this.state.verifyCurrentSignatureHelpParameterCount(expected); + } + + public currentSignatureHelpIs(expected: string) { + this.state.verifyCurrentSignatureHelpIs(expected); + } + + public numberOfErrorsInCurrentFile(expected: number) { + this.state.verifyNumberOfErrorsInCurrentFile(expected); + } + + public baselineCurrentFileBreakpointLocations() { + this.state.baselineCurrentFileBreakpointLocations(); + } + + public baselineCurrentFileNameOrDottedNameSpans() { + this.state.baselineCurrentFileNameOrDottedNameSpans(); + } + + public baselineGetEmitOutput() { + this.state.baselineGetEmitOutput(); + } + + public nameOrDottedNameSpanTextIs(text: string) { + this.state.verifyCurrentNameOrDottedNameSpanText(text); + } + + public outliningSpansInCurrentFile(spans: FourSlash.TextSpan[]) { + this.state.verifyOutliningSpans(spans); + } + + public todoCommentsInCurrentFile(descriptors: string[]) { + this.state.verifyTodoComments(descriptors, this.state.getRanges()); + } + + public matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number) { + this.state.verifyMatchingBracePosition(bracePosition, expectedMatchPosition); + } + + public noMatchingBracePositionInCurrentFile(bracePosition: number) { + this.state.verifyNoMatchingBracePosition(bracePosition); + } + + public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) { + this.state.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, caretOffset: expectedOffset }); + } + + public noDocCommentTemplate() { + this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true); + } + + public getScriptLexicalStructureListCount(count: number) { + this.state.verifyGetScriptLexicalStructureListCount(count); + } + + // TODO: figure out what to do with the unused arguments. + public getScriptLexicalStructureListContains( + name: string, + kind: string, + fileName?: string, + parentName?: string, + isAdditionalSpan?: boolean, + markerPosition?: number) { + this.state.verifyGetScriptLexicalStructureListContains(name, kind); + } + + public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) { + this.state.verifyNavigationItemsCount(count, searchValue, matchKind); + } + + public navigationItemsListContains( + name: string, + kind: string, + searchValue: string, + matchKind: string, + fileName?: string, + parentName?: string) { + this.state.verifyNavigationItemsListContains( + name, + kind, + searchValue, + matchKind, + fileName, + parentName); + } + + public occurrencesAtPositionContains(range: FourSlash.Range, isWriteAccess?: boolean) { + this.state.verifyOccurrencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess); + } + + public occurrencesAtPositionCount(expectedCount: number) { + this.state.verifyOccurrencesAtPositionListCount(expectedCount); + } + + public documentHighlightsAtPositionContains(range: FourSlash.Range, fileNamesToSearch: string[], kind?: string) { + this.state.verifyDocumentHighlightsAtPositionListContains(range.fileName, range.start, range.end, fileNamesToSearch, kind); + } + + public documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]) { + this.state.verifyDocumentHighlightsAtPositionListCount(expectedCount, fileNamesToSearch); + } + + public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string) { + this.state.verifyCompletionEntryDetails(entryName, text, documentation, kind); + } + + /** + * This method *requires* a contiguous, complete, and ordered stream of classifications for a file. + */ + public syntacticClassificationsAre(...classifications: { classificationType: string; text: string }[]) { + this.state.verifySyntacticClassifications(classifications); + } + + /** + * This method *requires* an ordered stream of classifications for a file, and spans are highly recommended. + */ + public semanticClassificationsAre(...classifications: { classificationType: string; text: string; textSpan?: FourSlash.TextSpan }[]) { + this.state.verifySemanticClassifications(classifications); + } + + public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) { + this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers); + } + + public renameInfoFailed(message?: string) { + this.state.verifyRenameInfoFailed(message); + } + + public renameLocations(findInStrings: boolean, findInComments: boolean) { + this.state.verifyRenameLocations(findInStrings, findInComments); + } + + public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; }, + displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) { + this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation); + } + + public getSyntacticDiagnostics(expected: string) { + this.state.getSyntacticDiagnostics(expected); + } + + public getSemanticDiagnostics(expected: string) { + this.state.getSemanticDiagnostics(expected); + } + + public ProjectInfo(expected: string []) { + this.state.verifyProjectInfo(expected); + } + } + + export class Edit { + constructor(private state: FourSlash.TestState) { + } + public backspace(count?: number) { + this.state.deleteCharBehindMarker(count); + } + + public deleteAtCaret(times?: number) { + this.state.deleteChar(times); + } + + public replace(start: number, length: number, text: string) { + this.state.replace(start, length, text); + } + + public paste(text: string) { + this.state.paste(text); + } + + public insert(text: string) { + this.insertLines(text); + } + + public insertLine(text: string) { + this.insertLines(text + "\n"); + } + + public insertLines(...lines: string[]) { + this.state.type(lines.join("\n")); + } + + public moveRight(count?: number) { + this.state.moveCaretRight(count); + } + + public moveLeft(count?: number) { + if (typeof count === "undefined") { + count = 1; + } + this.state.moveCaretRight(count * -1); + } + + public enableFormatting() { + this.state.enableFormatting = true; + } + + public disableFormatting() { + this.state.enableFormatting = false; + } + } + + export class Debug { + constructor(private state: FourSlash.TestState) { + } + + public printCurrentParameterHelp() { + this.state.printCurrentParameterHelp(); + } + + public printCurrentFileState() { + this.state.printCurrentFileState(); + } + + public printCurrentFileStateWithWhitespace() { + this.state.printCurrentFileState(/*makeWhitespaceVisible*/true); + } + + public printCurrentFileStateWithoutCaret() { + this.state.printCurrentFileState(/*makeWhitespaceVisible*/false, /*makeCaretVisible*/false); + } + + public printCurrentQuickInfo() { + this.state.printCurrentQuickInfo(); + } + + public printCurrentSignatureHelp() { + this.state.printCurrentSignatureHelp(); + } + + public printMemberListMembers() { + this.state.printMemberListMembers(); + } + + public printCompletionListMembers() { + this.state.printCompletionListMembers(); + } + + public printBreakpointLocation(pos: number) { + this.state.printBreakpointLocation(pos); + } + public printBreakpointAtCurrentLocation() { + this.state.printBreakpointAtCurrentLocation(); + } + + public printNameOrDottedNameSpans(pos: number) { + this.state.printNameOrDottedNameSpans(pos); + } + + public printErrorList() { + this.state.printErrorList(); + } + + public printNavigationItems(searchValue = ".*") { + this.state.printNavigationItems(searchValue); + } + + public printScriptLexicalStructureItems() { + this.state.printScriptLexicalStructureItems(); + } + + public printReferences() { + this.state.printReferences(); + } + + public printContext() { + this.state.printContext(); + } + } + + export class Format { + constructor(private state: FourSlash.TestState) { + } + + public document() { + this.state.formatDocument(); + } + + public copyFormatOptions(): ts.FormatCodeOptions { + return this.state.copyFormatOptions(); + } + + public setFormatOptions(options: ts.FormatCodeOptions) { + return this.state.setFormatOptions(options); + } + + public selection(startMarker: string, endMarker: string) { + this.state.formatSelection(this.state.getMarkerByName(startMarker).position, this.state.getMarkerByName(endMarker).position); + } + + public setOption(name: string, value: number): void; + public setOption(name: string, value: string): void; + public setOption(name: string, value: boolean): void; + public setOption(name: string, value: any): void { + this.state.formatCodeOptions[name] = value; + } + } + + export class Cancellation { + constructor(private state: FourSlash.TestState) { + } + + public resetCancelled() { + this.state.resetCancelled(); + } + + public setCancelled(numberOfCalls = 0) { + this.state.setCancelled(numberOfCalls); + } + } + + export namespace Classification { + export function comment(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("comment", text, position); + } + + export function identifier(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("identifier", text, position); + } + + export function keyword(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("keyword", text, position); + } + + export function numericLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("numericLiteral", text, position); + } + + export function operator(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("operator", text, position); + } + + export function stringLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("stringLiteral", text, position); + } + + export function whiteSpace(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("whiteSpace", text, position); + } + + export function text(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("text", text, position); + } + + export function punctuation(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("punctuation", text, position); + } + + export function docCommentTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("docCommentTagName", text, position); + } + + export function className(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("className", text, position); + } + + export function enumName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("enumName", text, position); + } + + export function interfaceName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("interfaceName", text, position); + } + + export function moduleName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("moduleName", text, position); + } + + export function typeParameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("typeParameterName", text, position); + } + + export function parameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("parameterName", text, position); + } + + export function typeAliasName(text: string, position?: number): { classificationType: string; text: string; textSpan?: FourSlash.TextSpan } { + return getClassification("typeAliasName", text, position); + } + + function getClassification(type: string, text: string, position?: number) { + return { + classificationType: type, + text: text, + textSpan: position === undefined ? undefined : { start: position, end: position + text.length } + }; + } + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts b/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts index 16d2efcd6d4..d66c1620751 100644 --- a/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts +++ b/tests/cases/fourslash/completionBeforeSemanticDiagnosticsInArrowFunction1.ts @@ -3,16 +3,16 @@ //// var f4 = (x: T/**/ ) => { //// } -fs.goTo.marker(); +goTo.marker(); // Replace the "T" type with the non-existent type 'V'. -fs.edit.backspace(1); -fs.edit.insert("A"); +edit.backspace(1); +edit.insert("A"); // Bring up completion to force a pull resolve. This will end up resolving several symbols and // producing unreported diagnostics (i.e. that 'V' wasn't found). -fs.verify.completionListContains("T"); -fs.verify.completionEntryDetailIs("T", "(type parameter) T in (x: any): void"); +verify.completionListContains("T"); +verify.completionEntryDetailIs("T", "(type parameter) T in (x: any): void"); // There should now be a single error. -fs.verify.numberOfErrorsInCurrentFile(1); \ No newline at end of file +verify.numberOfErrorsInCurrentFile(1); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index f6451e1f1c4..5b8bb94bb48 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -24,10 +24,7 @@ // @Module: Node // @Target: ES5 -// In the imperative section, you can write any valid TypeScript code. If -// you need help finding a something in Intellisense, you can -// type 'fs.' as an alternate way of accessing the top-level objects -// (e.g. 'fs.goTo.eof();') +// In the imperative section, you can write any valid TypeScript code. //--------------------------------------- // For API editors: @@ -45,52 +42,32 @@ // // TODO: figure out a better solution to the API exposure problem. -// /// -// /// - -declare var FourSlash; -module ts { - export interface SymbolDisplayPart { +declare module ts { + interface SymbolDisplayPart { text: string; kind: string; } + + enum IndentStyle { + None = 0, + Block = 1, + Smart = 2, + } } -//--------------------------------------------- - -// 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 { - Succeeded = 0, // All outputs generated if requested (.js, .map, .d.ts), no errors reported - AllOutputGenerationSkipped = 1, // No .js generated because of syntax errors, or compiler options errors, nothing generated - JSGeneratedWithSemanticErrors = 2, // .js and .map generated with semantic errors - DeclarationGenerationSkipped = 3, // .d.ts generation skipped because of semantic errors or declaration emitter specific errors; Output .js with semantic errors - EmitErrorsEncountered = 4 // Emitter errors occurred during emitting process -} - -// This is a duplicate of the indentstyle in services.ts to expose it to testcases in fourslash -enum IndentStyle { - None, - Block, - Smart, -} - -module FourSlashInterface { - - export interface Marker { +declare module FourSlashInterface { + interface Marker { fileName: string; position: number; data?: any; } - - export interface EditorOptions { + interface EditorOptions { IndentSize: number; TabSize: number; NewLineCharacter: string; ConvertTabsToSpaces: boolean; } - - export interface FormatCodeOptions extends EditorOptions { + interface FormatCodeOptions extends EditorOptions { InsertSpaceAfterCommaDelimiter: boolean; InsertSpaceAfterSemicolonInForStatements: boolean; InsertSpaceBeforeAndAfterBinaryOperators: boolean; @@ -100,646 +77,275 @@ module FourSlashInterface { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; - [s: string]: boolean | number| string; + [s: string]: boolean | number | string; } - - export interface Range { + interface Range { fileName: string; start: number; end: number; marker?: Marker; } - - export interface TextSpan { + interface TextSpan { start: number; end: number; } - - export class test_ { - public markers(): Marker[] { - return FourSlash.currentTestState.getMarkers(); - } - - public marker(name?: string): Marker { - return FourSlash.currentTestState.getMarkerByName(name); - } - - public ranges(): Range[] { - return FourSlash.currentTestState.getRanges(); - } - - public markerByName(s: string): Marker { - return FourSlash.currentTestState.getMarkerByName(s); - } + class test_ { + markers(): Marker[]; + marker(name?: string): Marker; + ranges(): Range[]; + markerByName(s: string): Marker; } - - export class goTo { - // Moves the caret to the specified marker, - // or the anonymous marker ('/**/') if no name - // is given - public marker(name?: string) { - FourSlash.currentTestState.goToMarker(name); - } - - public bof() { - FourSlash.currentTestState.goToBOF(); - } - - public eof() { - FourSlash.currentTestState.goToEOF(); - } - - public definition(definitionIndex: number = 0) { - FourSlash.currentTestState.goToDefinition(definitionIndex); - } - - public type(definitionIndex: number = 0) { - FourSlash.currentTestState.goToTypeDefinition(definitionIndex); - } - - public position(position: number, fileIndex?: number); - public position(position: number, fileName?: string); - public position(position: number, fileNameOrIndex?: any) { - if (fileNameOrIndex !== undefined) { - this.file(fileNameOrIndex); - } - FourSlash.currentTestState.goToPosition(position); - } - - // Opens a file, given either its index as it - // appears in the test source, or its filename - // as specified in the test metadata - public file(index: number, content?: string); - public file(name: string, content?: string); - public file(indexOrName: any, content?: string) { - FourSlash.currentTestState.openFile(indexOrName, content); - } + class goTo { + marker(name?: string): void; + bof(): void; + eof(): void; + definition(definitionIndex?: number): void; + type(definitionIndex?: number): void; + position(position: number, fileIndex?: number): any; + position(position: number, fileName?: string): any; + file(index: number, content?: string): any; + file(name: string, content?: string): any; } - - export class verifyNegatable { - public not: verifyNegatable; - - constructor(private negative = false) { - if (!negative) { - this.not = new verifyNegatable(true); - } - } - - // Verifies the member list contains the specified symbol. The - // member list is brought up if necessary - public memberListContains(symbol: string, text?: string, documenation?: string, kind?: string) { - if (this.negative) { - FourSlash.currentTestState.verifyMemberListDoesNotContain(symbol); - } else { - FourSlash.currentTestState.verifyMemberListContains(symbol, text, documenation, kind); - } - } - - public memberListCount(expectedCount: number) { - FourSlash.currentTestState.verifyMemberListCount(expectedCount, this.negative); - } - - // Verifies the completion list contains the specified symbol. The - // completion list is brought up if necessary - public completionListContains(symbol: string, text?: string, documentation?: string, kind?: string) { - if (this.negative) { - FourSlash.currentTestState.verifyCompletionListDoesNotContain(symbol, text, documentation, kind); - } else { - FourSlash.currentTestState.verifyCompletionListContains(symbol, text, documentation, kind); - } - } - - // Verifies the completion list items count to be greater than the specified amount. The - // completion list is brought up if necessary - public completionListItemsCountIsGreaterThan(count: number) { - FourSlash.currentTestState.verifyCompletionListItemsCountIsGreaterThan(count, this.negative); - } - - public completionListIsEmpty() { - FourSlash.currentTestState.verifyCompletionListIsEmpty(this.negative); - } - - public completionListAllowsNewIdentifier() { - FourSlash.currentTestState.verifyCompletionListAllowsNewIdentifier(this.negative); - } - - public memberListIsEmpty() { - FourSlash.currentTestState.verifyMemberListIsEmpty(this.negative); - } - - public referencesCountIs(count: number) { - FourSlash.currentTestState.verifyReferencesCountIs(count, /*localFilesOnly*/ false); - } - - public referencesAtPositionContains(range: Range, isWriteAccess?: boolean) { - FourSlash.currentTestState.verifyReferencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess); - } - - public signatureHelpPresent() { - FourSlash.currentTestState.verifySignatureHelpPresent(!this.negative); - } - - public errorExistsBetweenMarkers(startMarker: string, endMarker: string) { - FourSlash.currentTestState.verifyErrorExistsBetweenMarkers(startMarker, endMarker, !this.negative); - } - - public errorExistsAfterMarker(markerName = "") { - FourSlash.currentTestState.verifyErrorExistsAfterMarker(markerName, !this.negative, true); - } - - public errorExistsBeforeMarker(markerName = "") { - FourSlash.currentTestState.verifyErrorExistsAfterMarker(markerName, !this.negative, false); - } - - public quickInfoIs(expectedText?: string, expectedDocumentation?: string) { - FourSlash.currentTestState.verifyQuickInfoString(this.negative, expectedText, expectedDocumentation); - } - - public quickInfoExists() { - FourSlash.currentTestState.verifyQuickInfoExists(this.negative); - } - - public definitionCountIs(expectedCount: number) { - FourSlash.currentTestState.verifyDefinitionsCount(this.negative, expectedCount); - } - - public typeDefinitionCountIs(expectedCount: number) { - FourSlash.currentTestState.verifyTypeDefinitionsCount(this.negative, expectedCount); - } - - public definitionLocationExists() { - FourSlash.currentTestState.verifyDefinitionLocationExists(this.negative); - } - - public verifyDefinitionsName(name: string, containerName: string) { - FourSlash.currentTestState.verifyDefinitionsName(this.negative, name, containerName); - } + class verifyNegatable { + private negative; + not: verifyNegatable; + constructor(negative?: boolean); + memberListContains(symbol: string, text?: string, documenation?: string, kind?: string): void; + memberListCount(expectedCount: number): void; + completionListContains(symbol: string, text?: string, documentation?: string, kind?: string): void; + completionListItemsCountIsGreaterThan(count: number): void; + completionListIsEmpty(): void; + completionListAllowsNewIdentifier(): void; + memberListIsEmpty(): void; + referencesCountIs(count: number): void; + referencesAtPositionContains(range: Range, isWriteAccess?: boolean): void; + signatureHelpPresent(): void; + errorExistsBetweenMarkers(startMarker: string, endMarker: string): void; + errorExistsAfterMarker(markerName?: string): void; + errorExistsBeforeMarker(markerName?: string): void; + quickInfoIs(expectedText?: string, expectedDocumentation?: string): void; + quickInfoExists(): void; + definitionCountIs(expectedCount: number): void; + typeDefinitionCountIs(expectedCount: number): void; + definitionLocationExists(): void; + verifyDefinitionsName(name: string, containerName: string): void; } - - export class verify extends verifyNegatable { - public caretAtMarker(markerName?: string) { - FourSlash.currentTestState.verifyCaretAtMarker(markerName); - } - - public indentationIs(numberOfSpaces: number) { - FourSlash.currentTestState.verifyIndentationAtCurrentPosition(numberOfSpaces); - } - - public indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle = IndentStyle.Smart) { - FourSlash.currentTestState.verifyIndentationAtPosition(fileName, position, numberOfSpaces, indentStyle); - } - - public textAtCaretIs(text: string) { - FourSlash.currentTestState.verifyTextAtCaretIs(text); - } - + class verify extends verifyNegatable { + caretAtMarker(markerName?: string): void; + indentationIs(numberOfSpaces: number): void; + indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle?: IndentStyle): void; + textAtCaretIs(text: string): void; /** * Compiles the current file and evaluates 'expr' in a context containing * the emitted output, then compares (using ===) the result of that expression * to 'value'. Do not use this function with external modules as it is not supported. */ - public eval(expr: string, value: any) { - FourSlash.currentTestState.verifyEval(expr, value); - } - - public currentLineContentIs(text: string) { - FourSlash.currentTestState.verifyCurrentLineContent(text); - } - - public currentFileContentIs(text: string) { - FourSlash.currentTestState.verifyCurrentFileContent(text); - } - - public verifyGetEmitOutputForCurrentFile(expected: string): void { - FourSlash.currentTestState.verifyGetEmitOutputForCurrentFile(expected); - } - - public currentParameterHelpArgumentNameIs(name: string) { - FourSlash.currentTestState.verifyCurrentParameterHelpName(name); - } - - public currentParameterSpanIs(parameter: string) { - FourSlash.currentTestState.verifyCurrentParameterSpanIs(parameter); - } - - public currentParameterHelpArgumentDocCommentIs(docComment: string) { - FourSlash.currentTestState.verifyCurrentParameterHelpDocComment(docComment); - } - - public currentSignatureHelpDocCommentIs(docComment: string) { - FourSlash.currentTestState.verifyCurrentSignatureHelpDocComment(docComment); - } - - public signatureHelpCountIs(expected: number) { - FourSlash.currentTestState.verifySignatureHelpCount(expected); - } - - public signatureHelpArgumentCountIs(expected: number) { - FourSlash.currentTestState.verifySignatureHelpArgumentCount(expected); - } - - public currentSignatureParameterCountIs(expected: number) { - FourSlash.currentTestState.verifyCurrentSignatureHelpParameterCount(expected); - } - - public currentSignatureTypeParameterCountIs(expected: number) { - FourSlash.currentTestState.verifyCurrentSignatureHelpTypeParameterCount(expected); - } - - public currentSignatureHelpIs(expected: string) { - FourSlash.currentTestState.verifyCurrentSignatureHelpIs(expected); - } - - public numberOfErrorsInCurrentFile(expected: number) { - FourSlash.currentTestState.verifyNumberOfErrorsInCurrentFile(expected); - } - - public baselineCurrentFileBreakpointLocations() { - FourSlash.currentTestState.baselineCurrentFileBreakpointLocations(); - } - - public baselineCurrentFileNameOrDottedNameSpans() { - FourSlash.currentTestState.baselineCurrentFileNameOrDottedNameSpans(); - } - - public baselineGetEmitOutput() { - FourSlash.currentTestState.baselineGetEmitOutput(); - } - - public nameOrDottedNameSpanTextIs(text: string) { - FourSlash.currentTestState.verifyCurrentNameOrDottedNameSpanText(text); - } - - public outliningSpansInCurrentFile(spans: TextSpan[]) { - FourSlash.currentTestState.verifyOutliningSpans(spans); - } - - public todoCommentsInCurrentFile(descriptors: string[]) { - FourSlash.currentTestState.verifyTodoComments(descriptors, test.ranges()); - } - - public matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number) { - FourSlash.currentTestState.verifyMatchingBracePosition(bracePosition, expectedMatchPosition); - } - - public noMatchingBracePositionInCurrentFile(bracePosition: number) { - FourSlash.currentTestState.verifyNoMatchingBracePosition(bracePosition); - } - - public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) { - FourSlash.currentTestState.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, caretOffset: expectedOffset }); - } - - public noDocCommentTemplate() { - this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, true); - } - - public getScriptLexicalStructureListCount(count: number) { - FourSlash.currentTestState.verifyGetScriptLexicalStructureListCount(count); - } - - // TODO: figure out what to do with the unused arguments. - public getScriptLexicalStructureListContains( - name: string, - kind: string, - fileName?: string, - parentName?: string, - isAdditionalSpan?: boolean, - markerPosition?: number) { - FourSlash.currentTestState.verifyGetScriptLexicalStructureListContains(name, kind); - } - - public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) { - FourSlash.currentTestState.verifyNavigationItemsCount(count, searchValue, matchKind); - } - - public navigationItemsListContains( - name: string, - kind: string, - searchValue: string, - matchKind: string, - fileName?: string, - parentName?: string) { - FourSlash.currentTestState.verifyNavigationItemsListContains( - name, - kind, - searchValue, - matchKind, - fileName, - parentName); - } - - public occurrencesAtPositionContains(range: Range, isWriteAccess?: boolean) { - FourSlash.currentTestState.verifyOccurrencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess); - } - - public occurrencesAtPositionCount(expectedCount: number) { - FourSlash.currentTestState.verifyOccurrencesAtPositionListCount(expectedCount); - } - - public documentHighlightsAtPositionContains(range: Range, fileNamesToSearch: string[], kind?: string) { - FourSlash.currentTestState.verifyDocumentHighlightsAtPositionListContains(range.fileName, range.start, range.end, fileNamesToSearch, kind); - } - - public documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]) { - FourSlash.currentTestState.verifyDocumentHighlightsAtPositionListCount(expectedCount, fileNamesToSearch); - } - - public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string) { - FourSlash.currentTestState.verifyCompletionEntryDetails(entryName, text, documentation, kind); - } - + eval(expr: string, value: any): void; + currentLineContentIs(text: string): void; + currentFileContentIs(text: string): void; + verifyGetEmitOutputForCurrentFile(expected: string): void; + currentParameterHelpArgumentNameIs(name: string): void; + currentParameterSpanIs(parameter: string): void; + currentParameterHelpArgumentDocCommentIs(docComment: string): void; + currentSignatureHelpDocCommentIs(docComment: string): void; + signatureHelpCountIs(expected: number): void; + signatureHelpArgumentCountIs(expected: number): void; + currentSignatureParameterCountIs(expected: number): void; + currentSignatureTypeParameterCountIs(expected: number): void; + currentSignatureHelpIs(expected: string): void; + numberOfErrorsInCurrentFile(expected: number): void; + baselineCurrentFileBreakpointLocations(): void; + baselineCurrentFileNameOrDottedNameSpans(): void; + baselineGetEmitOutput(): void; + nameOrDottedNameSpanTextIs(text: string): void; + outliningSpansInCurrentFile(spans: TextSpan[]): void; + todoCommentsInCurrentFile(descriptors: string[]): void; + matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number): void; + noMatchingBracePositionInCurrentFile(bracePosition: number): void; + DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean): void; + noDocCommentTemplate(): void; + getScriptLexicalStructureListCount(count: number): void; + getScriptLexicalStructureListContains(name: string, kind: string, fileName?: string, parentName?: string, isAdditionalSpan?: boolean, markerPosition?: number): void; + navigationItemsListCount(count: number, searchValue: string, matchKind?: string): void; + navigationItemsListContains(name: string, kind: string, searchValue: string, matchKind: string, fileName?: string, parentName?: string): void; + occurrencesAtPositionContains(range: Range, isWriteAccess?: boolean): void; + occurrencesAtPositionCount(expectedCount: number): void; + documentHighlightsAtPositionContains(range: Range, fileNamesToSearch: string[], kind?: string): void; + documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]): void; + completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string): void; /** * This method *requires* a contiguous, complete, and ordered stream of classifications for a file. */ - public syntacticClassificationsAre(...classifications: { classificationType: string; text: string }[]) { - FourSlash.currentTestState.verifySyntacticClassifications(classifications); - } - + syntacticClassificationsAre(...classifications: { + classificationType: string; + text: string; + }[]): void; /** * This method *requires* an ordered stream of classifications for a file, and spans are highly recommended. */ - public semanticClassificationsAre(...classifications: { classificationType: string; text: string; textSpan?: TextSpan }[]) { - FourSlash.currentTestState.verifySemanticClassifications(classifications); - } - - public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) { - FourSlash.currentTestState.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers) - } - - public renameInfoFailed(message?: string) { - FourSlash.currentTestState.verifyRenameInfoFailed(message) - } - - public renameLocations(findInStrings: boolean, findInComments: boolean) { - FourSlash.currentTestState.verifyRenameLocations(findInStrings, findInComments); - } - - public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; }, - displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) { - FourSlash.currentTestState.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation); - } - - public getSyntacticDiagnostics(expected: string) { - FourSlash.currentTestState.getSyntacticDiagnostics(expected); - } - - public getSemanticDiagnostics(expected: string) { - FourSlash.currentTestState.getSemanticDiagnostics(expected); - } - - public ProjectInfo(expected: string []) { - FourSlash.currentTestState.verifyProjectInfo(expected); - } + semanticClassificationsAre(...classifications: { + classificationType: string; + text: string; + textSpan?: TextSpan; + }[]): void; + renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string): void; + renameInfoFailed(message?: string): void; + renameLocations(findInStrings: boolean, findInComments: boolean): void; + verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { + start: number; + length: number; + }, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]): void; + getSyntacticDiagnostics(expected: string): void; + getSemanticDiagnostics(expected: string): void; + ProjectInfo(expected: string[]): void; } - - export class edit { - public backspace(count?: number) { - FourSlash.currentTestState.deleteCharBehindMarker(count); - } - - public deleteAtCaret(times?: number) { - FourSlash.currentTestState.deleteChar(times); - } - - public replace(start: number, length: number, text: string) { - FourSlash.currentTestState.replace(start, length, text); - } - - public paste(text: string) { - FourSlash.currentTestState.paste(text); - } - - public insert(text: string) { - this.insertLines(text); - } - - public insertLine(text: string) { - this.insertLines(text + '\n'); - } - - public insertLines(...lines: string[]) { - FourSlash.currentTestState.type(lines.join('\n')); - } - - public moveRight(count?: number) { - FourSlash.currentTestState.moveCaretRight(count); - } - - public moveLeft(count?: number) { - if (typeof count === 'undefined') { - count = 1; - } - FourSlash.currentTestState.moveCaretRight(count * -1); - } - - public enableFormatting() { - FourSlash.currentTestState.enableFormatting = true; - } - - public disableFormatting() { - FourSlash.currentTestState.enableFormatting = false; - } + class edit { + backspace(count?: number): void; + deleteAtCaret(times?: number): void; + replace(start: number, length: number, text: string): void; + paste(text: string): void; + insert(text: string): void; + insertLine(text: string): void; + insertLines(...lines: string[]): void; + moveRight(count?: number): void; + moveLeft(count?: number): void; + enableFormatting(): void; + disableFormatting(): void; } - - export class debug { - public printCurrentParameterHelp() { - FourSlash.currentTestState.printCurrentParameterHelp(); - } - - public printCurrentFileState() { - FourSlash.currentTestState.printCurrentFileState(); - } - - public printCurrentFileStateWithWhitespace() { - FourSlash.currentTestState.printCurrentFileState(/*withWhiteSpace=*/true); - } - - public printCurrentFileStateWithoutCaret() { - FourSlash.currentTestState.printCurrentFileState(/*withWhiteSpace=*/false, /*withCaret=*/false); - } - - public printCurrentQuickInfo() { - FourSlash.currentTestState.printCurrentQuickInfo(); - } - - public printCurrentSignatureHelp() { - FourSlash.currentTestState.printCurrentSignatureHelp(); - } - - public printMemberListMembers() { - FourSlash.currentTestState.printMemberListMembers(); - } - - public printCompletionListMembers() { - FourSlash.currentTestState.printCompletionListMembers(); - } - - public printBreakpointLocation(pos: number) { - FourSlash.currentTestState.printBreakpointLocation(pos); - } - public printBreakpointAtCurrentLocation() { - FourSlash.currentTestState.printBreakpointAtCurrentLocation(); - } - - public printNameOrDottedNameSpans(pos: number) { - FourSlash.currentTestState.printNameOrDottedNameSpans(pos); - } - - public printErrorList() { - FourSlash.currentTestState.printErrorList(); - } - - public printNavigationItems(searchValue: string = ".*") { - FourSlash.currentTestState.printNavigationItems(searchValue); - } - - public printScriptLexicalStructureItems() { - FourSlash.currentTestState.printScriptLexicalStructureItems(); - } - - public printReferences() { - FourSlash.currentTestState.printReferences(); - } - - public printContext() { - FourSlash.currentTestState.printContext(); - } + class debug { + printCurrentParameterHelp(): void; + printCurrentFileState(): void; + printCurrentFileStateWithWhitespace(): void; + printCurrentFileStateWithoutCaret(): void; + printCurrentQuickInfo(): void; + printCurrentSignatureHelp(): void; + printMemberListMembers(): void; + printCompletionListMembers(): void; + printBreakpointLocation(pos: number): void; + printBreakpointAtCurrentLocation(): void; + printNameOrDottedNameSpans(pos: number): void; + printErrorList(): void; + printNavigationItems(searchValue?: string): void; + printScriptLexicalStructureItems(): void; + printReferences(): void; + printContext(): void; } - - export class format { - public document() { - FourSlash.currentTestState.formatDocument(); - } - - public copyFormatOptions(): FormatCodeOptions { - return FourSlash.currentTestState.copyFormatOptions(); - } - - public setFormatOptions(options: FormatCodeOptions) { - return FourSlash.currentTestState.setFormatOptions(options); - } - - public selection(startMarker: string, endMarker: string) { - FourSlash.currentTestState.formatSelection(FourSlash.currentTestState.getMarkerByName(startMarker).position, FourSlash.currentTestState.getMarkerByName(endMarker).position); - } - - public setOption(name: string, value: number); - public setOption(name: string, value: string); - public setOption(name: string, value: boolean); - public setOption(name: string, value: any) { - FourSlash.currentTestState.formatCodeOptions[name] = value; - } + class format { + document(): void; + copyFormatOptions(): FormatCodeOptions; + setFormatOptions(options: FormatCodeOptions): any; + selection(startMarker: string, endMarker: string): void; + setOption(name: string, value: number): any; + setOption(name: string, value: string): any; + setOption(name: string, value: boolean): any; } - - export class cancellation { - public resetCancelled() { - FourSlash.currentTestState.resetCancelled(); - } - - public setCancelled(numberOfCalls: number = 0) { - FourSlash.currentTestState.setCancelled(numberOfCalls); - } + class cancellation { + resetCancelled(): void; + setCancelled(numberOfCalls?: number): void; } - - export module classification { - export function comment(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("comment", text, position); - } - - export function identifier(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("identifier", text, position); - } - - export function keyword(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("keyword", text, position); - } - - export function numericLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("numericLiteral", text, position); - } - - export function operator(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("operator", text, position); - } - - export function stringLiteral(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("stringLiteral", text, position); - } - - export function whiteSpace(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("whiteSpace", text, position); - } - - export function text(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("text", text, position); - } - - export function punctuation(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("punctuation", text, position); - } - - export function docCommentTagName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("docCommentTagName", text, position); - } - - export function className(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("className", text, position); - } - - export function enumName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("enumName", text, position); - } - - export function interfaceName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("interfaceName", text, position); - } - - export function moduleName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("moduleName", text, position); - } - - export function typeParameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("typeParameterName", text, position); - } - - export function parameterName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("parameterName", text, position); - } - - export function typeAliasName(text: string, position?: number): { classificationType: string; text: string; textSpan?: TextSpan } { - return getClassification("typeAliasName", text, position); - } - - function getClassification(type: string, text: string, position?: number) { - return { - classificationType: type, - text: text, - textSpan: position === undefined ? undefined : { start: position, end: position + text.length } - }; - } + module classification { + function comment(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function identifier(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function keyword(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function numericLiteral(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function operator(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function stringLiteral(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function whiteSpace(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function text(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function punctuation(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function docCommentTagName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function className(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function enumName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function interfaceName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function moduleName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function typeParameterName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function parameterName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; + function typeAliasName(text: string, position?: number): { + classificationType: string; + text: string; + textSpan?: TextSpan; + }; } } - -module fs { - export var test = new FourSlashInterface.test_(); - export var goTo = new FourSlashInterface.goTo(); - export var verify = new FourSlashInterface.verify(); - export var edit = new FourSlashInterface.edit(); - export var debug = new FourSlashInterface.debug(); - export var format = new FourSlashInterface.format(); - export var cancellation = new FourSlashInterface.cancellation(); +declare module fs { + var test: FourSlashInterface.test_; + var goTo: FourSlashInterface.goTo; + var verify: FourSlashInterface.verify; + var edit: FourSlashInterface.edit; + var debug: FourSlashInterface.debug; + var format: FourSlashInterface.format; + var cancellation: FourSlashInterface.cancellation; } - -function verifyOperationIsCancelled(f) { - FourSlash.verifyOperationIsCancelled(f); -} - -var test = new FourSlashInterface.test_(); -var goTo = new FourSlashInterface.goTo(); -var verify = new FourSlashInterface.verify(); -var edit = new FourSlashInterface.edit(); -var debug = new FourSlashInterface.debug(); -var format = new FourSlashInterface.format(); -var cancellation = new FourSlashInterface.cancellation(); -var classification = FourSlashInterface.classification; +declare function verifyOperationIsCancelled(f: any): void; +declare var test: FourSlashInterface.test_; +declare var goTo: FourSlashInterface.goTo; +declare var verify: FourSlashInterface.verify; +declare var edit: FourSlashInterface.edit; +declare var debug: FourSlashInterface.debug; +declare var format: FourSlashInterface.format; +declare var cancellation: FourSlashInterface.cancellation; +declare var classification: typeof FourSlashInterface.classification; diff --git a/tests/cases/fourslash/indentationBlock.ts b/tests/cases/fourslash/indentationBlock.ts index e880c4a0957..853ff43b0d6 100644 --- a/tests/cases/fourslash/indentationBlock.ts +++ b/tests/cases/fourslash/indentationBlock.ts @@ -179,5 +179,5 @@ ////{| "indent": 0 |} test.markers().forEach(marker => { - verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, IndentStyle.Block); + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, ts.IndentStyle.Block); }); diff --git a/tests/cases/fourslash/indentationNone.ts b/tests/cases/fourslash/indentationNone.ts index 078f5ab35f6..610a336cdda 100644 --- a/tests/cases/fourslash/indentationNone.ts +++ b/tests/cases/fourslash/indentationNone.ts @@ -179,5 +179,5 @@ ////{| "indent": 0 |} test.markers().forEach(marker => { - verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, IndentStyle.None); + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent, ts.IndentStyle.None); }); diff --git a/tests/cases/fourslash/recursiveClassReference.ts b/tests/cases/fourslash/recursiveClassReference.ts index d0e96ac90e3..81843711d65 100644 --- a/tests/cases/fourslash/recursiveClassReference.ts +++ b/tests/cases/fourslash/recursiveClassReference.ts @@ -11,4 +11,4 @@ //// } goTo.marker(); -fs.verify.quickInfoExists(); +verify.quickInfoExists(); diff --git a/tests/cases/fourslash/renameModuleToVar.ts b/tests/cases/fourslash/renameModuleToVar.ts index 023b0fa1c74..fc31f4040e8 100644 --- a/tests/cases/fourslash/renameModuleToVar.ts +++ b/tests/cases/fourslash/renameModuleToVar.ts @@ -10,7 +10,7 @@ //// var z = y + 5; ////} -fs.goTo.marker(); -fs.edit.backspace(6); -fs.edit.insert("var"); -fs.verify.numberOfErrorsInCurrentFile(0); \ No newline at end of file +goTo.marker(); +edit.backspace(6); +edit.insert("var"); +verify.numberOfErrorsInCurrentFile(0); From 076d65e1cf261277692591c33c5f4978c57c36d1 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Nov 2015 16:23:18 -0800 Subject: [PATCH 4/4] addressed PR feedback --- src/harness/compilerRunner.ts | 7 ++++--- src/harness/harness.ts | 24 +++++++++++++----------- tests/cases/fourslash/fourslash.ts | 11 +---------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 85a51b8f2a4..399f8a272dd 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -250,10 +250,11 @@ class CompilerBaselineRunner extends RunnerBase { // These types are equivalent, but depend on what order the compiler observed // certain parts of the program. - const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!result.program.getSourceFile(file.unitName)); + const program = result.program; + const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName)); - const fullWalker = new TypeWriterWalker(result.program, /*fullTypeCheck*/ true); - const pullWalker = new TypeWriterWalker(result.program, /*fullTypeCheck*/ false); + const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true); + const pullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ false); const fullResults: ts.Map = {}; const pullResults: ts.Map = {}; diff --git a/src/harness/harness.ts b/src/harness/harness.ts index e58e6635434..ef0f2678e29 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -767,9 +767,9 @@ namespace Harness { } namespace Harness { - const tcServicesFileName = "built/local/typescriptServices.js"; export const libFolder = "built/local/"; - export let tcServicesFile = IO.readFile(tcServicesFileName); + const tcServicesFileName = ts.combinePaths(libFolder, "typescriptServices.js"); + export const tcServicesFile = IO.readFile(tcServicesFileName); export interface SourceMapEmitterCallback { (emittedFile: string, emittedLine: number, emittedColumn: number, sourceFile: string, sourceLine: number, sourceColumn: number, sourceName: string): void; @@ -990,7 +990,6 @@ namespace Harness { options.noErrorTruncation = true; options.skipDefaultLibCheck = true; - const newLine = "\r\n"; currentDirectory = currentDirectory || Harness.IO.getCurrentDirectory(); // Parse settings @@ -1002,27 +1001,30 @@ namespace Harness { useCaseSensitiveFileNames = options.useCaseSensitiveFileNames; } + const programFiles: TestFile[] = inputFiles.slice(); // Files from built\local that are requested by test "@includeBuiltFiles" to be in the context. // Treat them as library files, so include them in build, but not in baselines. - const includeBuiltFiles: TestFile[] = []; if (options.includeBuiltFile) { - const builtFileName = libFolder + options.includeBuiltFile; + const builtFileName = ts.combinePaths(libFolder, options.includeBuiltFile); const builtFile: TestFile = { unitName: builtFileName, - content: normalizeLineEndings(IO.readFile(builtFileName), newLine), + content: normalizeLineEndings(IO.readFile(builtFileName), Harness.IO.newLine()), }; - includeBuiltFiles.push(builtFile); + programFiles.push(builtFile); } const fileOutputs: GeneratedFile[] = []; - const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); + const programFileNames = programFiles.map(file => file.unitName); const compilerHost = createCompilerHost( - inputFiles.concat(includeBuiltFiles).concat(otherFiles), + programFiles.concat(otherFiles), (fileName, code, writeByteOrderMark) => fileOutputs.push({ fileName, code, writeByteOrderMark }), - options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine); - const program = ts.createProgram(programFiles, options, compilerHost); + options.target, + useCaseSensitiveFileNames, + currentDirectory, + options.newLine); + const program = ts.createProgram(programFileNames, options, compilerHost); const emitResult = program.emit(); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 5b8bb94bb48..f93ac76d6ed 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -55,7 +55,7 @@ declare module ts { } } -declare module FourSlashInterface { +declare namespace FourSlashInterface { interface Marker { fileName: string; position: number; @@ -331,15 +331,6 @@ declare module FourSlashInterface { }; } } -declare module fs { - var test: FourSlashInterface.test_; - var goTo: FourSlashInterface.goTo; - var verify: FourSlashInterface.verify; - var edit: FourSlashInterface.edit; - var debug: FourSlashInterface.debug; - var format: FourSlashInterface.format; - var cancellation: FourSlashInterface.cancellation; -} declare function verifyOperationIsCancelled(f: any): void; declare var test: FourSlashInterface.test_; declare var goTo: FourSlashInterface.goTo;