From 8da3bd2ffd3ee662afd8f0bb9af441cd8ec6e741 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 15 Sep 2015 15:53:44 -0700 Subject: [PATCH] Project testcase to run tsconfig file --- src/compiler/program.ts | 4 +- src/compiler/tsc.ts | 2 +- src/harness/harness.ts | 10 +- src/harness/projectsRunner.ts | 141 ++++++++++++------ .../noProjectOptionAndInputFiles/amd/a.d.ts | 1 + .../noProjectOptionAndInputFiles/amd/a.js | 1 + .../amd/noProjectOptionAndInputFiles.json | 14 ++ .../noProjectOptionAndInputFiles/node/a.d.ts | 1 + .../noProjectOptionAndInputFiles/node/a.js | 1 + .../node/noProjectOptionAndInputFiles.json | 14 ++ .../project/projectOptionTest/amd/Test/a.d.ts | 1 + .../project/projectOptionTest/amd/Test/a.js | 1 + .../amd/projectOptionTest.json | 15 ++ .../projectOptionTest/node/Test/a.d.ts | 1 + .../project/projectOptionTest/node/Test/a.js | 1 + .../node/projectOptionTest.json | 15 ++ .../project/noProjectOptionAndInputFiles.json | 6 + tests/cases/project/projectOptionTest.json | 7 + tests/cases/projects/projectOption/Test/a.ts | 1 + tests/cases/projects/projectOption/Test/b.ts | 1 + .../projects/projectOption/Test/tsconfig.json | 1 + 21 files changed, 189 insertions(+), 50 deletions(-) create mode 100644 tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/a.d.ts create mode 100644 tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/a.js create mode 100644 tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/noProjectOptionAndInputFiles.json create mode 100644 tests/baselines/reference/project/noProjectOptionAndInputFiles/node/a.d.ts create mode 100644 tests/baselines/reference/project/noProjectOptionAndInputFiles/node/a.js create mode 100644 tests/baselines/reference/project/noProjectOptionAndInputFiles/node/noProjectOptionAndInputFiles.json create mode 100644 tests/baselines/reference/project/projectOptionTest/amd/Test/a.d.ts create mode 100644 tests/baselines/reference/project/projectOptionTest/amd/Test/a.js create mode 100644 tests/baselines/reference/project/projectOptionTest/amd/projectOptionTest.json create mode 100644 tests/baselines/reference/project/projectOptionTest/node/Test/a.d.ts create mode 100644 tests/baselines/reference/project/projectOptionTest/node/Test/a.js create mode 100644 tests/baselines/reference/project/projectOptionTest/node/projectOptionTest.json create mode 100644 tests/cases/project/noProjectOptionAndInputFiles.json create mode 100644 tests/cases/project/projectOptionTest.json create mode 100644 tests/cases/projects/projectOption/Test/a.ts create mode 100644 tests/cases/projects/projectOption/Test/b.ts create mode 100644 tests/cases/projects/projectOption/Test/tsconfig.json diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 5124dccee0..3c1d3a97d1 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -14,10 +14,10 @@ namespace ts { export const version = "1.6.0"; - export function findConfigFile(searchPath: string): string { + export function findConfigFile(searchPath: string, moduleResolutionHost: ModuleResolutionHost): string { let fileName = "tsconfig.json"; while (true) { - if (sys.fileExists(fileName)) { + if (moduleResolutionHost.fileExists(fileName)) { return fileName; } let parentPath = getDirectoryPath(searchPath); diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 96759b6825..805275776a 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -188,7 +188,7 @@ namespace ts { } else if (commandLine.fileNames.length === 0 && isJSONSupported()) { let searchPath = normalizePath(sys.getCurrentDirectory()); - configFileName = findConfigFile(searchPath); + configFileName = findConfigFile(searchPath, sys); } if (commandLine.fileNames.length === 0 && !configFileName) { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index be924fe6ae..9eb1cd45f5 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -430,6 +430,7 @@ module Harness { args(): string[]; getExecutingFilePath(): string; exit(exitCode?: number): void; + readDirectory(path: string, extension?: string, exclude?: string[]): string[]; } export var IO: IO; @@ -466,7 +467,8 @@ module Harness { export const directoryExists: typeof IO.directoryExists = fso.FolderExists; export const fileExists: typeof IO.fileExists = fso.FileExists; export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine; - + export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude); + export function createDirectory(path: string) { if (directoryExists(path)) { fso.CreateFolder(path); @@ -534,6 +536,8 @@ module Harness { export const fileExists: typeof IO.fileExists = fs.existsSync; export const log: typeof IO.log = s => console.log(s); + export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude); + export function createDirectory(path: string) { if (!directoryExists(path)) { fs.mkdirSync(path); @@ -732,6 +736,10 @@ module Harness { export function writeFile(path: string, contents: string) { Http.writeToServerSync(serverRoot + path, "WRITE", contents); } + + export function readDirectory(path: string, extension?: string, exclude?: string[]) { + return listFiles(path).filter(f => !extension || ts.fileExtensionIs(f, extension)); + } } } diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 12e3222a54..8b30a8be37 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -25,14 +25,14 @@ interface BatchCompileProjectTestCaseEmittedFile extends Harness.Compiler.Genera interface CompileProjectFilesResult { moduleKind: ts.ModuleKind; - program: ts.Program; + program?: ts.Program; + compilerOptions?: ts.CompilerOptions, errors: ts.Diagnostic[]; - sourceMapData: ts.SourceMapData[]; + sourceMapData?: ts.SourceMapData[]; } interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult { - outputFiles: BatchCompileProjectTestCaseEmittedFile[]; - nonSubfolderDiskFiles: number; + outputFiles?: BatchCompileProjectTestCaseEmittedFile[]; } class ProjectRunner extends RunnerBase { @@ -119,9 +119,10 @@ class ProjectRunner extends RunnerBase { function compileProjectFiles(moduleKind: ts.ModuleKind, getInputFiles: () => string[], getSourceFileText: (fileName: string) => string, - writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void): CompileProjectFilesResult { + writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void, + compilerOptions: ts.CompilerOptions): CompileProjectFilesResult { - let program = ts.createProgram(getInputFiles(), createCompilerOptions(), createCompilerHost()); + let program = ts.createProgram(getInputFiles(), compilerOptions, createCompilerHost()); let errors = ts.getPreEmitDiagnostics(program); let emitResult = program.emit(); @@ -146,38 +147,6 @@ class ProjectRunner extends RunnerBase { sourceMapData }; - function createCompilerOptions(): ts.CompilerOptions { - // Set the special options that depend on other testcase options - let compilerOptions: ts.CompilerOptions = { - mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? Harness.IO.resolvePath(testCase.mapRoot) : testCase.mapRoot, - sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? Harness.IO.resolvePath(testCase.sourceRoot) : testCase.sourceRoot, - module: moduleKind, - moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future - }; - - // Set the values specified using json - let optionNameMap: ts.Map = {}; - ts.forEach(ts.optionDeclarations, option => { - optionNameMap[option.name] = option; - }); - for (let name in testCase) { - if (name !== "mapRoot" && name !== "sourceRoot" && ts.hasProperty(optionNameMap, name)) { - let option = optionNameMap[name]; - let optType = option.type; - let value = testCase[name]; - if (typeof optType !== "string") { - let key = value.toLowerCase(); - if (ts.hasProperty(optType, key)) { - value = optType[key]; - } - } - compilerOptions[option.name] = value; - } - } - - return compilerOptions; - } - function getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile { let sourceFile: ts.SourceFile = undefined; if (fileName === Harness.Compiler.defaultLibFileName) { @@ -212,23 +181,99 @@ class ProjectRunner extends RunnerBase { let nonSubfolderDiskFiles = 0; let outputFiles: BatchCompileProjectTestCaseEmittedFile[] = []; + let compilerOptions = createCompilerOptions(); + let inputFiles = testCase.inputFiles; + let configFileName: string; + if (compilerOptions.project) { + // Parse project + configFileName = ts.normalizePath(ts.combinePaths(compilerOptions.project, "tsconfig.json")); + assert(!inputFiles || inputFiles.length === 0, "cannot specify input files and project option together"); + } + else if (!inputFiles || inputFiles.length === 0) { + configFileName = ts.findConfigFile("", { fileExists, readFile: getSourceFileText }); + } - let projectCompilerResult = compileProjectFiles(moduleKind, () => testCase.inputFiles, getSourceFileText, writeFile); + if (configFileName) { + let result = ts.readConfigFile(configFileName, getSourceFileText); + if (result.error) { + return { + moduleKind, + errors: [result.error] + }; + } + + let configObject = result.config; + let configParseResult = ts.parseConfigFile(configObject, { fileExists, readFile: getSourceFileText, readDirectory }, ts.getDirectoryPath(configFileName)); + if (configParseResult.errors.length > 0) { + return { + moduleKind, + errors: configParseResult.errors + }; + } + inputFiles = configParseResult.fileNames; + compilerOptions = ts.extend(compilerOptions, configParseResult.options); + } + + let projectCompilerResult = compileProjectFiles(moduleKind, () => inputFiles, getSourceFileText, writeFile, compilerOptions); return { moduleKind, program: projectCompilerResult.program, + compilerOptions, sourceMapData: projectCompilerResult.sourceMapData, outputFiles, errors: projectCompilerResult.errors, - nonSubfolderDiskFiles, }; + function createCompilerOptions(): ts.CompilerOptions { + // Set the special options that depend on other testcase options + let compilerOptions: ts.CompilerOptions = { + mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? Harness.IO.resolvePath(testCase.mapRoot) : testCase.mapRoot, + sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? Harness.IO.resolvePath(testCase.sourceRoot) : testCase.sourceRoot, + module: moduleKind, + moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future + }; + + // Set the values specified using json + let optionNameMap: ts.Map = {}; + ts.forEach(ts.optionDeclarations, option => { + optionNameMap[option.name] = option; + }); + for (let name in testCase) { + if (name !== "mapRoot" && name !== "sourceRoot" && ts.hasProperty(optionNameMap, name)) { + let option = optionNameMap[name]; + let optType = option.type; + let value = testCase[name]; + if (typeof optType !== "string") { + let key = value.toLowerCase(); + if (ts.hasProperty(optType, key)) { + value = optType[key]; + } + } + compilerOptions[option.name] = value; + } + } + + return compilerOptions; + } + + function getFileNameInTheProjectTest(fileName: string): string { + return ts.isRootedDiskPath(fileName) + ? fileName + : ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName); + } + + function readDirectory(rootDir: string, extension: string, exclude: string[]): string[] { + return Harness.IO.readDirectory(getFileNameInTheProjectTest(rootDir), extension, exclude); + } + + function fileExists(fileName: string): boolean { + return Harness.IO.fileExists(getFileNameInTheProjectTest(fileName)); + } + function getSourceFileText(fileName: string): string { let text: string = undefined; try { - text = Harness.IO.readFile(ts.isRootedDiskPath(fileName) - ? fileName - : ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName)); + text = Harness.IO.readFile(getFileNameInTheProjectTest(fileName)); } catch (e) { // text doesn't get defined. @@ -288,6 +333,9 @@ class ProjectRunner extends RunnerBase { function compileCompileDTsFiles(compilerResult: BatchCompileProjectTestCaseResult) { let allInputFiles: { emittedFileName: string; code: string; }[] = []; + if (!compilerResult.program) { + return; + } let compilerOptions = compilerResult.program.getCompilerOptions(); ts.forEach(compilerResult.program.getSourceFiles(), sourceFile => { @@ -317,7 +365,8 @@ class ProjectRunner extends RunnerBase { } }); - return compileProjectFiles(compilerResult.moduleKind, getInputFiles, getSourceFileText, writeFile); + // Dont allow config files since we are compiling existing source options + return compileProjectFiles(compilerResult.moduleKind, getInputFiles, getSourceFileText, writeFile, compilerResult.compilerOptions); function findOutpuDtsFile(fileName: string) { return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName ? outputFile : undefined); @@ -352,7 +401,7 @@ class ProjectRunner extends RunnerBase { function getCompilerResolutionInfo() { let resolutionInfo: ProjectRunnerTestCaseResolutionInfo & ts.CompilerOptions = JSON.parse(JSON.stringify(testCase)); - resolutionInfo.resolvedInputFiles = ts.map(compilerResult.program.getSourceFiles(), inputFile => inputFile.fileName); + resolutionInfo.resolvedInputFiles = ts.map(compilerResult.program ? compilerResult.program.getSourceFiles() : undefined, inputFile => inputFile.fileName); resolutionInfo.emittedFiles = ts.map(compilerResult.outputFiles, outputFile => outputFile.emittedFileName); return resolutionInfo; } @@ -409,7 +458,7 @@ class ProjectRunner extends RunnerBase { it("Errors in generated Dts files for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => { if (!compilerResult.errors.length && testCase.declaration) { let dTsCompileResult = compileCompileDTsFiles(compilerResult); - if (dTsCompileResult.errors.length) { + if (dTsCompileResult && dTsCompileResult.errors.length) { Harness.Baseline.runBaseline("Errors in generated Dts files for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".dts.errors.txt", () => { return getErrorsBaseline(dTsCompileResult); }); diff --git a/tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/a.d.ts b/tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/a.d.ts new file mode 100644 index 0000000000..4c0b898931 --- /dev/null +++ b/tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/a.d.ts @@ -0,0 +1 @@ +declare var test: number; diff --git a/tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/a.js b/tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/a.js new file mode 100644 index 0000000000..e757934f20 --- /dev/null +++ b/tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/a.js @@ -0,0 +1 @@ +var test = 10; diff --git a/tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/noProjectOptionAndInputFiles.json b/tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/noProjectOptionAndInputFiles.json new file mode 100644 index 0000000000..32b8c5a28f --- /dev/null +++ b/tests/baselines/reference/project/noProjectOptionAndInputFiles/amd/noProjectOptionAndInputFiles.json @@ -0,0 +1,14 @@ +{ + "scenario": "Verify project option", + "projectRoot": "tests/cases/projects/projectOption/Test", + "baselineCheck": true, + "declaration": true, + "resolvedInputFiles": [ + "lib.d.ts", + "a.ts" + ], + "emittedFiles": [ + "a.js", + "a.d.ts" + ] +} \ No newline at end of file diff --git a/tests/baselines/reference/project/noProjectOptionAndInputFiles/node/a.d.ts b/tests/baselines/reference/project/noProjectOptionAndInputFiles/node/a.d.ts new file mode 100644 index 0000000000..4c0b898931 --- /dev/null +++ b/tests/baselines/reference/project/noProjectOptionAndInputFiles/node/a.d.ts @@ -0,0 +1 @@ +declare var test: number; diff --git a/tests/baselines/reference/project/noProjectOptionAndInputFiles/node/a.js b/tests/baselines/reference/project/noProjectOptionAndInputFiles/node/a.js new file mode 100644 index 0000000000..e757934f20 --- /dev/null +++ b/tests/baselines/reference/project/noProjectOptionAndInputFiles/node/a.js @@ -0,0 +1 @@ +var test = 10; diff --git a/tests/baselines/reference/project/noProjectOptionAndInputFiles/node/noProjectOptionAndInputFiles.json b/tests/baselines/reference/project/noProjectOptionAndInputFiles/node/noProjectOptionAndInputFiles.json new file mode 100644 index 0000000000..32b8c5a28f --- /dev/null +++ b/tests/baselines/reference/project/noProjectOptionAndInputFiles/node/noProjectOptionAndInputFiles.json @@ -0,0 +1,14 @@ +{ + "scenario": "Verify project option", + "projectRoot": "tests/cases/projects/projectOption/Test", + "baselineCheck": true, + "declaration": true, + "resolvedInputFiles": [ + "lib.d.ts", + "a.ts" + ], + "emittedFiles": [ + "a.js", + "a.d.ts" + ] +} \ No newline at end of file diff --git a/tests/baselines/reference/project/projectOptionTest/amd/Test/a.d.ts b/tests/baselines/reference/project/projectOptionTest/amd/Test/a.d.ts new file mode 100644 index 0000000000..4c0b898931 --- /dev/null +++ b/tests/baselines/reference/project/projectOptionTest/amd/Test/a.d.ts @@ -0,0 +1 @@ +declare var test: number; diff --git a/tests/baselines/reference/project/projectOptionTest/amd/Test/a.js b/tests/baselines/reference/project/projectOptionTest/amd/Test/a.js new file mode 100644 index 0000000000..e757934f20 --- /dev/null +++ b/tests/baselines/reference/project/projectOptionTest/amd/Test/a.js @@ -0,0 +1 @@ +var test = 10; diff --git a/tests/baselines/reference/project/projectOptionTest/amd/projectOptionTest.json b/tests/baselines/reference/project/projectOptionTest/amd/projectOptionTest.json new file mode 100644 index 0000000000..e2be92cb38 --- /dev/null +++ b/tests/baselines/reference/project/projectOptionTest/amd/projectOptionTest.json @@ -0,0 +1,15 @@ +{ + "scenario": "Verify project option", + "projectRoot": "tests/cases/projects/projectOption", + "baselineCheck": true, + "declaration": true, + "project": "Test", + "resolvedInputFiles": [ + "lib.d.ts", + "Test/a.ts" + ], + "emittedFiles": [ + "Test/a.js", + "Test/a.d.ts" + ] +} \ No newline at end of file diff --git a/tests/baselines/reference/project/projectOptionTest/node/Test/a.d.ts b/tests/baselines/reference/project/projectOptionTest/node/Test/a.d.ts new file mode 100644 index 0000000000..4c0b898931 --- /dev/null +++ b/tests/baselines/reference/project/projectOptionTest/node/Test/a.d.ts @@ -0,0 +1 @@ +declare var test: number; diff --git a/tests/baselines/reference/project/projectOptionTest/node/Test/a.js b/tests/baselines/reference/project/projectOptionTest/node/Test/a.js new file mode 100644 index 0000000000..e757934f20 --- /dev/null +++ b/tests/baselines/reference/project/projectOptionTest/node/Test/a.js @@ -0,0 +1 @@ +var test = 10; diff --git a/tests/baselines/reference/project/projectOptionTest/node/projectOptionTest.json b/tests/baselines/reference/project/projectOptionTest/node/projectOptionTest.json new file mode 100644 index 0000000000..e2be92cb38 --- /dev/null +++ b/tests/baselines/reference/project/projectOptionTest/node/projectOptionTest.json @@ -0,0 +1,15 @@ +{ + "scenario": "Verify project option", + "projectRoot": "tests/cases/projects/projectOption", + "baselineCheck": true, + "declaration": true, + "project": "Test", + "resolvedInputFiles": [ + "lib.d.ts", + "Test/a.ts" + ], + "emittedFiles": [ + "Test/a.js", + "Test/a.d.ts" + ] +} \ No newline at end of file diff --git a/tests/cases/project/noProjectOptionAndInputFiles.json b/tests/cases/project/noProjectOptionAndInputFiles.json new file mode 100644 index 0000000000..b391da41dc --- /dev/null +++ b/tests/cases/project/noProjectOptionAndInputFiles.json @@ -0,0 +1,6 @@ +{ + "scenario": "Verify project option", + "projectRoot": "tests/cases/projects/projectOption/Test", + "baselineCheck": true, + "declaration": true +} \ No newline at end of file diff --git a/tests/cases/project/projectOptionTest.json b/tests/cases/project/projectOptionTest.json new file mode 100644 index 0000000000..70ae0435ee --- /dev/null +++ b/tests/cases/project/projectOptionTest.json @@ -0,0 +1,7 @@ +{ + "scenario": "Verify project option", + "projectRoot": "tests/cases/projects/projectOption", + "baselineCheck": true, + "declaration": true, + "project": "Test" +} \ No newline at end of file diff --git a/tests/cases/projects/projectOption/Test/a.ts b/tests/cases/projects/projectOption/Test/a.ts new file mode 100644 index 0000000000..6d820a0093 --- /dev/null +++ b/tests/cases/projects/projectOption/Test/a.ts @@ -0,0 +1 @@ +var test = 10; \ No newline at end of file diff --git a/tests/cases/projects/projectOption/Test/b.ts b/tests/cases/projects/projectOption/Test/b.ts new file mode 100644 index 0000000000..a6bd8e8d43 --- /dev/null +++ b/tests/cases/projects/projectOption/Test/b.ts @@ -0,0 +1 @@ +var test = 10; // Shouldnt get compiled so shouldnt error \ No newline at end of file diff --git a/tests/cases/projects/projectOption/Test/tsconfig.json b/tests/cases/projects/projectOption/Test/tsconfig.json new file mode 100644 index 0000000000..1c0fb80335 --- /dev/null +++ b/tests/cases/projects/projectOption/Test/tsconfig.json @@ -0,0 +1 @@ +{ "files": [ "a.ts" ] } \ No newline at end of file