From d9ec5125bed869d848586ab9610395d8c78a7dc1 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 6 Jun 2016 11:29:03 -0700 Subject: [PATCH] Support using string values in enums for CompilerOptions in transpile methods --- src/compiler/commandLineParser.ts | 2 +- src/services/services.ts | 36 +++++++++++++++++++++++++++--- tests/cases/unittests/transpile.ts | 33 ++++++++++++++++++++------- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 506a2d5bee4..55e7a2a3a2f 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -6,7 +6,7 @@ namespace ts { /* @internal */ - export let optionDeclarations: CommandLineOption[] = [ + export const optionDeclarations: CommandLineOption[] = [ { name: "charset", type: "string", diff --git a/src/services/services.ts b/src/services/services.ts index 34b521b3496..2664c430912 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1920,6 +1920,36 @@ namespace ts { sourceMapText?: string; } + /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */ + function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]) { + options = clone(options); + + for (const opt of stringValuedEnums) { + if (!hasProperty(options, opt.name)) { + continue; + } + + const value = options[opt.name]; + // Value should be a key of opt.type + if (typeof value === "string") { + // If value is not a string, this will fail + options[opt.name] = parseCustomTypeOption(opt, value, diagnostics); + } + else { + if (!forEachValue(opt.type, v => v === value)) { + // Supplied value isn't a valid enum value. + diagnostics.push(createCompilerDiagnosticForInvalidCustomType(opt)); + } + } + } + + return options; + } + + const stringValuedEnums = filter(optionDeclarations, o => { + return typeof o.type === "object" && !forEachValue(> o.type, v => typeof v !== "number"); + }); + /* * This function will compile source text from 'input' argument using specified compiler options. * If not options are provided - it will use a set of default compiler options. @@ -1930,7 +1960,9 @@ namespace ts { * - noResolve = true */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { - const options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); + const diagnostics: Diagnostic[] = []; + + const options: CompilerOptions = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : getDefaultCompilerOptions(); options.isolatedModules = true; @@ -1988,9 +2020,7 @@ namespace ts { const program = createProgram([inputFileName], options, compilerHost); - let diagnostics: Diagnostic[]; if (transpileOptions.reportDiagnostics) { - diagnostics = []; addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); } diff --git a/tests/cases/unittests/transpile.ts b/tests/cases/unittests/transpile.ts index 904cc435c44..ca2c5939f35 100644 --- a/tests/cases/unittests/transpile.ts +++ b/tests/cases/unittests/transpile.ts @@ -9,11 +9,7 @@ namespace ts { expectedDiagnosticCodes?: number[]; } - function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes?: number[]) { - if (!expectedDiagnosticCodes) { - return; - } - + function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes: number[] = []) { for (let i = 0; i < expectedDiagnosticCodes.length; i++) { assert.equal(expectedDiagnosticCodes[i], diagnostics[i] && diagnostics[i].code, `Could not find expeced diagnostic.`); } @@ -26,7 +22,7 @@ namespace ts { if (!transpileOptions.compilerOptions) { transpileOptions.compilerOptions = {}; } - if (transpileOptions.compilerOptions.newLine === undefined) { // + if (transpileOptions.compilerOptions.newLine === undefined) { // use \r\n as default new line transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed; } @@ -292,13 +288,34 @@ var x = 0;`, const output = `"use strict";\nvar a = 10;\n`; test(input, { expectedOutput: output, - options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true }, - expectedDiagnosticCodes: [] + options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } }); }); it("Supports urls in file name", () => { test("var x", { expectedOutput: `"use strict";\r\nvar x;\r\n`, options: { fileName: "http://somewhere/directory//directory2/file.ts" } }); }); + + describe("String values for enums", () => { + it("Accepts strings instead of enum values", () => { + test(`export const x = 0`, { + options: { + compilerOptions: { + module: "es6", + // Capitalization and spaces ignored + target: " Es6 " + } + }, + expectedOutput: "export const x = 0;\r\n" + }); + }); + + it("Fails on bad value", () => { + test(``, { + options: { compilerOptions: { module: {} } }, + expectedDiagnosticCodes: [6046] + }); + }); + }); }); }