Skip to content

Commit 895b5c9

Browse files
dragomirtitianjakebailey
authored andcommitted
Perform usage analysis on refenced binding aliases in function signatures. (microsoft#55683)
Co-authored-by: Jake Bailey <[email protected]>
1 parent 81b4d82 commit 895b5c9

8 files changed

+1509
-53
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6200,12 +6200,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
62006200

62016201
function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult | undefined {
62026202
let aliasesToMakeVisible: LateVisibilityPaintedStatement[] | undefined;
6203+
let bindingElementToMakeVisible: BindingElement | undefined;
62036204
if (!every(filter(symbol.declarations, d => d.kind !== SyntaxKind.Identifier), getIsDeclarationVisible)) {
62046205
return undefined;
62056206
}
6206-
return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible };
6207+
return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible, bindingElementToMakeVisible };
62076208

62086209
function getIsDeclarationVisible(declaration: Declaration) {
6210+
if (isBindingElement(declaration) && findAncestor(declaration, isParameter)) {
6211+
bindingElementToMakeVisible = declaration;
6212+
}
62096213
if (!isDeclarationVisible(declaration)) {
62106214
// Mark the unexported alias as visible if its parent is visible
62116215
// because these kind of aliases can be used to name types in declaration file

src/compiler/transformers/declarations.ts

Lines changed: 278 additions & 52 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5591,6 +5591,7 @@ export type LateVisibilityPaintedStatement =
55915591
/** @internal */
55925592
export interface SymbolVisibilityResult {
55935593
accessibility: SymbolAccessibility;
5594+
bindingElementToMakeVisible?: BindingElement;
55945595
aliasesToMakeVisible?: LateVisibilityPaintedStatement[]; // aliases that need to have this symbol visible
55955596
errorSymbolName?: string; // Optional symbol name that results in error
55965597
errorNode?: Node; // optional node that results in error
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
declarationEmitBindingPatternsUnused.ts(85,35): error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
2+
declarationEmitBindingPatternsUnused.ts(89,41): error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
3+
declarationEmitBindingPatternsUnused.ts(95,11): error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
4+
declarationEmitBindingPatternsUnused.ts(96,15): error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
5+
declarationEmitBindingPatternsUnused.ts(97,16): error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
6+
declarationEmitBindingPatternsUnused.ts(98,12): error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
7+
8+
9+
==== declarationEmitBindingPatternsUnused.ts (6 errors) ====
10+
type Named = { name: string }
11+
function notReferenced({ name: alias }: Named) {
12+
13+
}
14+
function notReferencedNestedAlias({ p: { name: alias } }: { p: Named }) {
15+
}
16+
function notReferencedArrayAlias([a, b, { name: alias }]: Named[]) {
17+
}
18+
19+
20+
21+
function referencedInCode({ name: alias }: Named) {
22+
return alias;
23+
}
24+
25+
function referencedInSignarture({ name: alias }: Named): typeof alias {
26+
return alias;
27+
}
28+
29+
function referencedInSignartureKeyword({ function: alias }: { function: string }): typeof alias {
30+
return null!;
31+
}
32+
33+
function referencedInInferredType({ name: alias }: Named) {
34+
type Named2 = { name: typeof alias }
35+
return null! as Named2
36+
}
37+
38+
function referencedInNestedFunction({ name: alias }: Named) {
39+
return function(p: typeof alias) {
40+
41+
}
42+
}
43+
44+
function referencedNestedAlias({ p: { name: alias } }: { p: Named }): typeof alias {
45+
return alias;
46+
}
47+
48+
function referencedArrayAlias([a, b, { name: alias }]: Named[]): typeof alias {
49+
return alias;
50+
}
51+
52+
53+
class NotReferencedClass {
54+
constructor({ name: alias }: Named) {
55+
}
56+
set x({ name: alias }: Named) {
57+
console.log(alias);
58+
}
59+
m({ name: alias }: Named) {
60+
console.log(alias);
61+
}
62+
}
63+
64+
class ReferencedInCodeClas {
65+
constructor({ name: alias }: Named) {
66+
console.log(alias);
67+
}
68+
set x({ name: alias }: Named) {
69+
console.log(alias);
70+
}
71+
m({ name: alias }: Named) {
72+
console.log(alias);
73+
}
74+
}
75+
76+
class ReferencedInSignartureClass {
77+
constructor({ name: alias }: Named, p: typeof alias) {
78+
console.log(alias);
79+
}
80+
set x({ name: alias }: Named & { o: typeof alias }) {
81+
82+
}
83+
mReturnType({ name: alias }: Named): typeof alias {
84+
return null!
85+
}
86+
mRerturnTypeNested({ name: alias }: Named): NonNullable<typeof alias> {
87+
return null!
88+
}
89+
mParameter({ name: alias }: Named, p: typeof alias) {
90+
return null!
91+
}
92+
}
93+
94+
let notReferencedFnType: ({ name: alias }: Named) => void;
95+
~~~~~
96+
!!! error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
97+
let referencedInSignartureReturnTypeFnType: ({ name: alias }: Named) => typeof alias;
98+
let referencedInSignartureParamTypeFnType: ({ name: alias }: Named, p: typeof alias) => void;
99+
100+
let notReferencedCtorType: new ({ name: alias }: Named) => void;
101+
~~~~~
102+
!!! error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
103+
let referencedInSignartureReturnTypeCtorType: new ({ name: alias }: Named) => typeof alias;
104+
let referencedInSignartureParamTypeCtorType: new ({ name: alias }: Named, p: typeof alias) => void;
105+
106+
107+
interface NotReferencedInterface {
108+
({ name: alias }: Named): void
109+
~~~~~
110+
!!! error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
111+
new ({ name: alias }: Named): void
112+
~~~~~
113+
!!! error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
114+
set x({ name: alias }: Named);
115+
~~~~~
116+
!!! error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
117+
m({ name: alias }: Named);
118+
~~~~~
119+
!!! error TS2842: 'alias' is an unused renaming of 'name'. Did you intend to use it as a type annotation?
120+
}
121+
122+
interface ReferencedInSignartureInterface {
123+
({ name: alias }: Named, p: typeof alias): void
124+
({ name: alias }: Named): typeof alias
125+
126+
new ({ name: alias }: Named, p: typeof alias): void
127+
new ({ name: alias }: Named): typeof alias
128+
set x({ name: alias }: Named & { o: typeof alias })
129+
mReturnType({ name: alias }: Named): typeof alias;
130+
mRerturnTypeNested({ name: alias }: Named): NonNullable<typeof alias>;
131+
mParameter({ name: alias }: Named, p: typeof alias);
132+
}

0 commit comments

Comments
 (0)