diff --git a/Jakefile.js b/Jakefile.js
index cfc3ca7929c..fec30947e71 100644
--- a/Jakefile.js
+++ b/Jakefile.js
@@ -209,7 +209,8 @@ var harnessSources = harnessCoreSources.concat([
"convertCompilerOptionsFromJson.ts",
"convertTypingOptionsFromJson.ts",
"tsserverProjectSystem.ts",
- "matchFiles.ts"
+ "matchFiles.ts",
+ "initializeTSConfig.ts",
].map(function (f) {
return path.join(unittestsDirectory, f);
})).concat([
diff --git a/scripts/ior.ts b/scripts/ior.ts
index eb67e62a275..91580203350 100644
--- a/scripts/ior.ts
+++ b/scripts/ior.ts
@@ -1,4 +1,4 @@
-///
+///
import fs = require('fs');
import path = require('path');
diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts
index 616bf5e70c0..6406455d713 100644
--- a/src/compiler/commandLineParser.ts
+++ b/src/compiler/commandLineParser.ts
@@ -126,6 +126,10 @@ namespace ts {
type: "boolean",
description: Diagnostics.Do_not_emit_outputs_if_any_errors_were_reported,
},
+ {
+ name: "noErrorTruncation",
+ type: "boolean"
+ },
{
name: "noImplicitAny",
type: "boolean",
@@ -462,6 +466,14 @@ namespace ts {
shortOptionNames: Map;
}
+ /* @internal */
+ export const defaultInitCompilerOptions: CompilerOptions = {
+ module: ModuleKind.CommonJS,
+ target: ScriptTarget.ES5,
+ noImplicitAny: false,
+ sourceMap: false,
+ };
+
let optionNameMapCache: OptionNameMap;
/* @internal */
@@ -667,6 +679,94 @@ namespace ts {
}
}
+ /**
+ * Generate tsconfig configuration when running command line "--init"
+ * @param options commandlineOptions to be generated into tsconfig.json
+ * @param fileNames array of filenames to be generated into tsconfig.json
+ */
+ /* @internal */
+ export function generateTSConfig(options: CompilerOptions, fileNames: string[]): { compilerOptions: Map } {
+ const compilerOptions = extend(options, defaultInitCompilerOptions);
+ const configurations: any = {
+ compilerOptions: serializeCompilerOptions(compilerOptions)
+ };
+ if (fileNames && fileNames.length) {
+ // only set the files property if we have at least one file
+ configurations.files = fileNames;
+ }
+
+ return configurations;
+
+ function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map | undefined {
+ if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") {
+ // this is of a type CommandLineOptionOfPrimitiveType
+ return undefined;
+ }
+ else if (optionDefinition.type === "list") {
+ return getCustomTypeMapOfCommandLineOption((optionDefinition).element);
+ }
+ else {
+ return (optionDefinition).type;
+ }
+ }
+
+ function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: MapLike): string | undefined {
+ // There is a typeMap associated with this command-line option so use it to map value back to its name
+ for (const key in customTypeMap) {
+ if (customTypeMap[key] === value) {
+ return key;
+ }
+ }
+ return undefined;
+ }
+
+ function serializeCompilerOptions(options: CompilerOptions): Map {
+ const result = createMap();
+ const optionsNameMap = getOptionNameMap().optionNameMap;
+
+ for (const name in options) {
+ if (hasProperty(options, name)) {
+ // tsconfig only options cannot be specified via command line,
+ // so we can assume that only types that can appear here string | number | boolean
+ switch (name) {
+ case "init":
+ case "watch":
+ case "version":
+ case "help":
+ case "project":
+ break;
+ default:
+ const value = options[name];
+ let optionDefinition = optionsNameMap[name.toLowerCase()];
+ if (optionDefinition) {
+ const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
+ if (!customTypeMap) {
+ // There is no map associated with this compiler option then use the value as-is
+ // This is the case if the value is expect to be string, number, boolean or list of string
+ result[name] = value;
+ }
+ else {
+ if (optionDefinition.type === "list") {
+ const convertedValue: string[] = [];
+ for (const element of value as (string | number)[]) {
+ convertedValue.push(getNameOfCompilerOptionValue(element, customTypeMap));
+ }
+ result[name] = convertedValue;
+ }
+ else {
+ // There is a typeMap associated with this command-line option so use it to map value back to its name
+ result[name] = getNameOfCompilerOptionValue(value, customTypeMap);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ return result;
+ }
+ }
+
/**
* Remove the comments from a json like text.
* Comments can be single line comments (starting with # or //) or multiline comments using / * * /
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 869f2decce7..357a15507a4 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -5311,6 +5311,21 @@ const _super = (function (geti, seti) {
emitSignatureParameters(ctor);
}
else {
+ // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation:
+ // If constructor is empty, then
+ // If ClassHeritag_eopt is present and protoParent is not null, then
+ // Let constructor be the result of parsing the source text
+ // constructor(...args) { super (...args);}
+ // using the syntactic grammar with the goal symbol MethodDefinition[~Yield].
+ // Else,
+ // Let constructor be the result of parsing the source text
+ // constructor( ){ }
+ // using the syntactic grammar with the goal symbol MethodDefinition[~Yield].
+ //
+ // While we could emit the '...args' rest parameter, certain later tools in the pipeline might
+ // downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array.
+ // Instead, we'll avoid using a rest parameter and spread into the super call as
+ // 'super(...arguments)' instead of 'super(...args)', as you can see below.
write("()");
}
}
@@ -5349,6 +5364,7 @@ const _super = (function (geti, seti) {
write("_super.apply(this, arguments);");
}
else {
+ // See comment above on using '...arguments' instead of '...args'.
write("super(...arguments);");
}
emitEnd(baseTypeElement);
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 60ee66a6aa6..510ff94f0dc 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -828,14 +828,6 @@ namespace ts {
: { resolvedModule: undefined, failedLookupLocations };
}
- /* @internal */
- export const defaultInitCompilerOptions: CompilerOptions = {
- module: ModuleKind.CommonJS,
- target: ScriptTarget.ES5,
- noImplicitAny: false,
- sourceMap: false,
- };
-
interface OutputFingerprint {
hash: string;
byteOrderMark: boolean;
diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts
index 8b445bcb626..62b58609086 100644
--- a/src/compiler/tsc.ts
+++ b/src/compiler/tsc.ts
@@ -763,67 +763,11 @@ namespace ts {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined);
}
else {
- const compilerOptions = extend(options, defaultInitCompilerOptions);
- const configurations: any = {
- compilerOptions: serializeCompilerOptions(compilerOptions)
- };
-
- if (fileNames && fileNames.length) {
- // only set the files property if we have at least one file
- configurations.files = fileNames;
- }
- else {
- configurations.exclude = ["node_modules"];
- if (compilerOptions.outDir) {
- configurations.exclude.push(compilerOptions.outDir);
- }
- }
-
- sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
+ sys.writeFile(file, JSON.stringify(generateTSConfig(options, fileNames), undefined, 4));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined);
}
return;
-
- function serializeCompilerOptions(options: CompilerOptions): Map {
- const result = createMap();
- const optionsNameMap = getOptionNameMap().optionNameMap;
-
- for (const name in options) {
- if (hasProperty(options, name)) {
- // tsconfig only options cannot be specified via command line,
- // so we can assume that only types that can appear here string | number | boolean
- const value = options[name];
- switch (name) {
- case "init":
- case "watch":
- case "version":
- case "help":
- case "project":
- break;
- default:
- let optionDefinition = optionsNameMap[name.toLowerCase()];
- if (optionDefinition) {
- if (typeof optionDefinition.type === "string") {
- // string, number or boolean
- result[name] = value;
- }
- else {
- // Enum
- const typeMap =