Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New --strict master option #14486

Merged
merged 5 commits into from
Mar 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ namespace ts {
return bindSourceFile;

function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean {
if (opts.alwaysStrict && !isDeclarationFile(file)) {
if ((opts.alwaysStrict === undefined ? opts.strict : opts.alwaysStrict) && !isDeclarationFile(file)) {
// bind in strict mode source files with alwaysStrict option
return true;
}
Expand Down
40 changes: 21 additions & 19 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ 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;
const strictNullChecks = compilerOptions.strictNullChecks === undefined ? compilerOptions.strict : compilerOptions.strictNullChecks;
const noImplicitAny = compilerOptions.noImplicitAny === undefined ? compilerOptions.strict : compilerOptions.noImplicitAny;
const noImplicitThis = compilerOptions.noImplicitThis === undefined ? compilerOptions.strict : compilerOptions.noImplicitThis;

const emitResolver = createResolver();

Expand Down Expand Up @@ -1564,7 +1566,7 @@ namespace ts {
error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName);
return undefined;
}
else if (compilerOptions.noImplicitAny && moduleNotFoundError) {
else if (noImplicitAny && moduleNotFoundError) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sort of thing is a bug waiting to happen - it is very likely that next time someone will need to check a flag like noImplicitAny, they will go through compilerOptions first. That said, I'm not sure what else we could do here.

error(errorNode,
Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type,
moduleReference,
Expand Down Expand Up @@ -3407,7 +3409,7 @@ namespace ts {
return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality);
}

if ((compilerOptions.noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) &&
if ((noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) &&
declaration.kind === SyntaxKind.VariableDeclaration && !isBindingPattern(declaration.name) &&
!(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !isInAmbientContext(declaration)) {
// If --noImplicitAny is on or the declaration is in a Javascript file,
Expand Down Expand Up @@ -3509,7 +3511,7 @@ namespace ts {
if (isBindingPattern(element.name)) {
return getTypeFromBindingPattern(<BindingPattern>element.name, includePatternInType, reportErrors);
}
if (reportErrors && compilerOptions.noImplicitAny && !declarationBelongsToPrivateAmbientMember(element)) {
if (reportErrors && noImplicitAny && !declarationBelongsToPrivateAmbientMember(element)) {
reportImplicitAnyError(element, anyType);
}
return anyType;
Expand Down Expand Up @@ -3607,7 +3609,7 @@ namespace ts {
type = declaration.dotDotDotToken ? anyArrayType : anyType;

// Report implicit any errors unless this is a private property within an ambient declaration
if (reportErrors && compilerOptions.noImplicitAny) {
if (reportErrors && noImplicitAny) {
if (!declarationBelongsToPrivateAmbientMember(declaration)) {
reportImplicitAnyError(declaration, type);
}
Expand Down Expand Up @@ -3726,7 +3728,7 @@ namespace ts {
}
// Otherwise, fall back to 'any'.
else {
if (compilerOptions.noImplicitAny) {
if (noImplicitAny) {
if (setter) {
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
}
Expand All @@ -3741,7 +3743,7 @@ namespace ts {
}
if (!popTypeResolution()) {
type = anyType;
if (compilerOptions.noImplicitAny) {
if (noImplicitAny) {
const getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
}
Expand Down Expand Up @@ -3824,7 +3826,7 @@ namespace ts {
return unknownType;
}
// Otherwise variable has initializer that circularly references the variable itself
if (compilerOptions.noImplicitAny) {
if (noImplicitAny) {
error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
symbolToString(symbol));
}
Expand Down Expand Up @@ -5585,7 +5587,7 @@ namespace ts {
}
if (!popTypeResolution()) {
type = anyType;
if (compilerOptions.noImplicitAny) {
if (noImplicitAny) {
const declaration = <Declaration>signature.declaration;
if (declaration.name) {
error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(declaration.name));
Expand Down Expand Up @@ -6540,7 +6542,7 @@ namespace ts {
return indexInfo.type;
}
if (accessExpression && !isConstEnumObjectType(objectType)) {
if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) {
if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) {
if (getIndexTypeOfType(objectType, IndexKind.Number)) {
error(accessExpression.argumentExpression, Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number);
}
Expand Down Expand Up @@ -9126,7 +9128,7 @@ namespace ts {
}

function reportErrorsFromWidening(declaration: Declaration, type: Type) {
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsWideningType) {
if (produceDiagnostics && noImplicitAny && type.flags & TypeFlags.ContainsWideningType) {
// Report implicit any error within type if possible, otherwise report error on declaration
if (!reportWideningErrorsInType(type)) {
reportImplicitAnyError(declaration, type);
Expand Down Expand Up @@ -11007,7 +11009,7 @@ namespace ts {
// control flow based type does include undefined.
if (type === autoType || type === autoArrayType) {
if (flowType === autoType || flowType === autoArrayType) {
if (compilerOptions.noImplicitAny) {
if (noImplicitAny) {
error(declaration.name, Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType));
error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType));
}
Expand Down Expand Up @@ -11277,7 +11279,7 @@ namespace ts {
}
}

if (compilerOptions.noImplicitThis) {
if (noImplicitThis) {
// With noImplicitThis, functions may not reference 'this' if it has type 'any'
error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation);
}
Expand Down Expand Up @@ -12531,7 +12533,7 @@ namespace ts {
return links.resolvedSymbol = unknownSymbol;
}
else {
if (compilerOptions.noImplicitAny) {
if (noImplicitAny) {
error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, JsxNames.IntrinsicElements);
}
return links.resolvedSymbol = unknownSymbol;
Expand Down Expand Up @@ -12919,7 +12921,7 @@ namespace ts {
}

if (jsxElementType === undefined) {
if (compilerOptions.noImplicitAny) {
if (noImplicitAny) {
error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist);
}
}
Expand Down Expand Up @@ -14742,7 +14744,7 @@ namespace ts {
if (funcSymbol && funcSymbol.members && funcSymbol.flags & SymbolFlags.Function) {
return getInferredClassType(funcSymbol);
}
else if (compilerOptions.noImplicitAny) {
else if (noImplicitAny) {
error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
}
return anyType;
Expand Down Expand Up @@ -15002,7 +15004,7 @@ namespace ts {
const iterableIteratorAny = functionFlags & FunctionFlags.Async
? createAsyncIterableIteratorType(anyType) // AsyncGenerator function
: createIterableIteratorType(anyType); // Generator function
if (compilerOptions.noImplicitAny) {
if (noImplicitAny) {
error(func.asteriskToken,
Diagnostics.Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type, typeToString(iterableIteratorAny));
}
Expand Down Expand Up @@ -16546,7 +16548,7 @@ namespace ts {

if (produceDiagnostics) {
checkCollisionWithArgumentsInGeneratedCode(node);
if (compilerOptions.noImplicitAny && !node.type) {
if (noImplicitAny && !node.type) {
switch (node.kind) {
case SyntaxKind.ConstructSignature:
error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
Expand Down Expand Up @@ -17858,7 +17860,7 @@ namespace ts {
if (produceDiagnostics && !node.type) {
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
// in an ambient context
if (compilerOptions.noImplicitAny && nodeIsMissing(node.body) && !isPrivateWithinAmbient(node)) {
if (noImplicitAny && nodeIsMissing(node.body) && !isPrivateWithinAmbient(node)) {
reportImplicitAnyError(node, anyType);
}

Expand Down
7 changes: 6 additions & 1 deletion src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,11 @@ namespace ts {
type: "boolean",
description: Diagnostics.Parse_in_strict_mode_and_emit_use_strict_for_each_source_file
},
{
name: "strict",
type: "boolean",
description: Diagnostics.Enable_all_strict_type_checks
},
{
// A list of plugins to load in the language service
name: "plugins",
Expand Down Expand Up @@ -520,7 +525,7 @@ namespace ts {
export const defaultInitCompilerOptions: CompilerOptions = {
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
strict: true,
sourceMap: false,
};

Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3045,6 +3045,10 @@
"category": "Message",
"code": 6149
},
"Enable all strict type checks.": {
"category": "Message",
"code": 6150
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1630,7 +1630,7 @@ namespace ts {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"));
}

if (options.noImplicitUseStrict && options.alwaysStrict) {
if (options.noImplicitUseStrict && (options.alwaysStrict === undefined ? options.strict : options.alwaysStrict)) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"));
}

Expand Down
3 changes: 2 additions & 1 deletion src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ namespace ts {
}

function visitSourceFile(node: SourceFile) {
const alwaysStrict = compilerOptions.alwaysStrict && !(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
const alwaysStrict = (compilerOptions.alwaysStrict === undefined ? compilerOptions.strict : compilerOptions.alwaysStrict) &&
!(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
return updateSourceFileNode(
node,
visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict));
Expand Down
9 changes: 5 additions & 4 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3308,7 +3308,7 @@
allowSyntheticDefaultImports?: boolean;
allowUnreachableCode?: boolean;
allowUnusedLabels?: boolean;
alwaysStrict?: boolean;
alwaysStrict?: boolean; // Always combine with strict property
baseUrl?: string;
charset?: string;
/* @internal */ configFilePath?: string;
Expand Down Expand Up @@ -3344,9 +3344,9 @@
noEmitOnError?: boolean;
noErrorTruncation?: boolean;
noFallthroughCasesInSwitch?: boolean;
noImplicitAny?: boolean;
noImplicitAny?: boolean; // Always combine with strict property
noImplicitReturns?: boolean;
noImplicitThis?: boolean;
noImplicitThis?: boolean; // Always combine with strict property
noUnusedLocals?: boolean;
noUnusedParameters?: boolean;
noImplicitUseStrict?: boolean;
Expand All @@ -3369,7 +3369,8 @@
skipDefaultLibCheck?: boolean;
sourceMap?: boolean;
sourceRoot?: string;
strictNullChecks?: boolean;
strict?: boolean;
strictNullChecks?: boolean; // Always combine with strict property
/* @internal */ stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"strict": true,
"sourceMap": false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"strict": true,
"sourceMap": false,
"noUnusedLocals": true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"strict": true,
"sourceMap": false,
"jsx": "react"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"strict": true,
"sourceMap": false
},
"files": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"strict": true,
"sourceMap": false,
"lib": [
"es5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"strict": true,
"sourceMap": false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"strict": true,
"sourceMap": false,
"lib": [
"es5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"strict": true,
"sourceMap": false,
"types": [
"jquery",
Expand Down