From d60c640d0f3bd75fe743a29d726787acb0f2469f Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 23 Oct 2017 12:39:10 -0700 Subject: [PATCH 1/5] Add utility function to check for strict option flags - Correctelly check for noImplicitAny in checker - Correctelly check for noImplicitAny in installTypesForPackage refactor --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 10 +++++----- src/compiler/core.ts | 4 ++++ src/compiler/program.ts | 4 ++-- src/compiler/transformers/module/module.ts | 2 +- src/compiler/transformers/module/system.ts | 2 +- src/compiler/transformers/ts.ts | 4 ++-- src/services/refactors/installTypesForPackage.ts | 3 +-- 8 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 35a62a644d839..99047e200175a 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -192,7 +192,7 @@ namespace ts { return bindSourceFile; function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean { - if ((opts.alwaysStrict === undefined ? opts.strict : opts.alwaysStrict) && !file.isDeclarationFile) { + if (getStrictOptionValue(opts, "alwaysStrict") && !file.isDeclarationFile) { // bind in strict mode source files with alwaysStrict option return true; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index da3dac4d60504..f1f4d55fa69b7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -65,10 +65,10 @@ namespace ts { const modulekind = getEmitModuleKind(compilerOptions); const noUnusedIdentifiers = !!compilerOptions.noUnusedLocals || !!compilerOptions.noUnusedParameters; const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; - const strictNullChecks = compilerOptions.strictNullChecks === undefined ? compilerOptions.strict : compilerOptions.strictNullChecks; - const strictFunctionTypes = compilerOptions.strictFunctionTypes === undefined ? compilerOptions.strict : compilerOptions.strictFunctionTypes; - const noImplicitAny = compilerOptions.noImplicitAny === undefined ? compilerOptions.strict : compilerOptions.noImplicitAny; - const noImplicitThis = compilerOptions.noImplicitThis === undefined ? compilerOptions.strict : compilerOptions.noImplicitThis; + const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks"); + const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes"); + const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny"); + const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis"); const emitResolver = createResolver(); const nodeBuilder = createNodeBuilder(); @@ -6875,7 +6875,7 @@ namespace ts { const numTypeArguments = length(node.typeArguments); const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); const isJs = isInJavaScriptFile(node); - const isJsImplicitAny = !compilerOptions.noImplicitAny && isJs; + const isJsImplicitAny = !noImplicitAny && isJs; if (!isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { const missingAugmentsTag = isJs && node.parent.kind !== SyntaxKind.JSDocAugmentsTag; const diag = minTypeArgumentCount === typeParameters.length diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 12b8dd2f87e63..1db21ae46f06e 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1710,6 +1710,10 @@ namespace ts { return moduleResolution; } + export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"): boolean { + return compilerOptions[flag] === undefined ? compilerOptions.strict : compilerOptions[flag]; + } + export function hasZeroOrOneAsteriskCharacter(str: string): boolean { let seenAsterisk = false; for (let i = 0; i < str.length; i++) { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 1d325983f5fc6..dadac596e9806 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2127,7 +2127,7 @@ namespace ts { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"); } - if (options.noImplicitUseStrict && (options.alwaysStrict === undefined ? options.strict : options.alwaysStrict)) { + if (options.noImplicitUseStrict && getStrictOptionValue(options, "alwaysStrict")) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"); } @@ -2356,7 +2356,7 @@ namespace ts { return options.jsx ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set; } function needAllowJs() { - return options.allowJs || !options.noImplicitAny ? undefined : Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type; + return options.allowJs || !getStrictOptionValue(options, "noImplicitAny") ? undefined : Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type; } } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index bd360fdffe404..f60e50ea36587 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -91,7 +91,7 @@ namespace ts { startLexicalEnvironment(); const statements: Statement[] = []; - const ensureUseStrict = compilerOptions.alwaysStrict || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); + const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); const statementOffset = addPrologue(statements, node.statements, ensureUseStrict, sourceElementVisitor); if (shouldEmitUnderscoreUnderscoreESModule()) { diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index d674546efb902..a481f0c1d4036 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -225,7 +225,7 @@ namespace ts { startLexicalEnvironment(); // Add any prologue directives. - const ensureUseStrict = compilerOptions.alwaysStrict || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); + const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); const statementOffset = addPrologue(statements, node.statements, ensureUseStrict, sourceElementVisitor); // var __moduleName = context_1 && context_1.id; diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index ba4b5fcdf521e..ffaecd77d718d 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -45,7 +45,7 @@ namespace ts { const resolver = context.getEmitResolver(); const compilerOptions = context.getCompilerOptions(); - const strictNullChecks = typeof compilerOptions.strictNullChecks === "undefined" ? compilerOptions.strict : compilerOptions.strictNullChecks; + const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks"); const languageVersion = getEmitScriptTarget(compilerOptions); const moduleKind = getEmitModuleKind(compilerOptions); @@ -521,7 +521,7 @@ namespace ts { } function visitSourceFile(node: SourceFile) { - const alwaysStrict = (compilerOptions.alwaysStrict === undefined ? compilerOptions.strict : compilerOptions.alwaysStrict) && + const alwaysStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") && !(isExternalModule(node) && moduleKind >= ModuleKind.ES2015); return updateSourceFileNode( node, diff --git a/src/services/refactors/installTypesForPackage.ts b/src/services/refactors/installTypesForPackage.ts index 5edc557071096..996645fc15d3b 100644 --- a/src/services/refactors/installTypesForPackage.ts +++ b/src/services/refactors/installTypesForPackage.ts @@ -12,8 +12,7 @@ namespace ts.refactor.installTypesForPackage { registerRefactor(installTypesForPackage); function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { - const options = context.program.getCompilerOptions(); - if (options.noImplicitAny || options.strict) { + if (getStrictOptionValue(context.program.getCompilerOptions(), "noImplicitAny")) { // Then it will be available via `fixCannotFindModule`. return undefined; } From 97cd7bf5af7bcf6a96c3688919d92b9fbc928b9d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 27 Oct 2017 10:14:21 -0700 Subject: [PATCH 2/5] Respond to code review comments --- src/compiler/core.ts | 2 +- src/compiler/types.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 1db21ae46f06e..9daf31f7899c0 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1710,7 +1710,7 @@ namespace ts { return moduleResolution; } - export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"): boolean { + export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { return compilerOptions[flag] === undefined ? compilerOptions.strict : compilerOptions[flag]; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fb59c9eb8812c..8749d06b43df6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3676,6 +3676,8 @@ namespace ts { export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | null | undefined; + export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; + export interface CompilerOptions { /*@internal*/ all?: boolean; allowJs?: boolean; From cf4ef62830b4ee5555125ce214d824e16c244488 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 27 Oct 2017 11:02:43 -0700 Subject: [PATCH 3/5] Accept baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 62f4f68d148cc..11162e8c86fb4 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2200,6 +2200,7 @@ declare namespace ts { name: string; } type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | null | undefined; + type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; interface CompilerOptions { allowJs?: boolean; allowSyntheticDefaultImports?: boolean; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index c7c8ba88d7277..2c225efb03bd9 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2200,6 +2200,7 @@ declare namespace ts { name: string; } type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | null | undefined; + type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; interface CompilerOptions { allowJs?: boolean; allowSyntheticDefaultImports?: boolean; From 6ef5e14c796339fcf4c408c09643ac429e17a253 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 27 Oct 2017 12:08:32 -0700 Subject: [PATCH 4/5] Revert "Accept baselines" This reverts commit cf4ef62830b4ee5555125ce214d824e16c244488. --- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 - tests/baselines/reference/api/typescript.d.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 11162e8c86fb4..62f4f68d148cc 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2200,7 +2200,6 @@ declare namespace ts { name: string; } type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | null | undefined; - type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; interface CompilerOptions { allowJs?: boolean; allowSyntheticDefaultImports?: boolean; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2c225efb03bd9..c7c8ba88d7277 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2200,7 +2200,6 @@ declare namespace ts { name: string; } type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | null | undefined; - type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; interface CompilerOptions { allowJs?: boolean; allowSyntheticDefaultImports?: boolean; From 25492b7925262b0377995d532421a565d9d0d933 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 27 Oct 2017 12:09:32 -0700 Subject: [PATCH 5/5] Move type alias to core --- src/compiler/core.ts | 2 ++ src/compiler/types.ts | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 9daf31f7899c0..b954d16fd9d25 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1710,6 +1710,8 @@ namespace ts { return moduleResolution; } + export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; + export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { return compilerOptions[flag] === undefined ? compilerOptions.strict : compilerOptions[flag]; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8749d06b43df6..fb59c9eb8812c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3676,8 +3676,6 @@ namespace ts { export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | null | undefined; - export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; - export interface CompilerOptions { /*@internal*/ all?: boolean; allowJs?: boolean;