diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5d6ab7abe9b54..889b387d4f4fb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5335,7 +5335,7 @@ module ts { } // Fall back to any. - if (compilerOptions.noImplicitAny && objectType !== anyType) { + if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && objectType !== anyType) { error(node, Diagnostics.Index_signature_of_object_type_implicitly_has_an_any_type); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 3fabf6c8588ac..ae4c751869c5c 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -88,6 +88,11 @@ module ts { description: Diagnostics.Redirect_output_structure_to_the_directory, paramType: Diagnostics.DIRECTORY, }, + { + name: "preserveConstEnums", + type: "boolean", + description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code + }, { name: "removeComments", type: "boolean", @@ -104,6 +109,11 @@ module ts { description: Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations, paramType: Diagnostics.LOCATION, }, + { + name: "suppressImplicitAnyIndexErrors", + type: "boolean", + description: Diagnostics.Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures, + }, { name: "target", shortName: "t", @@ -124,13 +134,8 @@ module ts { type: "boolean", description: Diagnostics.Watch_input_files, }, - { - name: "preserveConstEnums", - type: "boolean", - description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code - } ]; - + var shortOptionNames: Map = {}; var optionNameMap: Map = {}; diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 7377c42b238cc..6ce7579588ef3 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -411,6 +411,7 @@ module ts { Warn_on_expressions_and_declarations_with_an_implied_any_type: { code: 6052, category: DiagnosticCategory.Message, key: "Warn on expressions and declarations with an implied 'any' type." }, File_0_not_found: { code: 6053, category: DiagnosticCategory.Error, key: "File '{0}' not found." }, File_0_must_have_extension_ts_or_d_ts: { code: 6054, category: DiagnosticCategory.Error, key: "File '{0}' must have extension '.ts' or '.d.ts'." }, + Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f0dba54e1a1a4..3e5ac7ae1d653 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1643,6 +1643,10 @@ "category": "Error", "code": 6054 }, + "Suppress noImplicitAny errors for indexing objects lacking index signatures.": { + "category": "Message", + "code": 6055 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 5e4918d91e93a..bc4d48b751326 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -378,12 +378,12 @@ module ts { var usageText = " "; if (option.shortName) { usageText += "-" + option.shortName; - usageText += getParamName(option); + usageText += getParamType(option); usageText += ", "; } usageText += "--" + option.name; - usageText += getParamName(option); + usageText += getParamType(option); usageColumn.push(usageText); descriptionColumn.push(getDiagnosticText(option.description)); @@ -408,9 +408,9 @@ module ts { sys.write(output); return; - function getParamName(option: CommandLineOption) { - if (option.paramName !== undefined) { - return " " + getDiagnosticText(option.paramName); + function getParamType(option: CommandLineOption) { + if (option.paramType !== undefined) { + return " " + getDiagnosticText(option.paramType); } return ""; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fa23494f75545..102c468125235 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1358,6 +1358,7 @@ module ts { } export interface CompilerOptions { + allowNonTsExtensions?: boolean; charset?: string; codepage?: number; declaration?: boolean; @@ -1375,14 +1376,14 @@ module ts { noResolve?: boolean; out?: string; outDir?: string; + preserveConstEnums?: boolean; removeComments?: boolean; sourceMap?: boolean; sourceRoot?: string; + suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; version?: boolean; watch?: boolean; - preserveConstEnums?: boolean; - allowNonTsExtensions?: boolean; [option: string]: string | number | boolean; } @@ -1419,7 +1420,7 @@ module ts { type: string | Map; // "string", "number", "boolean", or an object literal mapping named values to actual values shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help'. description?: DiagnosticMessage; // The message describing what the command line switch does - paramName?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter. + paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter. error?: DiagnosticMessage; // The error given when the argument does not fit a customized 'type'. } @@ -1557,7 +1558,7 @@ module ts { tab = 0x09, // \t verticalTab = 0x0B, // \v } - + export interface CancellationToken { isCancellationRequested(): boolean; } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 374d08af1781a..c56b29ed3b856 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -781,6 +781,10 @@ module Harness { options.preserveConstEnums = setting.value === 'true'; break; + case 'suppressimplicitanyindexerrors': + options.suppressImplicitAnyIndexErrors = setting.value === 'true'; + break; + case 'includebuiltfile': inputFiles.push({ unitName: setting.value, content: IO.readFile(libFolder + setting.value)}); break; @@ -1170,7 +1174,8 @@ module Harness { var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines // List of allowed metadata names - var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noemitonerror", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "includebuiltfile"]; + + var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noemitonerror", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "includebuiltfile", "suppressimplicitanyindexerrors"]; function extractCompilerSettings(content: string): CompilerSetting[] { diff --git a/tests/baselines/reference/APISample_node_compile.js b/tests/baselines/reference/APISample_node_compile.js index bcadb7c109e9b..d4111bcafd433 100644 --- a/tests/baselines/reference/APISample_node_compile.js +++ b/tests/baselines/reference/APISample_node_compile.js @@ -1094,6 +1094,7 @@ declare module "typescript" { Message = 2, } interface CompilerOptions { + allowNonTsExtensions?: boolean; charset?: string; codepage?: number; declaration?: boolean; @@ -1111,14 +1112,14 @@ declare module "typescript" { noResolve?: boolean; out?: string; outDir?: string; + preserveConstEnums?: boolean; removeComments?: boolean; sourceMap?: boolean; sourceRoot?: string; + suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; version?: boolean; watch?: boolean; - preserveConstEnums?: boolean; - allowNonTsExtensions?: boolean; [option: string]: string | number | boolean; } const enum ModuleKind { @@ -1146,7 +1147,7 @@ declare module "typescript" { type: string | Map; shortName?: string; description?: DiagnosticMessage; - paramName?: DiagnosticMessage; + paramType?: DiagnosticMessage; error?: DiagnosticMessage; } const enum CharacterCodes { diff --git a/tests/baselines/reference/APISample_node_compile.types b/tests/baselines/reference/APISample_node_compile.types index 389093ba3e7d2..347c5aa358efe 100644 --- a/tests/baselines/reference/APISample_node_compile.types +++ b/tests/baselines/reference/APISample_node_compile.types @@ -3483,6 +3483,9 @@ declare module "typescript" { interface CompilerOptions { >CompilerOptions : CompilerOptions + allowNonTsExtensions?: boolean; +>allowNonTsExtensions : boolean + charset?: string; >charset : string @@ -3535,6 +3538,9 @@ declare module "typescript" { outDir?: string; >outDir : string + preserveConstEnums?: boolean; +>preserveConstEnums : boolean + removeComments?: boolean; >removeComments : boolean @@ -3544,6 +3550,9 @@ declare module "typescript" { sourceRoot?: string; >sourceRoot : string + suppressImplicitAnyIndexErrors?: boolean; +>suppressImplicitAnyIndexErrors : boolean + target?: ScriptTarget; >target : ScriptTarget >ScriptTarget : ScriptTarget @@ -3554,12 +3563,6 @@ declare module "typescript" { watch?: boolean; >watch : boolean - preserveConstEnums?: boolean; ->preserveConstEnums : boolean - - allowNonTsExtensions?: boolean; ->allowNonTsExtensions : boolean - [option: string]: string | number | boolean; >option : string } @@ -3630,8 +3633,8 @@ declare module "typescript" { >description : DiagnosticMessage >DiagnosticMessage : DiagnosticMessage - paramName?: DiagnosticMessage; ->paramName : DiagnosticMessage + paramType?: DiagnosticMessage; +>paramType : DiagnosticMessage >DiagnosticMessage : DiagnosticMessage error?: DiagnosticMessage; diff --git a/tests/baselines/reference/APISample_standalone_compile.js b/tests/baselines/reference/APISample_standalone_compile.js index edd6c3ed49b3b..6ba3d4f6b1bb0 100644 --- a/tests/baselines/reference/APISample_standalone_compile.js +++ b/tests/baselines/reference/APISample_standalone_compile.js @@ -1092,6 +1092,7 @@ declare module ts { Message = 2, } interface CompilerOptions { + allowNonTsExtensions?: boolean; charset?: string; codepage?: number; declaration?: boolean; @@ -1109,14 +1110,14 @@ declare module ts { noResolve?: boolean; out?: string; outDir?: string; + preserveConstEnums?: boolean; removeComments?: boolean; sourceMap?: boolean; sourceRoot?: string; + suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; version?: boolean; watch?: boolean; - preserveConstEnums?: boolean; - allowNonTsExtensions?: boolean; [option: string]: string | number | boolean; } const enum ModuleKind { @@ -1144,7 +1145,7 @@ declare module ts { type: string | Map; shortName?: string; description?: DiagnosticMessage; - paramName?: DiagnosticMessage; + paramType?: DiagnosticMessage; error?: DiagnosticMessage; } const enum CharacterCodes { diff --git a/tests/baselines/reference/APISample_standalone_compile.types b/tests/baselines/reference/APISample_standalone_compile.types index c4630007cba75..465a89b8f9708 100644 --- a/tests/baselines/reference/APISample_standalone_compile.types +++ b/tests/baselines/reference/APISample_standalone_compile.types @@ -3482,6 +3482,9 @@ declare module ts { interface CompilerOptions { >CompilerOptions : CompilerOptions + allowNonTsExtensions?: boolean; +>allowNonTsExtensions : boolean + charset?: string; >charset : string @@ -3534,6 +3537,9 @@ declare module ts { outDir?: string; >outDir : string + preserveConstEnums?: boolean; +>preserveConstEnums : boolean + removeComments?: boolean; >removeComments : boolean @@ -3543,6 +3549,9 @@ declare module ts { sourceRoot?: string; >sourceRoot : string + suppressImplicitAnyIndexErrors?: boolean; +>suppressImplicitAnyIndexErrors : boolean + target?: ScriptTarget; >target : ScriptTarget >ScriptTarget : ScriptTarget @@ -3553,12 +3562,6 @@ declare module ts { watch?: boolean; >watch : boolean - preserveConstEnums?: boolean; ->preserveConstEnums : boolean - - allowNonTsExtensions?: boolean; ->allowNonTsExtensions : boolean - [option: string]: string | number | boolean; >option : string } @@ -3629,8 +3632,8 @@ declare module ts { >description : DiagnosticMessage >DiagnosticMessage : DiagnosticMessage - paramName?: DiagnosticMessage; ->paramName : DiagnosticMessage + paramType?: DiagnosticMessage; +>paramType : DiagnosticMessage >DiagnosticMessage : DiagnosticMessage error?: DiagnosticMessage; diff --git a/tests/baselines/reference/noImplicitAnyIndexingSuppressed.js b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.js new file mode 100644 index 0000000000000..5185a9b8db846 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.js @@ -0,0 +1,81 @@ +//// [noImplicitAnyIndexingSuppressed.ts] + +enum MyEmusEnum { + emu +} + +// Should be okay; should be a string. +var strRepresentation1 = MyEmusEnum[0] + +// Should be okay; should be a string. +var strRepresentation2 = MyEmusEnum[MyEmusEnum.emu] + +// Should be okay, as we suppress implicit 'any' property access checks +var strRepresentation3 = MyEmusEnum["monehh"]; + +// Should be okay; should be a MyEmusEnum +var strRepresentation4 = MyEmusEnum["emu"]; + + +// Should be okay, as we suppress implicit 'any' property access checks +var x = {}["hi"]; + +// Should be okay, as we suppress implicit 'any' property access checks +var y = {}[10]; + +var hi: any = "hi"; + +var emptyObj = {}; + +// Should be okay, as we suppress implicit 'any' property access checks +var z1 = emptyObj[hi]; +var z2 = (emptyObj)[hi]; + +interface MyMap { + [key: string]: T; +} + +var m: MyMap = { + "0": 0, + "1": 1, + "2": 2, + "Okay that's enough for today.": NaN +}; + +var mResult1 = m[MyEmusEnum.emu]; +var mResult2 = m[MyEmusEnum[MyEmusEnum.emu]]; +var mResult3 = m[hi]; + + + +//// [noImplicitAnyIndexingSuppressed.js] +var MyEmusEnum; +(function (MyEmusEnum) { + MyEmusEnum[MyEmusEnum["emu"] = 0] = "emu"; +})(MyEmusEnum || (MyEmusEnum = {})); +// Should be okay; should be a string. +var strRepresentation1 = MyEmusEnum[0]; +// Should be okay; should be a string. +var strRepresentation2 = MyEmusEnum[0 /* emu */]; +// Should be okay, as we suppress implicit 'any' property access checks +var strRepresentation3 = MyEmusEnum["monehh"]; +// Should be okay; should be a MyEmusEnum +var strRepresentation4 = 0 /* "emu" */; +// Should be okay, as we suppress implicit 'any' property access checks +var x = {}["hi"]; +// Should be okay, as we suppress implicit 'any' property access checks +var y = {}[10]; +var hi = "hi"; +var emptyObj = {}; +// Should be okay, as we suppress implicit 'any' property access checks +var z1 = emptyObj[hi]; +var z2 = emptyObj[hi]; +var m = { + "0": 0, + "1": 1, + "2": 2, + "Okay that's enough for today.": NaN +}; +var mResult1 = m[0 /* emu */]; +var mResult2 = m[MyEmusEnum[0 /* emu */]]; +var mResult3 = m[hi]; diff --git a/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types new file mode 100644 index 0000000000000..20be75dc29e29 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types @@ -0,0 +1,118 @@ +=== tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts === + +enum MyEmusEnum { +>MyEmusEnum : MyEmusEnum + + emu +>emu : MyEmusEnum +} + +// Should be okay; should be a string. +var strRepresentation1 = MyEmusEnum[0] +>strRepresentation1 : string +>MyEmusEnum[0] : string +>MyEmusEnum : typeof MyEmusEnum + +// Should be okay; should be a string. +var strRepresentation2 = MyEmusEnum[MyEmusEnum.emu] +>strRepresentation2 : string +>MyEmusEnum[MyEmusEnum.emu] : string +>MyEmusEnum : typeof MyEmusEnum +>MyEmusEnum.emu : MyEmusEnum +>MyEmusEnum : typeof MyEmusEnum +>emu : MyEmusEnum + +// Should be okay, as we suppress implicit 'any' property access checks +var strRepresentation3 = MyEmusEnum["monehh"]; +>strRepresentation3 : any +>MyEmusEnum["monehh"] : any +>MyEmusEnum : typeof MyEmusEnum + +// Should be okay; should be a MyEmusEnum +var strRepresentation4 = MyEmusEnum["emu"]; +>strRepresentation4 : MyEmusEnum +>MyEmusEnum["emu"] : MyEmusEnum +>MyEmusEnum : typeof MyEmusEnum + + +// Should be okay, as we suppress implicit 'any' property access checks +var x = {}["hi"]; +>x : any +>{}["hi"] : any +>{} : {} + +// Should be okay, as we suppress implicit 'any' property access checks +var y = {}[10]; +>y : any +>{}[10] : any +>{} : {} + +var hi: any = "hi"; +>hi : any + +var emptyObj = {}; +>emptyObj : {} +>{} : {} + +// Should be okay, as we suppress implicit 'any' property access checks +var z1 = emptyObj[hi]; +>z1 : any +>emptyObj[hi] : any +>emptyObj : {} +>hi : any + +var z2 = (emptyObj)[hi]; +>z2 : any +>(emptyObj)[hi] : any +>(emptyObj) : any +>emptyObj : any +>emptyObj : {} +>hi : any + +interface MyMap { +>MyMap : MyMap +>T : T + + [key: string]: T; +>key : string +>T : T +} + +var m: MyMap = { +>m : MyMap +>MyMap : MyMap +>{ "0": 0, "1": 1, "2": 2, "Okay that's enough for today.": NaN} : { [x: string]: number; "0": number; "1": number; "2": number; "Okay that's enough for today.": number; } + + "0": 0, + "1": 1, + "2": 2, + "Okay that's enough for today.": NaN +>NaN : number + +}; + +var mResult1 = m[MyEmusEnum.emu]; +>mResult1 : number +>m[MyEmusEnum.emu] : number +>m : MyMap +>MyEmusEnum.emu : MyEmusEnum +>MyEmusEnum : typeof MyEmusEnum +>emu : MyEmusEnum + +var mResult2 = m[MyEmusEnum[MyEmusEnum.emu]]; +>mResult2 : number +>m[MyEmusEnum[MyEmusEnum.emu]] : number +>m : MyMap +>MyEmusEnum[MyEmusEnum.emu] : string +>MyEmusEnum : typeof MyEmusEnum +>MyEmusEnum.emu : MyEmusEnum +>MyEmusEnum : typeof MyEmusEnum +>emu : MyEmusEnum + +var mResult3 = m[hi]; +>mResult3 : number +>m[hi] : number +>m : MyMap +>hi : any + + diff --git a/tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts b/tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts new file mode 100644 index 0000000000000..42ae529fddce5 --- /dev/null +++ b/tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts @@ -0,0 +1,49 @@ +//@noImplicitAny: true +//@suppressImplicitAnyIndexErrors: true + +enum MyEmusEnum { + emu +} + +// Should be okay; should be a string. +var strRepresentation1 = MyEmusEnum[0] + +// Should be okay; should be a string. +var strRepresentation2 = MyEmusEnum[MyEmusEnum.emu] + +// Should be okay, as we suppress implicit 'any' property access checks +var strRepresentation3 = MyEmusEnum["monehh"]; + +// Should be okay; should be a MyEmusEnum +var strRepresentation4 = MyEmusEnum["emu"]; + + +// Should be okay, as we suppress implicit 'any' property access checks +var x = {}["hi"]; + +// Should be okay, as we suppress implicit 'any' property access checks +var y = {}[10]; + +var hi: any = "hi"; + +var emptyObj = {}; + +// Should be okay, as we suppress implicit 'any' property access checks +var z1 = emptyObj[hi]; +var z2 = (emptyObj)[hi]; + +interface MyMap { + [key: string]: T; +} + +var m: MyMap = { + "0": 0, + "1": 1, + "2": 2, + "Okay that's enough for today.": NaN +}; + +var mResult1 = m[MyEmusEnum.emu]; +var mResult2 = m[MyEmusEnum[MyEmusEnum.emu]]; +var mResult3 = m[hi]; +