Elide import namespace from which only const enums are used (#20320)
This commit is contained in:
parent
78250ec58f
commit
a625dec58a
5 changed files with 144 additions and 0 deletions
|
@ -15581,6 +15581,8 @@ namespace ts {
|
|||
|
||||
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
|
||||
let propType: Type;
|
||||
let leftSymbol = getNodeLinks(left) && getNodeLinks(left).resolvedSymbol;
|
||||
const leftWasReferenced = leftSymbol && getSymbolLinks(leftSymbol).referenced;
|
||||
const leftType = checkNonNullExpression(left);
|
||||
const apparentType = getApparentType(getWidenedType(leftType));
|
||||
if (isTypeAny(apparentType) || apparentType === silentNeverType) {
|
||||
|
@ -15604,6 +15606,13 @@ namespace ts {
|
|||
else {
|
||||
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
|
||||
markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword);
|
||||
// Reset the referenced-ness of the LHS expression if this access refers to a const enum or const enum only module
|
||||
leftSymbol = getNodeLinks(left) && getNodeLinks(left).resolvedSymbol;
|
||||
if (leftSymbol && !leftWasReferenced && getSymbolLinks(leftSymbol).referenced &&
|
||||
!(isNonLocalAlias(leftSymbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(prop))
|
||||
) {
|
||||
getSymbolLinks(leftSymbol).referenced = undefined;
|
||||
}
|
||||
getNodeLinks(node).resolvedSymbol = prop;
|
||||
checkPropertyAccessibility(node, left, apparentType, prop);
|
||||
if (assignmentKind) {
|
||||
|
@ -24691,6 +24700,11 @@ namespace ts {
|
|||
if (symbol && getSymbolLinks(symbol).referenced) {
|
||||
return true;
|
||||
}
|
||||
const target = getSymbolLinks(symbol).target;
|
||||
if (target && getModifierFlags(node) & ModifierFlags.Export && target.flags & SymbolFlags.Value) {
|
||||
// An `export import ... =` of a value symbol is always considered referenced
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkChildren) {
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
//// [tests/cases/compiler/constEnumNamespaceReferenceCausesNoImport.ts] ////
|
||||
|
||||
//// [foo.ts]
|
||||
export const enum ConstFooEnum {
|
||||
Some,
|
||||
Values,
|
||||
Here
|
||||
};
|
||||
export function fooFunc(): void { /* removed */ }
|
||||
//// [index.ts]
|
||||
import * as Foo from "./foo";
|
||||
|
||||
function check(x: Foo.ConstFooEnum): void {
|
||||
switch (x) {
|
||||
case Foo.ConstFooEnum.Some:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//// [foo.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
;
|
||||
function fooFunc() { }
|
||||
exports.fooFunc = fooFunc;
|
||||
//// [index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
function check(x) {
|
||||
switch (x) {
|
||||
case 0 /* Some */:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
=== tests/cases/compiler/foo.ts ===
|
||||
export const enum ConstFooEnum {
|
||||
>ConstFooEnum : Symbol(ConstFooEnum, Decl(foo.ts, 0, 0))
|
||||
|
||||
Some,
|
||||
>Some : Symbol(ConstFooEnum.Some, Decl(foo.ts, 0, 32))
|
||||
|
||||
Values,
|
||||
>Values : Symbol(ConstFooEnum.Values, Decl(foo.ts, 1, 9))
|
||||
|
||||
Here
|
||||
>Here : Symbol(ConstFooEnum.Here, Decl(foo.ts, 2, 11))
|
||||
|
||||
};
|
||||
export function fooFunc(): void { /* removed */ }
|
||||
>fooFunc : Symbol(fooFunc, Decl(foo.ts, 4, 2))
|
||||
|
||||
=== tests/cases/compiler/index.ts ===
|
||||
import * as Foo from "./foo";
|
||||
>Foo : Symbol(Foo, Decl(index.ts, 0, 6))
|
||||
|
||||
function check(x: Foo.ConstFooEnum): void {
|
||||
>check : Symbol(check, Decl(index.ts, 0, 29))
|
||||
>x : Symbol(x, Decl(index.ts, 2, 15))
|
||||
>Foo : Symbol(Foo, Decl(index.ts, 0, 6))
|
||||
>ConstFooEnum : Symbol(Foo.ConstFooEnum, Decl(foo.ts, 0, 0))
|
||||
|
||||
switch (x) {
|
||||
>x : Symbol(x, Decl(index.ts, 2, 15))
|
||||
|
||||
case Foo.ConstFooEnum.Some:
|
||||
>Foo.ConstFooEnum.Some : Symbol(Foo.ConstFooEnum.Some, Decl(foo.ts, 0, 32))
|
||||
>Foo.ConstFooEnum : Symbol(Foo.ConstFooEnum, Decl(foo.ts, 0, 0))
|
||||
>Foo : Symbol(Foo, Decl(index.ts, 0, 6))
|
||||
>ConstFooEnum : Symbol(Foo.ConstFooEnum, Decl(foo.ts, 0, 0))
|
||||
>Some : Symbol(Foo.ConstFooEnum.Some, Decl(foo.ts, 0, 32))
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
=== tests/cases/compiler/foo.ts ===
|
||||
export const enum ConstFooEnum {
|
||||
>ConstFooEnum : ConstFooEnum
|
||||
|
||||
Some,
|
||||
>Some : ConstFooEnum.Some
|
||||
|
||||
Values,
|
||||
>Values : ConstFooEnum.Values
|
||||
|
||||
Here
|
||||
>Here : ConstFooEnum.Here
|
||||
|
||||
};
|
||||
export function fooFunc(): void { /* removed */ }
|
||||
>fooFunc : () => void
|
||||
|
||||
=== tests/cases/compiler/index.ts ===
|
||||
import * as Foo from "./foo";
|
||||
>Foo : typeof Foo
|
||||
|
||||
function check(x: Foo.ConstFooEnum): void {
|
||||
>check : (x: Foo.ConstFooEnum) => void
|
||||
>x : Foo.ConstFooEnum
|
||||
>Foo : any
|
||||
>ConstFooEnum : Foo.ConstFooEnum
|
||||
|
||||
switch (x) {
|
||||
>x : Foo.ConstFooEnum
|
||||
|
||||
case Foo.ConstFooEnum.Some:
|
||||
>Foo.ConstFooEnum.Some : Foo.ConstFooEnum.Some
|
||||
>Foo.ConstFooEnum : typeof Foo.ConstFooEnum
|
||||
>Foo : typeof Foo
|
||||
>ConstFooEnum : typeof Foo.ConstFooEnum
|
||||
>Some : Foo.ConstFooEnum.Some
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// @filename: foo.ts
|
||||
export const enum ConstFooEnum {
|
||||
Some,
|
||||
Values,
|
||||
Here
|
||||
};
|
||||
export function fooFunc(): void { /* removed */ }
|
||||
// @filename: index.ts
|
||||
import * as Foo from "./foo";
|
||||
|
||||
function check(x: Foo.ConstFooEnum): void {
|
||||
switch (x) {
|
||||
case Foo.ConstFooEnum.Some:
|
||||
break;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue