Skip to content

Commit d9ec512

Browse files
author
Andy Hanson
committed
Support using string values in enums for CompilerOptions in transpile methods
1 parent 13ddc34 commit d9ec512

3 files changed

Lines changed: 59 additions & 12 deletions

File tree

src/compiler/commandLineParser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace ts {
88
/* @internal */
9-
export let optionDeclarations: CommandLineOption[] = [
9+
export const optionDeclarations: CommandLineOption[] = [
1010
{
1111
name: "charset",
1212
type: "string",

src/services/services.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1920,6 +1920,36 @@ namespace ts {
19201920
sourceMapText?: string;
19211921
}
19221922

1923+
/** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */
1924+
function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]) {
1925+
options = clone(options);
1926+
1927+
for (const opt of stringValuedEnums) {
1928+
if (!hasProperty(options, opt.name)) {
1929+
continue;
1930+
}
1931+
1932+
const value = options[opt.name];
1933+
// Value should be a key of opt.type
1934+
if (typeof value === "string") {
1935+
// If value is not a string, this will fail
1936+
options[opt.name] = parseCustomTypeOption(opt, value, diagnostics);
1937+
}
1938+
else {
1939+
if (!forEachValue(opt.type, v => v === value)) {
1940+
// Supplied value isn't a valid enum value.
1941+
diagnostics.push(createCompilerDiagnosticForInvalidCustomType(opt));
1942+
}
1943+
}
1944+
}
1945+
1946+
return options;
1947+
}
1948+
1949+
const stringValuedEnums = <CommandLineOptionOfCustomType[]>filter(optionDeclarations, o => {
1950+
return typeof o.type === "object" && !forEachValue(<Map<any>> o.type, v => typeof v !== "number");
1951+
});
1952+
19231953
/*
19241954
* This function will compile source text from 'input' argument using specified compiler options.
19251955
* If not options are provided - it will use a set of default compiler options.
@@ -1930,7 +1960,9 @@ namespace ts {
19301960
* - noResolve = true
19311961
*/
19321962
export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput {
1933-
const options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions();
1963+
const diagnostics: Diagnostic[] = [];
1964+
1965+
const options: CompilerOptions = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : getDefaultCompilerOptions();
19341966

19351967
options.isolatedModules = true;
19361968

@@ -1988,9 +2020,7 @@ namespace ts {
19882020

19892021
const program = createProgram([inputFileName], options, compilerHost);
19902022

1991-
let diagnostics: Diagnostic[];
19922023
if (transpileOptions.reportDiagnostics) {
1993-
diagnostics = [];
19942024
addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile));
19952025
addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics());
19962026
}

tests/cases/unittests/transpile.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ namespace ts {
99
expectedDiagnosticCodes?: number[];
1010
}
1111

12-
function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes?: number[]) {
13-
if (!expectedDiagnosticCodes) {
14-
return;
15-
}
16-
12+
function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes: number[] = []) {
1713
for (let i = 0; i < expectedDiagnosticCodes.length; i++) {
1814
assert.equal(expectedDiagnosticCodes[i], diagnostics[i] && diagnostics[i].code, `Could not find expeced diagnostic.`);
1915
}
@@ -26,7 +22,7 @@ namespace ts {
2622
if (!transpileOptions.compilerOptions) {
2723
transpileOptions.compilerOptions = {};
2824
}
29-
if (transpileOptions.compilerOptions.newLine === undefined) { //
25+
if (transpileOptions.compilerOptions.newLine === undefined) {
3026
// use \r\n as default new line
3127
transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed;
3228
}
@@ -292,13 +288,34 @@ var x = 0;`,
292288
const output = `"use strict";\nvar a = 10;\n`;
293289
test(input, {
294290
expectedOutput: output,
295-
options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true },
296-
expectedDiagnosticCodes: []
291+
options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true }
297292
});
298293
});
299294

300295
it("Supports urls in file name", () => {
301296
test("var x", { expectedOutput: `"use strict";\r\nvar x;\r\n`, options: { fileName: "http://somewhere/directory//directory2/file.ts" } });
302297
});
298+
299+
describe("String values for enums", () => {
300+
it("Accepts strings instead of enum values", () => {
301+
test(`export const x = 0`, {
302+
options: {
303+
compilerOptions: {
304+
module: <ModuleKind><any>"es6",
305+
// Capitalization and spaces ignored
306+
target: <ScriptTarget><any>" Es6 "
307+
}
308+
},
309+
expectedOutput: "export const x = 0;\r\n"
310+
});
311+
});
312+
313+
it("Fails on bad value", () => {
314+
test(``, {
315+
options: { compilerOptions: { module: <ModuleKind><any>{} } },
316+
expectedDiagnosticCodes: [6046]
317+
});
318+
});
319+
});
303320
});
304321
}

0 commit comments

Comments
 (0)