Skip to content

Commit 8a0713b

Browse files
committed
Harden Extract Symbol against symbols without declarations
Fixes #21793
1 parent 6dd88b3 commit 8a0713b

File tree

4 files changed

+62
-2
lines changed

4 files changed

+62
-2
lines changed

src/harness/unittests/extractFunctions.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,12 @@ var q = /*b*/ //c
548548
/*m*/; /*n*/ //o`);
549549
});
550550

551+
testExtractFunction("extractFunction_NoDeclarations", `
552+
function F() {
553+
[#|arguments.length|]; // arguments has no declaration
554+
}
555+
`);
556+
551557
function testExtractFunction(caption: string, text: string, includeLib?: boolean) {
552558
testExtractSymbol(caption, text, "extractFunction", Diagnostics.Extract_function, includeLib);
553559
}

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: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// ==ORIGINAL==
2+
3+
function F() {
4+
/*[#|*/arguments.length/*|]*/; // arguments has no declaration
5+
}
6+
7+
// ==SCOPE::Extract to inner function in function 'F'==
8+
9+
function F() {
10+
/*RENAME*/newFunction(); // arguments has no declaration
11+
12+
13+
function newFunction() {
14+
arguments.length;
15+
}
16+
}
17+
18+
// ==SCOPE::Extract to function in global scope==
19+
20+
function F() {
21+
/*RENAME*/newFunction(); // arguments has no declaration
22+
}
23+
24+
function newFunction() {
25+
arguments.length;
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// ==ORIGINAL==
2+
3+
function F() {
4+
/*[#|*/arguments.length/*|]*/; // arguments has no declaration
5+
}
6+
7+
// ==SCOPE::Extract to inner function in function 'F'==
8+
9+
function F() {
10+
/*RENAME*/newFunction(); // arguments has no declaration
11+
12+
13+
function newFunction() {
14+
arguments.length;
15+
}
16+
}
17+
18+
// ==SCOPE::Extract to function in global scope==
19+
20+
function F() {
21+
/*RENAME*/newFunction(); // arguments has no declaration
22+
}
23+
24+
function newFunction() {
25+
arguments.length;
26+
}

0 commit comments

Comments
 (0)