diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f18a0b2a32a23..a95baef7d4ccd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29504,7 +29504,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { node.kind === SyntaxKind.PropertyDeclaration)!; } - // Check if a parameter or catch variable is assigned anywhere + // Check if a parameter, catch variable, or mutable local variable is assigned anywhere definitely + function isSymbolAssignedDefinitely(symbol: Symbol) { + if (symbol.lastAssignmentPos !== undefined) { + return symbol.lastAssignmentPos < 0; + } + return isSymbolAssigned(symbol) && symbol.lastAssignmentPos !== undefined && symbol.lastAssignmentPos < 0; + } + + // Check if a parameter, catch variable, or mutable local variable is assigned anywhere function isSymbolAssigned(symbol: Symbol) { return !isPastLastAssignment(symbol, /*location*/ undefined); } @@ -29523,7 +29531,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { markNodeAssignments(parent); } } - return !symbol.lastAssignmentPos || location && symbol.lastAssignmentPos < location.pos; + return !symbol.lastAssignmentPos || location && Math.abs(symbol.lastAssignmentPos) < location.pos; } // Check if a parameter or catch variable (or their bindings elements) is assigned anywhere @@ -29557,12 +29565,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function markNodeAssignments(node: Node) { switch (node.kind) { case SyntaxKind.Identifier: - if (isAssignmentTarget(node)) { + const assigmentTarget = getAssignmentTargetKind(node); + if (assigmentTarget !== AssignmentKind.None) { const symbol = getResolvedSymbol(node as Identifier); - if (isParameterOrMutableLocalVariable(symbol) && symbol.lastAssignmentPos !== Number.MAX_VALUE) { - const referencingFunction = findAncestor(node, isFunctionOrSourceFile); - const declaringFunction = findAncestor(symbol.valueDeclaration, isFunctionOrSourceFile); - symbol.lastAssignmentPos = referencingFunction === declaringFunction ? extendAssignmentPosition(node, symbol.valueDeclaration!) : Number.MAX_VALUE; + const hasDefiniteAssignment = assigmentTarget === AssignmentKind.Definite || (symbol.lastAssignmentPos !== undefined && symbol.lastAssignmentPos < 0); + if (isParameterOrMutableLocalVariable(symbol)) { + if (symbol.lastAssignmentPos === undefined || Math.abs(symbol.lastAssignmentPos) !== Number.MAX_VALUE) { + const referencingFunction = findAncestor(node, isFunctionOrSourceFile); + const declaringFunction = findAncestor(symbol.valueDeclaration, isFunctionOrSourceFile); + symbol.lastAssignmentPos = referencingFunction === declaringFunction ? extendAssignmentPosition(node, symbol.valueDeclaration!) : Number.MAX_VALUE; + } + if (hasDefiniteAssignment && symbol.lastAssignmentPos > 0) { + symbol.lastAssignmentPos *= -1; + } } } return; @@ -29572,7 +29587,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!(node as ExportSpecifier).isTypeOnly && !exportDeclaration.isTypeOnly && !exportDeclaration.moduleSpecifier && name.kind !== SyntaxKind.StringLiteral) { const symbol = resolveEntityName(name, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true); if (symbol && isParameterOrMutableLocalVariable(symbol)) { - symbol.lastAssignmentPos = Number.MAX_VALUE; + const sign = symbol.lastAssignmentPos !== undefined && symbol.lastAssignmentPos < 0 ? -1 : 1; + symbol.lastAssignmentPos = sign * Number.MAX_VALUE; } } return; @@ -30316,6 +30332,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); let declaration = localOrExportSymbol.valueDeclaration; + const immediateDeclaration = declaration; // If the identifier is declared in a binding pattern for which we're currently computing the implied type and the // reference occurs with the same binding pattern, return the non-inferrable any type. This for example occurs in @@ -30405,7 +30422,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We only look for uninitialized variables in strict null checking mode, and only when we can analyze // the entire control flow graph from the variable's declaration (i.e. when the flow container and // declaration container are the same). - const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAssignmentTarget || isModuleExports || isSameScopedBindingElement(node, declaration) || + const isNeverInitialized = immediateDeclaration && isVariableDeclaration(immediateDeclaration) && !immediateDeclaration.initializer && !immediateDeclaration.exclamationToken && isMutableLocalVariableDeclaration(immediateDeclaration) && !isSymbolAssignedDefinitely(symbol); + const assumeInitialized = isParameter || isAlias || + (isOuterVariable && !isNeverInitialized) || + isSpreadDestructuringAssignmentTarget || isModuleExports || isSameScopedBindingElement(node, declaration) || type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void)) !== 0 || isInTypeQuery(node) || isInAmbientOrTypeNode(node) || node.parent.kind === SyntaxKind.ExportSpecifier) || node.parent.kind === SyntaxKind.NonNullExpression || @@ -43264,7 +43284,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - if (node.body) { // Don't report unused parameters in overloads + // Only report unused parameters on the implementation, not overloads. + if (node.body) { checkUnusedLocalsAndParameters(node, addDiagnostic); } checkUnusedTypeParameters(node, addDiagnostic); diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index 5a1b432179210..7d8bc6f8eab22 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -228,6 +228,7 @@ import { } from "../_namespaces/ts.js"; const enum ClassPropertySubstitutionFlags { + None = 0, /** * Enables substitutions for class expressions with static fields * which have initializers that reference the class name. @@ -401,7 +402,7 @@ export function transformClassFields(context: TransformationContext): (x: Source context.onEmitNode = onEmitNode; let shouldTransformPrivateStaticElementsInFile = false; - let enabledSubstitutions: ClassPropertySubstitutionFlags; + let enabledSubstitutions = ClassPropertySubstitutionFlags.None; let classAliases: Identifier[]; diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index e8dffceda4de1..5b29d34da9387 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -218,6 +218,7 @@ import { } from "../_namespaces/ts.js"; const enum ES2015SubstitutionFlags { + None = 0, /** Enables substitutions for captured `this` */ CapturedThis = 1 << 0, /** Enables substitutions for block-scoped bindings. */ @@ -523,7 +524,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile * They are persisted between each SourceFile transformation and should not * be reset. */ - let enabledSubstitutions: ES2015SubstitutionFlags; + let enabledSubstitutions = ES2015SubstitutionFlags.None; return chainBundle(context, transformSourceFile); diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index e1f0c9756b242..8947a94a079f4 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -104,6 +104,7 @@ import { type SuperContainer = ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration; const enum ES2017SubstitutionFlags { + None = 0, /** Enables substitutions for async methods with `super` calls. */ AsyncMethodsWithSuper = 1 << 0, } @@ -132,7 +133,7 @@ export function transformES2017(context: TransformationContext): (x: SourceFile * Keeps track of whether expression substitution has been enabled for specific edge cases. * They are persisted between each SourceFile transformation and should not be reset. */ - let enabledSubstitutions: ES2017SubstitutionFlags; + let enabledSubstitutions = ES2017SubstitutionFlags.None; /** * This keeps track of containers where `super` is valid, for use with diff --git a/src/compiler/transformers/es2018.ts b/src/compiler/transformers/es2018.ts index 4eff61428d9fd..c8894d336af1c 100644 --- a/src/compiler/transformers/es2018.ts +++ b/src/compiler/transformers/es2018.ts @@ -113,6 +113,7 @@ import { } from "../_namespaces/ts.js"; const enum ESNextSubstitutionFlags { + None = 0, /** Enables substitutions for async methods with `super` calls. */ AsyncMethodsWithSuper = 1 << 0, } @@ -170,7 +171,7 @@ export function transformES2018(context: TransformationContext): (x: SourceFile context.onSubstituteNode = onSubstituteNode; let exportedVariableStatement = false; - let enabledSubstitutions: ESNextSubstitutionFlags; + let enabledSubstitutions = ESNextSubstitutionFlags.None; let enclosingFunctionFlags: FunctionFlags; let parametersWithPrecedingObjectRestOrSpread: Set | undefined; let enclosingSuperContainerFlags: NodeCheckFlags = 0; diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 668da90d8e696..2d9981391186c 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -209,6 +209,7 @@ import { const USE_NEW_TYPE_METADATA_FORMAT = false; const enum TypeScriptSubstitutionFlags { + None = 0, /** Enables substitutions for namespace exports. */ NamespaceExports = 1 << 1, /* Enables substitutions for unqualified enum members */ @@ -272,7 +273,7 @@ export function transformTypeScript(context: TransformationContext) { * Keeps track of whether expression substitution has been enabled for specific edge cases. * They are persisted between each SourceFile transformation and should not be reset. */ - let enabledSubstitutions: TypeScriptSubstitutionFlags; + let enabledSubstitutions = TypeScriptSubstitutionFlags.None; /** * Keeps track of whether we are within any containing namespaces when performing diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 564fa64e1294c..fd7470ea1ca19 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5944,7 +5944,7 @@ export interface Symbol { /** @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol /** @internal */ constEnumOnlyModule: boolean | undefined; // True if module contains only const enums or other modules with only const enums /** @internal */ isReferenced?: SymbolFlags; // True if the symbol is referenced elsewhere. Keeps track of the meaning of a reference in case a symbol is both a type parameter and parameter. - /** @internal */ lastAssignmentPos?: number; // Source position of last node that assigns value to symbol + /** @internal */ lastAssignmentPos?: number; // Source position of last node that assigns value to symbol. Negative if it is assigned anywhere definitely /** @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol? /** @internal */ assignmentDeclarationMembers?: Map; // detected late-bound assignment declarations associated with the symbol } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a1ef5bb08d8e3..b7642d5c7c9b2 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -153,6 +153,8 @@ import { forEachChild, forEachChildRecursively, ForInOrOfStatement, + ForInStatement, + ForOfStatement, ForStatement, FunctionBody, FunctionDeclaration, @@ -7905,6 +7907,9 @@ function accessKind(node: Node): AccessKind { return node === (parent as ShorthandPropertyAssignment).objectAssignmentInitializer ? AccessKind.Read : accessKind(parent.parent); case SyntaxKind.ArrayLiteralExpression: return accessKind(parent); + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + return node === (parent as ForInStatement | ForOfStatement).initializer ? AccessKind.Write : AccessKind.Read; default: return AccessKind.Read; } diff --git a/tests/baselines/reference/findAllRefsObjectBindingElementPropertyName06.baseline.jsonc b/tests/baselines/reference/findAllRefsObjectBindingElementPropertyName06.baseline.jsonc index 5051e0492a750..3dd00d3b7f57c 100644 --- a/tests/baselines/reference/findAllRefsObjectBindingElementPropertyName06.baseline.jsonc +++ b/tests/baselines/reference/findAllRefsObjectBindingElementPropertyName06.baseline.jsonc @@ -13,7 +13,7 @@ // for (<|var { [|property1|]: p1 } of elems|>) { // } // var p2; -// for (<|{ [|{| isWriteAccess: true |}property1|] : p2 } of elems|>) { +// for (<|{ [|property1|] : p2 } of elems|>) { // } // === Definitions === @@ -94,7 +94,7 @@ // for (<|var { [|property1|]: p1 } of elems|>) { // } // var p2; -// for (<|{ [|{| isWriteAccess: true |}property1|] : p2 } of elems|>) { +// for (<|{ [|property1|] : p2 } of elems|>) { // } // === Definitions === @@ -180,7 +180,7 @@ // for (<|var { /*FIND ALL REFS*/[|property1|]: p1 } of elems|>) { // } // var p2; -// for (<|{ [|{| isWriteAccess: true |}property1|] : p2 } of elems|>) { +// for (<|{ [|property1|] : p2 } of elems|>) { // } // === Definitions === @@ -270,7 +270,7 @@ // for (<|var { [|property1|]: p1 } of elems|>) { // } // var p2; -// for (<|{ /*FIND ALL REFS*/[|{| isWriteAccess: true, isDefinition: true |}property1|] : p2 } of elems|>) { +// for (<|{ /*FIND ALL REFS*/[|{| isDefinition: true |}property1|] : p2 } of elems|>) { // } // === Definitions === @@ -358,7 +358,7 @@ // for (<|var { [|{| defId: 0 |}property1|]: p1 } of elems|>) { // } // var p2; -// for (<|{ [|{| defId: 0, isWriteAccess: true |}property1|] : p2 } of elems|>) { +// for (<|{ [|{| defId: 0 |}property1|] : p2 } of elems|>) { // } // === Definitions === diff --git a/tests/baselines/reference/narrowingPastLastAssignment.errors.txt b/tests/baselines/reference/narrowingPastLastAssignment.errors.txt index 0477f4c4877a1..d601615b04455 100644 --- a/tests/baselines/reference/narrowingPastLastAssignment.errors.txt +++ b/tests/baselines/reference/narrowingPastLastAssignment.errors.txt @@ -1,8 +1,9 @@ narrowingPastLastAssignment.ts(88,9): error TS7034: Variable 'x' implicitly has type 'any' in some locations where its type cannot be determined. narrowingPastLastAssignment.ts(90,20): error TS7005: Variable 'x' implicitly has an 'any' type. +narrowingPastLastAssignment.ts(161,9): error TS18048: 'foo' is possibly 'undefined'. -==== narrowingPastLastAssignment.ts (2 errors) ==== +==== narrowingPastLastAssignment.ts (3 errors) ==== function action(f: Function) {} // Narrowings are preserved in closures created past last assignment @@ -160,4 +161,15 @@ narrowingPastLastAssignment.ts(90,20): error TS7005: Variable 'x' implicitly has } values.forEach(v => foo.push(v)); } - \ No newline at end of file + + function f13() { + // Test for captured 'var' declaration (as opposed to parameters, let, const). + var foo: string | undefined; + foo = ''; + + return () => { + foo.toLocaleLowerCase(); + ~~~ +!!! error TS18048: 'foo' is possibly 'undefined'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/narrowingPastLastAssignment.symbols b/tests/baselines/reference/narrowingPastLastAssignment.symbols index 4ace603d16418..0aa5ff567438f 100644 --- a/tests/baselines/reference/narrowingPastLastAssignment.symbols +++ b/tests/baselines/reference/narrowingPastLastAssignment.symbols @@ -363,3 +363,20 @@ function f12() { >v : Symbol(v, Decl(narrowingPastLastAssignment.ts, 151, 19)) } +function f13() { +>f13 : Symbol(f13, Decl(narrowingPastLastAssignment.ts, 152, 1)) + + // Test for captured 'var' declaration (as opposed to parameters, let, const). + var foo: string | undefined; +>foo : Symbol(foo, Decl(narrowingPastLastAssignment.ts, 156, 7)) + + foo = ''; +>foo : Symbol(foo, Decl(narrowingPastLastAssignment.ts, 156, 7)) + + return () => { + foo.toLocaleLowerCase(); +>foo.toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --), Decl(lib.es2020.string.d.ts, --, --)) +>foo : Symbol(foo, Decl(narrowingPastLastAssignment.ts, 156, 7)) +>toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.es5.d.ts, --, --), Decl(lib.es2020.string.d.ts, --, --)) + } +} diff --git a/tests/baselines/reference/narrowingPastLastAssignment.types b/tests/baselines/reference/narrowingPastLastAssignment.types index ba185b982df4f..50e1d0d26665c 100644 --- a/tests/baselines/reference/narrowingPastLastAssignment.types +++ b/tests/baselines/reference/narrowingPastLastAssignment.types @@ -731,3 +731,35 @@ function f12() { > : ^^^^^^ } +function f13() { +>f13 : () => () => void +> : ^^^^^^^^^^^^^^^^ + + // Test for captured 'var' declaration (as opposed to parameters, let, const). + var foo: string | undefined; +>foo : string | undefined +> : ^^^^^^^^^^^^^^^^^^ + + foo = ''; +>foo = '' : "" +> : ^^ +>foo : string | undefined +> : ^^^^^^^^^^^^^^^^^^ +>'' : "" +> : ^^ + + return () => { +>() => { foo.toLocaleLowerCase(); } : () => void +> : ^^^^^^^^^^ + + foo.toLocaleLowerCase(); +>foo.toLocaleLowerCase() : string +> : ^^^^^^ +>foo.toLocaleLowerCase : { (locales?: string | string[]): string; (locales?: Intl.LocalesArgument): string; } +> : ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ +>foo : string | undefined +> : ^^^^^^^^^^^^^^^^^^ +>toLocaleLowerCase : { (locales?: string | string[]): string; (locales?: Intl.LocalesArgument): string; } +> : ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ + } +} diff --git a/tests/baselines/reference/typeGuardsAsAssertions.errors.txt b/tests/baselines/reference/typeGuardsAsAssertions.errors.txt new file mode 100644 index 0000000000000..dbe1d428c4bed --- /dev/null +++ b/tests/baselines/reference/typeGuardsAsAssertions.errors.txt @@ -0,0 +1,138 @@ +typeGuardsAsAssertions.ts(23,12): error TS2454: Variable 'cond' is used before being assigned. +typeGuardsAsAssertions.ts(33,12): error TS2454: Variable 'cond' is used before being assigned. +typeGuardsAsAssertions.ts(44,12): error TS2454: Variable 'cond' is used before being assigned. + + +==== typeGuardsAsAssertions.ts (3 errors) ==== + // Repro from #8513 + + let cond: boolean; + + export type Optional = Some | None; + + export interface None { readonly none: string; } + export interface Some { readonly some: a; } + + export const none : None = { none: '' }; + + export function isSome(value: Optional): value is Some { + return 'some' in value; + } + + function someFrom(some: a) { + return { some }; + } + + export function fn(makeSome: () => r): void { + let result: Optional = none; + result; // None + while (cond) { + ~~~~ +!!! error TS2454: Variable 'cond' is used before being assigned. + result; // Some | None + result = someFrom(isSome(result) ? result.some : makeSome()); + result; // Some + } + } + + function foo1() { + let x: string | number | boolean = 0; + x; // number + while (cond) { + ~~~~ +!!! error TS2454: Variable 'cond' is used before being assigned. + x; // number, then string | number + x = typeof x === "string" ? x.slice() : "abc"; + x; // string + } + x; + } + + function foo2() { + let x: string | number | boolean = 0; + x; // number + while (cond) { + ~~~~ +!!! error TS2454: Variable 'cond' is used before being assigned. + x; // number, then string | number + if (typeof x === "string") { + x = x.slice(); + } + else { + x = "abc"; + } + x; // string + } + x; + } + + // Type guards as assertions + + function f1() { + let x: string | number | undefined = undefined; + x; // undefined + if (x) { + x; // string | number (guard as assertion) + } + x; // string | number | undefined + } + + function f2() { + let x: string | number | undefined = undefined; + x; // undefined + if (typeof x === "string") { + x; // string (guard as assertion) + } + x; // string | undefined + } + + function f3() { + let x: string | number | undefined = undefined; + x; // undefined + if (!x) { + return; + } + x; // string | number (guard as assertion) + } + + function f4() { + let x: string | number | undefined = undefined; + x; // undefined + if (typeof x === "boolean") { + x; // nothing (boolean not in declared type) + } + x; // undefined + } + + function f5(x: string | number) { + if (typeof x === "string" && typeof x === "number") { + x; // number (guard as assertion) + } + else { + x; // string | number + } + x; // string | number + } + + function f6() { + let x: string | undefined | null; + x!.slice(); + x = ""; + x!.slice(); + x = undefined; + x!.slice(); + x = null; + x!.slice(); + x = undefined; + x!.slice(); + x = ""; + x!.slice(); + x = ""; + x!.slice(); + } + + function f7() { + let x: string; + x!.slice(); + } + \ No newline at end of file diff --git a/tests/baselines/reference/unusedLocalsInMethod4.errors.txt b/tests/baselines/reference/unusedLocalsInMethod4.errors.txt new file mode 100644 index 0000000000000..631245f86b71f --- /dev/null +++ b/tests/baselines/reference/unusedLocalsInMethod4.errors.txt @@ -0,0 +1,191 @@ +unusedLocalsInMethod4.ts(15,21): error TS2454: Variable 'x1' is used before being assigned. +unusedLocalsInMethod4.ts(16,21): error TS2454: Variable 'x2' is used before being assigned. +unusedLocalsInMethod4.ts(22,21): error TS2454: Variable 'x8' is used before being assigned. +unusedLocalsInMethod4.ts(23,21): error TS2454: Variable 'x9' is used before being assigned. +unusedLocalsInMethod4.ts(44,17): error TS2454: Variable 'x1' is used before being assigned. +unusedLocalsInMethod4.ts(45,17): error TS2454: Variable 'x2' is used before being assigned. +unusedLocalsInMethod4.ts(51,17): error TS2454: Variable 'x8' is used before being assigned. +unusedLocalsInMethod4.ts(52,17): error TS2454: Variable 'x9' is used before being assigned. +unusedLocalsInMethod4.ts(58,9): error TS2454: Variable 'x' is used before being assigned. +unusedLocalsInMethod4.ts(67,20): error TS2454: Variable 'x' is used before being assigned. +unusedLocalsInMethod4.ts(103,11): error TS1155: 'const' declarations must be initialized. +unusedLocalsInMethod4.ts(113,9): error TS2454: Variable 'i' is used before being assigned. +unusedLocalsInMethod4.ts(114,21): error TS2454: Variable 'i' is used before being assigned. +unusedLocalsInMethod4.ts(139,9): error TS2454: Variable 'enabledSubstitutions' is used before being assigned. +unusedLocalsInMethod4.ts(141,9): error TS2454: Variable 'enabledSubstitutions' is used before being assigned. + + +==== unusedLocalsInMethod4.ts (15 errors) ==== + function f() { + let x1: number[]; // should error + let x2: number[] | null; // should error + let x3: number[] | undefined; // should not error + let x4: number[] | undefined | null; // should not error + let x5!: number[]; // should not error + let x6: any; // should not error + let x7: unknown; // should not error + let x8: T; // should error + let x9: NonNull; // should error + var x10: NonNull; // should not error + let x11: NonNull; // should not error + + function foo() { + console.log(x1); + ~~ +!!! error TS2454: Variable 'x1' is used before being assigned. + console.log(x2); + ~~ +!!! error TS2454: Variable 'x2' is used before being assigned. + console.log(x3); + console.log(x4); + console.log(x5); + console.log(x6); + console.log(x7); + console.log(x8); + ~~ +!!! error TS2454: Variable 'x8' is used before being assigned. + console.log(x9); + ~~ +!!! error TS2454: Variable 'x9' is used before being assigned. + console.log(x10); + console.log(x11); + } + function bar() { + x11 = {} as any; + } + foo(); + } + + function f2() { + let x1: number[]; // should error + let x2: number[] | null; // should error + let x3: number[] | undefined; // should not error + let x4: number[] | undefined | null; // should not error + let x5!: number[]; // should not error + let x6: any; // should not error + let x7: unknown; // should not error + let x8: T; // should error + let x9: NonNull; // should error + + console.log(x1); + ~~ +!!! error TS2454: Variable 'x1' is used before being assigned. + console.log(x2); + ~~ +!!! error TS2454: Variable 'x2' is used before being assigned. + console.log(x3); + console.log(x4); + console.log(x5); + console.log(x6); + console.log(x7); + console.log(x8); + ~~ +!!! error TS2454: Variable 'x8' is used before being assigned. + console.log(x9); + ~~ +!!! error TS2454: Variable 'x9' is used before being assigned. + } + + function f3() { + let x: number[]; // should error + function foo() { + x.toString(); + ~ +!!! error TS2454: Variable 'x' is used before being assigned. + } + foo(); + } + + function f4() { + let x: number; // should error + return { + foo() { + return x.toString(); + ~ +!!! error TS2454: Variable 'x' is used before being assigned. + } + }; + } + + declare let x: number; // should not error + function f5() { + x.toString(); + } + export default {}; + + function f6() { + let key: string; // should not error + for (key in {}) { + console.log(key); + } + } + + function f7() { + let key: string; // should not error + for (key of []) { + console.log(key); + } + } + + function f8() { + function ff() { + let _; + let rest: {}; // should not error + + [_, ...rest] = bar(); + } + } + declare function bar(): [number, ...string[]]; + + function f9() { + const x: number; // should have only one error + ~ +!!! error TS1155: 'const' declarations must be initialized. + function bar() { + let y = x; + } + } + + + function rw() { + let i: number; // should error + function inside() { + i++; + ~ +!!! error TS2454: Variable 'i' is used before being assigned. + console.log(i); // NaN + ~ +!!! error TS2454: Variable 'i' is used before being assigned. + } + inside(); + } + rw(); + + function createBinder() { + var file: string; // should not error + + function bindSourceFile(f: string) { + file = f; + + file.toString(); + } + } + + function transformClassFields() { + enum ClassPropertySubstitutionFlags { + ClassAliases = 1 << 0, + ClassStaticThisOrSuperReference = 1 << 1, + } + + let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error + + function enableSubstitutionForClassAliases() { + enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2454: Variable 'enabledSubstitutions' is used before being assigned. + + enabledSubstitutions.toString(); + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2454: Variable 'enabledSubstitutions' is used before being assigned. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/unusedLocalsInMethod4.js b/tests/baselines/reference/unusedLocalsInMethod4.js new file mode 100644 index 0000000000000..d066e78908ec4 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsInMethod4.js @@ -0,0 +1,274 @@ +//// [tests/cases/compiler/unusedLocalsInMethod4.ts] //// + +//// [unusedLocalsInMethod4.ts] +function f() { + let x1: number[]; // should error + let x2: number[] | null; // should error + let x3: number[] | undefined; // should not error + let x4: number[] | undefined | null; // should not error + let x5!: number[]; // should not error + let x6: any; // should not error + let x7: unknown; // should not error + let x8: T; // should error + let x9: NonNull; // should error + var x10: NonNull; // should not error + let x11: NonNull; // should not error + + function foo() { + console.log(x1); + console.log(x2); + console.log(x3); + console.log(x4); + console.log(x5); + console.log(x6); + console.log(x7); + console.log(x8); + console.log(x9); + console.log(x10); + console.log(x11); + } + function bar() { + x11 = {} as any; + } + foo(); +} + +function f2() { + let x1: number[]; // should error + let x2: number[] | null; // should error + let x3: number[] | undefined; // should not error + let x4: number[] | undefined | null; // should not error + let x5!: number[]; // should not error + let x6: any; // should not error + let x7: unknown; // should not error + let x8: T; // should error + let x9: NonNull; // should error + + console.log(x1); + console.log(x2); + console.log(x3); + console.log(x4); + console.log(x5); + console.log(x6); + console.log(x7); + console.log(x8); + console.log(x9); +} + +function f3() { + let x: number[]; // should error + function foo() { + x.toString(); + } + foo(); +} + +function f4() { + let x: number; // should error + return { + foo() { + return x.toString(); + } + }; +} + +declare let x: number; // should not error +function f5() { + x.toString(); +} +export default {}; + +function f6() { + let key: string; // should not error + for (key in {}) { + console.log(key); + } +} + +function f7() { + let key: string; // should not error + for (key of []) { + console.log(key); + } +} + +function f8() { + function ff() { + let _; + let rest: {}; // should not error + + [_, ...rest] = bar(); + } +} +declare function bar(): [number, ...string[]]; + +function f9() { + const x: number; // should have only one error + function bar() { + let y = x; + } +} + + +function rw() { + let i: number; // should error + function inside() { + i++; + console.log(i); // NaN + } + inside(); +} +rw(); + +function createBinder() { + var file: string; // should not error + + function bindSourceFile(f: string) { + file = f; + + file.toString(); + } +} + +function transformClassFields() { + enum ClassPropertySubstitutionFlags { + ClassAliases = 1 << 0, + ClassStaticThisOrSuperReference = 1 << 1, + } + + let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error + + function enableSubstitutionForClassAliases() { + enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases; + + enabledSubstitutions.toString(); + } +} + +//// [unusedLocalsInMethod4.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function f() { + var x1; // should error + var x2; // should error + var x3; // should not error + var x4; // should not error + var x5; // should not error + var x6; // should not error + var x7; // should not error + var x8; // should error + var x9; // should error + var x10; // should not error + var x11; // should not error + function foo() { + console.log(x1); + console.log(x2); + console.log(x3); + console.log(x4); + console.log(x5); + console.log(x6); + console.log(x7); + console.log(x8); + console.log(x9); + console.log(x10); + console.log(x11); + } + function bar() { + x11 = {}; + } + foo(); +} +function f2() { + var x1; // should error + var x2; // should error + var x3; // should not error + var x4; // should not error + var x5; // should not error + var x6; // should not error + var x7; // should not error + var x8; // should error + var x9; // should error + console.log(x1); + console.log(x2); + console.log(x3); + console.log(x4); + console.log(x5); + console.log(x6); + console.log(x7); + console.log(x8); + console.log(x9); +} +function f3() { + var x; // should error + function foo() { + x.toString(); + } + foo(); +} +function f4() { + var x; // should error + return { + foo: function () { + return x.toString(); + } + }; +} +function f5() { + x.toString(); +} +exports.default = {}; +function f6() { + var key; // should not error + for (key in {}) { + console.log(key); + } +} +function f7() { + var key; // should not error + for (var _i = 0, _a = []; _i < _a.length; _i++) { + key = _a[_i]; + console.log(key); + } +} +function f8() { + function ff() { + var _a; + var _; + var rest; // should not error + _a = bar(), _ = _a[0], rest = _a.slice(1); + } +} +function f9() { + var x; // should have only one error + function bar() { + var y = x; + } +} +function rw() { + var i; // should error + function inside() { + i++; + console.log(i); // NaN + } + inside(); +} +rw(); +function createBinder() { + var file; // should not error + function bindSourceFile(f) { + file = f; + file.toString(); + } +} +function transformClassFields() { + var ClassPropertySubstitutionFlags; + (function (ClassPropertySubstitutionFlags) { + ClassPropertySubstitutionFlags[ClassPropertySubstitutionFlags["ClassAliases"] = 1] = "ClassAliases"; + ClassPropertySubstitutionFlags[ClassPropertySubstitutionFlags["ClassStaticThisOrSuperReference"] = 2] = "ClassStaticThisOrSuperReference"; + })(ClassPropertySubstitutionFlags || (ClassPropertySubstitutionFlags = {})); + var enabledSubstitutions; // should error + function enableSubstitutionForClassAliases() { + enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases; + enabledSubstitutions.toString(); + } +} diff --git a/tests/baselines/reference/unusedLocalsInMethod4.symbols b/tests/baselines/reference/unusedLocalsInMethod4.symbols new file mode 100644 index 0000000000000..0d9aae9987410 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsInMethod4.symbols @@ -0,0 +1,410 @@ +//// [tests/cases/compiler/unusedLocalsInMethod4.ts] //// + +=== unusedLocalsInMethod4.ts === +function f() { +>f : Symbol(f, Decl(unusedLocalsInMethod4.ts, 0, 0)) +>T : Symbol(T, Decl(unusedLocalsInMethod4.ts, 0, 11)) +>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 0, 13)) + + let x1: number[]; // should error +>x1 : Symbol(x1, Decl(unusedLocalsInMethod4.ts, 1, 7)) + + let x2: number[] | null; // should error +>x2 : Symbol(x2, Decl(unusedLocalsInMethod4.ts, 2, 7)) + + let x3: number[] | undefined; // should not error +>x3 : Symbol(x3, Decl(unusedLocalsInMethod4.ts, 3, 7)) + + let x4: number[] | undefined | null; // should not error +>x4 : Symbol(x4, Decl(unusedLocalsInMethod4.ts, 4, 7)) + + let x5!: number[]; // should not error +>x5 : Symbol(x5, Decl(unusedLocalsInMethod4.ts, 5, 7)) + + let x6: any; // should not error +>x6 : Symbol(x6, Decl(unusedLocalsInMethod4.ts, 6, 7)) + + let x7: unknown; // should not error +>x7 : Symbol(x7, Decl(unusedLocalsInMethod4.ts, 7, 7)) + + let x8: T; // should error +>x8 : Symbol(x8, Decl(unusedLocalsInMethod4.ts, 8, 7)) +>T : Symbol(T, Decl(unusedLocalsInMethod4.ts, 0, 11)) + + let x9: NonNull; // should error +>x9 : Symbol(x9, Decl(unusedLocalsInMethod4.ts, 9, 7)) +>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 0, 13)) + + var x10: NonNull; // should not error +>x10 : Symbol(x10, Decl(unusedLocalsInMethod4.ts, 10, 7)) +>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 0, 13)) + + let x11: NonNull; // should not error +>x11 : Symbol(x11, Decl(unusedLocalsInMethod4.ts, 11, 7)) +>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 0, 13)) + + function foo() { +>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 11, 21)) + + console.log(x1); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x1 : Symbol(x1, Decl(unusedLocalsInMethod4.ts, 1, 7)) + + console.log(x2); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x2 : Symbol(x2, Decl(unusedLocalsInMethod4.ts, 2, 7)) + + console.log(x3); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x3 : Symbol(x3, Decl(unusedLocalsInMethod4.ts, 3, 7)) + + console.log(x4); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x4 : Symbol(x4, Decl(unusedLocalsInMethod4.ts, 4, 7)) + + console.log(x5); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x5 : Symbol(x5, Decl(unusedLocalsInMethod4.ts, 5, 7)) + + console.log(x6); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x6 : Symbol(x6, Decl(unusedLocalsInMethod4.ts, 6, 7)) + + console.log(x7); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x7 : Symbol(x7, Decl(unusedLocalsInMethod4.ts, 7, 7)) + + console.log(x8); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x8 : Symbol(x8, Decl(unusedLocalsInMethod4.ts, 8, 7)) + + console.log(x9); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x9 : Symbol(x9, Decl(unusedLocalsInMethod4.ts, 9, 7)) + + console.log(x10); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x10 : Symbol(x10, Decl(unusedLocalsInMethod4.ts, 10, 7)) + + console.log(x11); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x11 : Symbol(x11, Decl(unusedLocalsInMethod4.ts, 11, 7)) + } + function bar() { +>bar : Symbol(bar, Decl(unusedLocalsInMethod4.ts, 25, 5)) + + x11 = {} as any; +>x11 : Symbol(x11, Decl(unusedLocalsInMethod4.ts, 11, 7)) + } + foo(); +>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 11, 21)) +} + +function f2() { +>f2 : Symbol(f2, Decl(unusedLocalsInMethod4.ts, 30, 1)) +>T : Symbol(T, Decl(unusedLocalsInMethod4.ts, 32, 12)) +>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 32, 14)) + + let x1: number[]; // should error +>x1 : Symbol(x1, Decl(unusedLocalsInMethod4.ts, 33, 7)) + + let x2: number[] | null; // should error +>x2 : Symbol(x2, Decl(unusedLocalsInMethod4.ts, 34, 7)) + + let x3: number[] | undefined; // should not error +>x3 : Symbol(x3, Decl(unusedLocalsInMethod4.ts, 35, 7)) + + let x4: number[] | undefined | null; // should not error +>x4 : Symbol(x4, Decl(unusedLocalsInMethod4.ts, 36, 7)) + + let x5!: number[]; // should not error +>x5 : Symbol(x5, Decl(unusedLocalsInMethod4.ts, 37, 7)) + + let x6: any; // should not error +>x6 : Symbol(x6, Decl(unusedLocalsInMethod4.ts, 38, 7)) + + let x7: unknown; // should not error +>x7 : Symbol(x7, Decl(unusedLocalsInMethod4.ts, 39, 7)) + + let x8: T; // should error +>x8 : Symbol(x8, Decl(unusedLocalsInMethod4.ts, 40, 7)) +>T : Symbol(T, Decl(unusedLocalsInMethod4.ts, 32, 12)) + + let x9: NonNull; // should error +>x9 : Symbol(x9, Decl(unusedLocalsInMethod4.ts, 41, 7)) +>NonNull : Symbol(NonNull, Decl(unusedLocalsInMethod4.ts, 32, 14)) + + console.log(x1); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x1 : Symbol(x1, Decl(unusedLocalsInMethod4.ts, 33, 7)) + + console.log(x2); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x2 : Symbol(x2, Decl(unusedLocalsInMethod4.ts, 34, 7)) + + console.log(x3); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x3 : Symbol(x3, Decl(unusedLocalsInMethod4.ts, 35, 7)) + + console.log(x4); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x4 : Symbol(x4, Decl(unusedLocalsInMethod4.ts, 36, 7)) + + console.log(x5); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x5 : Symbol(x5, Decl(unusedLocalsInMethod4.ts, 37, 7)) + + console.log(x6); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x6 : Symbol(x6, Decl(unusedLocalsInMethod4.ts, 38, 7)) + + console.log(x7); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x7 : Symbol(x7, Decl(unusedLocalsInMethod4.ts, 39, 7)) + + console.log(x8); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x8 : Symbol(x8, Decl(unusedLocalsInMethod4.ts, 40, 7)) + + console.log(x9); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>x9 : Symbol(x9, Decl(unusedLocalsInMethod4.ts, 41, 7)) +} + +function f3() { +>f3 : Symbol(f3, Decl(unusedLocalsInMethod4.ts, 52, 1)) + + let x: number[]; // should error +>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 55, 7)) + + function foo() { +>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 55, 20)) + + x.toString(); +>x.toString : Symbol(Array.toString, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 55, 7)) +>toString : Symbol(Array.toString, Decl(lib.es5.d.ts, --, --)) + } + foo(); +>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 55, 20)) +} + +function f4() { +>f4 : Symbol(f4, Decl(unusedLocalsInMethod4.ts, 60, 1)) + + let x: number; // should error +>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 63, 7)) + + return { + foo() { +>foo : Symbol(foo, Decl(unusedLocalsInMethod4.ts, 64, 12)) + + return x.toString(); +>x.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 63, 7)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + } + }; +} + +declare let x: number; // should not error +>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 71, 11)) + +function f5() { +>f5 : Symbol(f5, Decl(unusedLocalsInMethod4.ts, 71, 22)) + + x.toString(); +>x.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 71, 11)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +} +export default {}; + +function f6() { +>f6 : Symbol(f6, Decl(unusedLocalsInMethod4.ts, 75, 18)) + + let key: string; // should not error +>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 78, 7)) + + for (key in {}) { +>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 78, 7)) + + console.log(key); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 78, 7)) + } +} + +function f7() { +>f7 : Symbol(f7, Decl(unusedLocalsInMethod4.ts, 82, 1)) + + let key: string; // should not error +>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 85, 7)) + + for (key of []) { +>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 85, 7)) + + console.log(key); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>key : Symbol(key, Decl(unusedLocalsInMethod4.ts, 85, 7)) + } +} + +function f8() { +>f8 : Symbol(f8, Decl(unusedLocalsInMethod4.ts, 89, 1)) + + function ff() { +>ff : Symbol(ff, Decl(unusedLocalsInMethod4.ts, 91, 15)) + + let _; +>_ : Symbol(_, Decl(unusedLocalsInMethod4.ts, 93, 11)) + + let rest: {}; // should not error +>rest : Symbol(rest, Decl(unusedLocalsInMethod4.ts, 94, 11)) + + [_, ...rest] = bar(); +>_ : Symbol(_, Decl(unusedLocalsInMethod4.ts, 93, 11)) +>rest : Symbol(rest, Decl(unusedLocalsInMethod4.ts, 94, 11)) +>bar : Symbol(bar, Decl(unusedLocalsInMethod4.ts, 98, 1)) + } +} +declare function bar(): [number, ...string[]]; +>bar : Symbol(bar, Decl(unusedLocalsInMethod4.ts, 98, 1)) + +function f9() { +>f9 : Symbol(f9, Decl(unusedLocalsInMethod4.ts, 99, 46)) + + const x: number; // should have only one error +>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 102, 9)) + + function bar() { +>bar : Symbol(bar, Decl(unusedLocalsInMethod4.ts, 102, 20)) + + let y = x; +>y : Symbol(y, Decl(unusedLocalsInMethod4.ts, 104, 11)) +>x : Symbol(x, Decl(unusedLocalsInMethod4.ts, 102, 9)) + } +} + + +function rw() { +>rw : Symbol(rw, Decl(unusedLocalsInMethod4.ts, 106, 1)) + + let i: number; // should error +>i : Symbol(i, Decl(unusedLocalsInMethod4.ts, 110, 7)) + + function inside() { +>inside : Symbol(inside, Decl(unusedLocalsInMethod4.ts, 110, 18)) + + i++; +>i : Symbol(i, Decl(unusedLocalsInMethod4.ts, 110, 7)) + + console.log(i); // NaN +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>i : Symbol(i, Decl(unusedLocalsInMethod4.ts, 110, 7)) + } + inside(); +>inside : Symbol(inside, Decl(unusedLocalsInMethod4.ts, 110, 18)) +} +rw(); +>rw : Symbol(rw, Decl(unusedLocalsInMethod4.ts, 106, 1)) + +function createBinder() { +>createBinder : Symbol(createBinder, Decl(unusedLocalsInMethod4.ts, 117, 5)) + + var file: string; // should not error +>file : Symbol(file, Decl(unusedLocalsInMethod4.ts, 120, 7)) + + function bindSourceFile(f: string) { +>bindSourceFile : Symbol(bindSourceFile, Decl(unusedLocalsInMethod4.ts, 120, 21)) +>f : Symbol(f, Decl(unusedLocalsInMethod4.ts, 122, 28)) + + file = f; +>file : Symbol(file, Decl(unusedLocalsInMethod4.ts, 120, 7)) +>f : Symbol(f, Decl(unusedLocalsInMethod4.ts, 122, 28)) + + file.toString(); +>file.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) +>file : Symbol(file, Decl(unusedLocalsInMethod4.ts, 120, 7)) +>toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) + } +} + +function transformClassFields() { +>transformClassFields : Symbol(transformClassFields, Decl(unusedLocalsInMethod4.ts, 127, 1)) + + enum ClassPropertySubstitutionFlags { +>ClassPropertySubstitutionFlags : Symbol(ClassPropertySubstitutionFlags, Decl(unusedLocalsInMethod4.ts, 129, 33)) + + ClassAliases = 1 << 0, +>ClassAliases : Symbol(ClassPropertySubstitutionFlags.ClassAliases, Decl(unusedLocalsInMethod4.ts, 130, 41)) + + ClassStaticThisOrSuperReference = 1 << 1, +>ClassStaticThisOrSuperReference : Symbol(ClassPropertySubstitutionFlags.ClassStaticThisOrSuperReference, Decl(unusedLocalsInMethod4.ts, 131, 30)) + } + + let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error +>enabledSubstitutions : Symbol(enabledSubstitutions, Decl(unusedLocalsInMethod4.ts, 135, 7)) +>ClassPropertySubstitutionFlags : Symbol(ClassPropertySubstitutionFlags, Decl(unusedLocalsInMethod4.ts, 129, 33)) + + function enableSubstitutionForClassAliases() { +>enableSubstitutionForClassAliases : Symbol(enableSubstitutionForClassAliases, Decl(unusedLocalsInMethod4.ts, 135, 61)) + + enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases; +>enabledSubstitutions : Symbol(enabledSubstitutions, Decl(unusedLocalsInMethod4.ts, 135, 7)) +>ClassPropertySubstitutionFlags.ClassAliases : Symbol(ClassPropertySubstitutionFlags.ClassAliases, Decl(unusedLocalsInMethod4.ts, 130, 41)) +>ClassPropertySubstitutionFlags : Symbol(ClassPropertySubstitutionFlags, Decl(unusedLocalsInMethod4.ts, 129, 33)) +>ClassAliases : Symbol(ClassPropertySubstitutionFlags.ClassAliases, Decl(unusedLocalsInMethod4.ts, 130, 41)) + + enabledSubstitutions.toString(); +>enabledSubstitutions.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>enabledSubstitutions : Symbol(enabledSubstitutions, Decl(unusedLocalsInMethod4.ts, 135, 7)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + } +} diff --git a/tests/baselines/reference/unusedLocalsInMethod4.types b/tests/baselines/reference/unusedLocalsInMethod4.types new file mode 100644 index 0000000000000..b684bd318d203 --- /dev/null +++ b/tests/baselines/reference/unusedLocalsInMethod4.types @@ -0,0 +1,687 @@ +//// [tests/cases/compiler/unusedLocalsInMethod4.ts] //// + +=== unusedLocalsInMethod4.ts === +function f() { +>f : () => void +> : ^ ^^ ^^^^^^^^^ ^^^^^^^^^^^ + + let x1: number[]; // should error +>x1 : number[] +> : ^^^^^^^^ + + let x2: number[] | null; // should error +>x2 : number[] | null +> : ^^^^^^^^^^^^^^^ + + let x3: number[] | undefined; // should not error +>x3 : number[] | undefined +> : ^^^^^^^^^^^^^^^^^^^^ + + let x4: number[] | undefined | null; // should not error +>x4 : number[] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + let x5!: number[]; // should not error +>x5 : number[] +> : ^^^^^^^^ + + let x6: any; // should not error +>x6 : any +> : ^^^ + + let x7: unknown; // should not error +>x7 : unknown +> : ^^^^^^^ + + let x8: T; // should error +>x8 : T +> : ^ + + let x9: NonNull; // should error +>x9 : NonNull +> : ^^^^^^^ + + var x10: NonNull; // should not error +>x10 : NonNull +> : ^^^^^^^ + + let x11: NonNull; // should not error +>x11 : NonNull +> : ^^^^^^^ + + function foo() { +>foo : () => void +> : ^^^^^^^^^^ + + console.log(x1); +>console.log(x1) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x1 : number[] +> : ^^^^^^^^ + + console.log(x2); +>console.log(x2) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x2 : number[] | null +> : ^^^^^^^^^^^^^^^ + + console.log(x3); +>console.log(x3) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x3 : number[] | undefined +> : ^^^^^^^^^^^^^^^^^^^^ + + console.log(x4); +>console.log(x4) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x4 : number[] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + console.log(x5); +>console.log(x5) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x5 : number[] +> : ^^^^^^^^ + + console.log(x6); +>console.log(x6) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x6 : any +> : ^^^ + + console.log(x7); +>console.log(x7) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x7 : unknown +> : ^^^^^^^ + + console.log(x8); +>console.log(x8) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x8 : T +> : ^ + + console.log(x9); +>console.log(x9) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x9 : NonNull +> : ^^^^^^^ + + console.log(x10); +>console.log(x10) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x10 : NonNull +> : ^^^^^^^ + + console.log(x11); +>console.log(x11) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x11 : NonNull +> : ^^^^^^^ + } + function bar() { +>bar : () => void +> : ^^^^^^^^^^ + + x11 = {} as any; +>x11 = {} as any : any +> : ^^^ +>x11 : NonNull +> : ^^^^^^^ +>{} as any : any +> : ^^^ +>{} : {} +> : ^^ + } + foo(); +>foo() : void +> : ^^^^ +>foo : () => void +> : ^^^^^^^^^^ +} + +function f2() { +>f2 : () => void +> : ^ ^^ ^^^^^^^^^ ^^^^^^^^^^^ + + let x1: number[]; // should error +>x1 : number[] +> : ^^^^^^^^ + + let x2: number[] | null; // should error +>x2 : number[] | null +> : ^^^^^^^^^^^^^^^ + + let x3: number[] | undefined; // should not error +>x3 : number[] | undefined +> : ^^^^^^^^^^^^^^^^^^^^ + + let x4: number[] | undefined | null; // should not error +>x4 : number[] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + let x5!: number[]; // should not error +>x5 : number[] +> : ^^^^^^^^ + + let x6: any; // should not error +>x6 : any +> : ^^^ + + let x7: unknown; // should not error +>x7 : unknown +> : ^^^^^^^ + + let x8: T; // should error +>x8 : T +> : ^ + + let x9: NonNull; // should error +>x9 : NonNull +> : ^^^^^^^ + + console.log(x1); +>console.log(x1) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x1 : number[] +> : ^^^^^^^^ + + console.log(x2); +>console.log(x2) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x2 : number[] | null +> : ^^^^^^^^^^^^^^^ + + console.log(x3); +>console.log(x3) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x3 : number[] | undefined +> : ^^^^^^^^^^^^^^^^^^^^ + + console.log(x4); +>console.log(x4) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x4 : number[] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + console.log(x5); +>console.log(x5) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x5 : number[] +> : ^^^^^^^^ + + console.log(x6); +>console.log(x6) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x6 : any +> : ^^^ + + console.log(x7); +>console.log(x7) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x7 : unknown +> : ^^^^^^^ + + console.log(x8); +>console.log(x8) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x8 : T +> : ^ + + console.log(x9); +>console.log(x9) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>x9 : NonNull +> : ^^^^^^^ +} + +function f3() { +>f3 : () => void +> : ^^^^^^^^^^ + + let x: number[]; // should error +>x : number[] +> : ^^^^^^^^ + + function foo() { +>foo : () => void +> : ^^^^^^^^^^ + + x.toString(); +>x.toString() : string +> : ^^^^^^ +>x.toString : () => string +> : ^^^^^^ +>x : number[] +> : ^^^^^^^^ +>toString : () => string +> : ^^^^^^ + } + foo(); +>foo() : void +> : ^^^^ +>foo : () => void +> : ^^^^^^^^^^ +} + +function f4() { +>f4 : () => { foo(): string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + + let x: number; // should error +>x : number +> : ^^^^^^ + + return { +>{ foo() { return x.toString(); } } : { foo(): string; } +> : ^^^^^^^^^^^^^^^^^^ + + foo() { +>foo : () => string +> : ^^^^^^^^^^^^ + + return x.toString(); +>x.toString() : string +> : ^^^^^^ +>x.toString : (radix?: number) => string +> : ^ ^^^ ^^^^^ +>x : number +> : ^^^^^^ +>toString : (radix?: number) => string +> : ^ ^^^ ^^^^^ + } + }; +} + +declare let x: number; // should not error +>x : number +> : ^^^^^^ + +function f5() { +>f5 : () => void +> : ^^^^^^^^^^ + + x.toString(); +>x.toString() : string +> : ^^^^^^ +>x.toString : (radix?: number) => string +> : ^ ^^^ ^^^^^ +>x : number +> : ^^^^^^ +>toString : (radix?: number) => string +> : ^ ^^^ ^^^^^ +} +export default {}; +>{} : {} +> : ^^ + +function f6() { +>f6 : () => void +> : ^^^^^^^^^^ + + let key: string; // should not error +>key : string +> : ^^^^^^ + + for (key in {}) { +>key : string +> : ^^^^^^ +>{} : {} +> : ^^ + + console.log(key); +>console.log(key) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>key : string +> : ^^^^^^ + } +} + +function f7() { +>f7 : () => void +> : ^^^^^^^^^^ + + let key: string; // should not error +>key : string +> : ^^^^^^ + + for (key of []) { +>key : string +> : ^^^^^^ +>[] : never[] +> : ^^^^^^^ + + console.log(key); +>console.log(key) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>key : string +> : ^^^^^^ + } +} + +function f8() { +>f8 : () => void +> : ^^^^^^^^^^ + + function ff() { +>ff : () => void +> : ^^^^^^^^^^ + + let _; +>_ : any +> : ^^^ + + let rest: {}; // should not error +>rest : {} +> : ^^ + + [_, ...rest] = bar(); +>[_, ...rest] = bar() : [number, ...string[]] +> : ^^^^^^^^^^^^^^^^^^^^^ +>[_, ...rest] : [any, ...unknown[]] +> : ^^^^^^^^^^^^^^^^^^^ +>_ : any +> : ^^^ +>...rest : any +> : ^^^ +>rest : {} +> : ^^ +>bar() : [number, ...string[]] +> : ^^^^^^^^^^^^^^^^^^^^^ +>bar : () => [number, ...string[]] +> : ^^^^^^ + } +} +declare function bar(): [number, ...string[]]; +>bar : () => [number, ...string[]] +> : ^^^^^^ + +function f9() { +>f9 : () => void +> : ^^^^^^^^^^ + + const x: number; // should have only one error +>x : number +> : ^^^^^^ + + function bar() { +>bar : () => void +> : ^^^^^^^^^^ + + let y = x; +>y : number +> : ^^^^^^ +>x : number +> : ^^^^^^ + } +} + + +function rw() { +>rw : () => void +> : ^^^^^^^^^^ + + let i: number; // should error +>i : number +> : ^^^^^^ + + function inside() { +>inside : () => void +> : ^^^^^^^^^^ + + i++; +>i++ : number +> : ^^^^^^ +>i : number +> : ^^^^^^ + + console.log(i); // NaN +>console.log(i) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>i : number +> : ^^^^^^ + } + inside(); +>inside() : void +> : ^^^^ +>inside : () => void +> : ^^^^^^^^^^ +} +rw(); +>rw() : void +> : ^^^^ +>rw : () => void +> : ^^^^^^^^^^ + +function createBinder() { +>createBinder : () => void +> : ^^^^^^^^^^ + + var file: string; // should not error +>file : string +> : ^^^^^^ + + function bindSourceFile(f: string) { +>bindSourceFile : (f: string) => void +> : ^ ^^ ^^^^^^^^^ +>f : string +> : ^^^^^^ + + file = f; +>file = f : string +> : ^^^^^^ +>file : string +> : ^^^^^^ +>f : string +> : ^^^^^^ + + file.toString(); +>file.toString() : string +> : ^^^^^^ +>file.toString : () => string +> : ^^^^^^ +>file : string +> : ^^^^^^ +>toString : () => string +> : ^^^^^^ + } +} + +function transformClassFields() { +>transformClassFields : () => void +> : ^^^^^^^^^^ + + enum ClassPropertySubstitutionFlags { +>ClassPropertySubstitutionFlags : ClassPropertySubstitutionFlags +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ClassAliases = 1 << 0, +>ClassAliases : ClassPropertySubstitutionFlags.ClassAliases +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 << 0 : number +> : ^^^^^^ +>1 : 1 +> : ^ +>0 : 0 +> : ^ + + ClassStaticThisOrSuperReference = 1 << 1, +>ClassStaticThisOrSuperReference : ClassPropertySubstitutionFlags.ClassStaticThisOrSuperReference +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 << 1 : number +> : ^^^^^^ +>1 : 1 +> : ^ +>1 : 1 +> : ^ + } + + let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error +>enabledSubstitutions : ClassPropertySubstitutionFlags +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + function enableSubstitutionForClassAliases() { +>enableSubstitutionForClassAliases : () => void +> : ^^^^^^^^^^ + + enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases; +>enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases : number +> : ^^^^^^ +>enabledSubstitutions : ClassPropertySubstitutionFlags +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ClassPropertySubstitutionFlags.ClassAliases : ClassPropertySubstitutionFlags.ClassAliases +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ClassPropertySubstitutionFlags : typeof ClassPropertySubstitutionFlags +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>ClassAliases : ClassPropertySubstitutionFlags.ClassAliases +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + enabledSubstitutions.toString(); +>enabledSubstitutions.toString() : string +> : ^^^^^^ +>enabledSubstitutions.toString : (radix?: number) => string +> : ^ ^^^ ^^^^^ +>enabledSubstitutions : ClassPropertySubstitutionFlags +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>toString : (radix?: number) => string +> : ^ ^^^ ^^^^^ + } +} diff --git a/tests/cases/compiler/narrowingPastLastAssignment.ts b/tests/cases/compiler/narrowingPastLastAssignment.ts index ae66ab03db719..26d898f168897 100644 --- a/tests/cases/compiler/narrowingPastLastAssignment.ts +++ b/tests/cases/compiler/narrowingPastLastAssignment.ts @@ -155,3 +155,13 @@ function f12() { } values.forEach(v => foo.push(v)); } + +function f13() { + // Test for captured 'var' declaration (as opposed to parameters, let, const). + var foo: string | undefined; + foo = ''; + + return () => { + foo.toLocaleLowerCase(); + } +} \ No newline at end of file diff --git a/tests/cases/compiler/unusedLocalsInMethod4.ts b/tests/cases/compiler/unusedLocalsInMethod4.ts new file mode 100644 index 0000000000000..973f68994ae7b --- /dev/null +++ b/tests/cases/compiler/unusedLocalsInMethod4.ts @@ -0,0 +1,145 @@ +// @strict: true + +function f() { + let x1: number[]; // should error + let x2: number[] | null; // should error + let x3: number[] | undefined; // should not error + let x4: number[] | undefined | null; // should not error + let x5!: number[]; // should not error + let x6: any; // should not error + let x7: unknown; // should not error + let x8: T; // should error + let x9: NonNull; // should error + var x10: NonNull; // should not error + let x11: NonNull; // should not error + + function foo() { + console.log(x1); + console.log(x2); + console.log(x3); + console.log(x4); + console.log(x5); + console.log(x6); + console.log(x7); + console.log(x8); + console.log(x9); + console.log(x10); + console.log(x11); + } + function bar() { + x11 = {} as any; + } + foo(); +} + +function f2() { + let x1: number[]; // should error + let x2: number[] | null; // should error + let x3: number[] | undefined; // should not error + let x4: number[] | undefined | null; // should not error + let x5!: number[]; // should not error + let x6: any; // should not error + let x7: unknown; // should not error + let x8: T; // should error + let x9: NonNull; // should error + + console.log(x1); + console.log(x2); + console.log(x3); + console.log(x4); + console.log(x5); + console.log(x6); + console.log(x7); + console.log(x8); + console.log(x9); +} + +function f3() { + let x: number[]; // should error + function foo() { + x.toString(); + } + foo(); +} + +function f4() { + let x: number; // should error + return { + foo() { + return x.toString(); + } + }; +} + +declare let x: number; // should not error +function f5() { + x.toString(); +} +export default {}; + +function f6() { + let key: string; // should not error + for (key in {}) { + console.log(key); + } +} + +function f7() { + let key: string; // should not error + for (key of []) { + console.log(key); + } +} + +function f8() { + function ff() { + let _; + let rest: {}; // should not error + + [_, ...rest] = bar(); + } +} +declare function bar(): [number, ...string[]]; + +function f9() { + const x: number; // should have only one error + function bar() { + let y = x; + } +} + + +function rw() { + let i: number; // should error + function inside() { + i++; + console.log(i); // NaN + } + inside(); +} +rw(); + +function createBinder() { + var file: string; // should not error + + function bindSourceFile(f: string) { + file = f; + + file.toString(); + } +} + +function transformClassFields() { + enum ClassPropertySubstitutionFlags { + ClassAliases = 1 << 0, + ClassStaticThisOrSuperReference = 1 << 1, + } + + let enabledSubstitutions: ClassPropertySubstitutionFlags; // should error + + function enableSubstitutionForClassAliases() { + enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassAliases; + + enabledSubstitutions.toString(); + } +} \ No newline at end of file