Skip to content

Commit 0860b94

Browse files
committed
Harden Extract Symbol against symbols without declarations
Fixes #21793
1 parent 22c4862 commit 0860b94

4 files changed

Lines changed: 57 additions & 2 deletions

File tree

src/harness/unittests/extractFunctions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,11 @@ var q = /*b*/ //c
546546
/*g*/ + /*h*/ //i
547547
/*j*/ 2|] /*k*/ //l
548548
/*m*/; /*n*/ //o`);
549+
550+
testExtractFunction("extractFunction_NoDeclarations", `
551+
function F() {
552+
[#|arguments.length|]; // arguments has no declaration
553+
}`);
549554
});
550555

551556
function testExtractFunction(caption: string, text: string, includeLib?: boolean) {

src/services/refactors/extractSymbol.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,8 @@ namespace ts.refactor.extractSymbol {
16891689
return symbolId;
16901690
}
16911691
// find first declaration in this file
1692-
const declInFile = find(symbol.getDeclarations(), d => d.getSourceFile() === sourceFile);
1692+
const decls = symbol.getDeclarations();
1693+
const declInFile = decls && find(decls, d => d.getSourceFile() === sourceFile);
16931694
if (!declInFile) {
16941695
return undefined;
16951696
}
@@ -1782,7 +1783,8 @@ namespace ts.refactor.extractSymbol {
17821783
if (!symbol) {
17831784
return undefined;
17841785
}
1785-
if (symbol.getDeclarations().some(d => d.parent === scopeDecl)) {
1786+
const decls = symbol.getDeclarations();
1787+
if (decls && decls.some(d => d.parent === scopeDecl)) {
17861788
return createIdentifier(symbol.name);
17871789
}
17881790
const prefix = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.parent, scopeDecl, isTypeNode);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// ==ORIGINAL==
2+
3+
function F() {
4+
/*[#|*/arguments.length/*|]*/; // arguments has no declaration
5+
}
6+
// ==SCOPE::Extract to inner function in function 'F'==
7+
8+
function F() {
9+
/*RENAME*/newFunction(); // arguments has no declaration
10+
11+
12+
function newFunction() {
13+
arguments.length;
14+
}
15+
}
16+
// ==SCOPE::Extract to function in global scope==
17+
18+
function F() {
19+
/*RENAME*/newFunction(); // arguments has no declaration
20+
}
21+
22+
function newFunction() {
23+
arguments.length;
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// ==ORIGINAL==
2+
3+
function F() {
4+
/*[#|*/arguments.length/*|]*/; // arguments has no declaration
5+
}
6+
// ==SCOPE::Extract to inner function in function 'F'==
7+
8+
function F() {
9+
/*RENAME*/newFunction(); // arguments has no declaration
10+
11+
12+
function newFunction() {
13+
arguments.length;
14+
}
15+
}
16+
// ==SCOPE::Extract to function in global scope==
17+
18+
function F() {
19+
/*RENAME*/newFunction(); // arguments has no declaration
20+
}
21+
22+
function newFunction() {
23+
arguments.length;
24+
}

0 commit comments

Comments
 (0)