Skip to content

Commit 2f453ce

Browse files
author
Paul van Brenk
committed
Handle most module cases
1 parent 7196018 commit 2f453ce

File tree

7 files changed

+89
-26
lines changed

7 files changed

+89
-26
lines changed

src/harness/fourslash.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2055,7 +2055,7 @@ namespace FourSlash {
20552055

20562056
const diagnostic = !errorCode ? diagnostics[0] : ts.find(diagnostics, d => d.code == errorCode);
20572057

2058-
return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]);
2058+
return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.start + diagnostic.length, [diagnostic.code]);
20592059
}
20602060

20612061
public verifyCodeFixAtPosition(expectedText: string, errorCode?: number) {

src/services/codefixes/unusedIdentifierFixes.ts

Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ namespace ts.codefix {
88
getCodeActions: (context: CodeFixContext) => {
99
const sourceFile = context.sourceFile;
1010
const start = context.span.start;
11-
const token = getTokenAtPosition(sourceFile, start);
11+
12+
let token = getTokenAtPosition(sourceFile, start);
13+
14+
// this handles var ["computed"] = 12;
15+
if (token.kind === SyntaxKind.OpenBracketToken) {
16+
token = getTokenAtPosition(sourceFile, start + 1);
17+
}
1218

1319
switch (token.kind) {
1420
case ts.SyntaxKind.Identifier:
@@ -72,34 +78,43 @@ namespace ts.codefix {
7278
return removeSingleItem(functionDeclaration.parameters, token);
7379
}
7480

81+
// handle case where 'import a = A;'
82+
case SyntaxKind.ImportEqualsDeclaration:
83+
let importEquals = findImportDeclaration(token);
84+
return createCodeFix("", importEquals.pos, importEquals.end - importEquals.pos);
85+
7586
case SyntaxKind.ImportSpecifier:
7687
const namedImports = <NamedImports>token.parent.parent;
77-
const elements = namedImports.elements;
78-
if (elements.length === 1) {
79-
// Only 1 import and it is unused. So the entire line could be removed.
80-
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos);
88+
if (namedImports.elements.length === 1) {
89+
// Only 1 import and it is unused. So the entire declaration should be removed.
90+
let importSpec = findImportDeclaration(token);
91+
return createCodeFix("", importSpec.pos, importSpec.end - importSpec.pos);
8192
}
8293
else {
83-
return removeSingleItem(elements, token);
94+
return removeSingleItem(namedImports.elements, token);
8495
}
8596

86-
// handle case where 'import a = A;'
87-
case SyntaxKind.ImportEqualsDeclaration:
88-
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos);
89-
90-
// handle case where 'import d from './file'
91-
case SyntaxKind.ImportClause:
92-
return createCodeFix("", token.parent.parent.pos, token.parent.parent.end - token.parent.parent.pos);
97+
// handle case where "import d, * as ns from './file'"
98+
// or "'import {a, b as ns} from './file'"
99+
case SyntaxKind.ImportClause: // this covers both 'import |d|' and 'import |d,| *'
100+
const importClause = <ImportClause>token.parent;
101+
if (!importClause.namedBindings) { // |import d from './file'| or |import * as ns from './file'|
102+
const importDecl = findImportDeclaration(importClause);
103+
return createCodeFix("", importDecl.pos, importDecl.end - importDecl.pos);
104+
}
105+
else { // import |d,| * as ns from './file'
106+
return createCodeFix("", importClause.name.pos, importClause.namedBindings.pos - importClause.name.pos);
107+
}
93108

94-
// handle case where 'import * as a from './file'
95109
case SyntaxKind.NamespaceImport:
96-
return createCodeFix("", token.parent.parent.parent.pos, token.parent.parent.parent.end - token.parent.parent.parent.pos);
97-
98-
default:
99-
if (isDeclarationName(token)) {
100-
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos);
110+
const namespaceImport = <NamespaceImport>token.parent;
111+
if(namespaceImport.name == token && !(<ImportClause>namespaceImport.parent).name){
112+
const importDecl = findImportDeclaration(namespaceImport);
113+
return createCodeFix("", importDecl.pos, importDecl.end - importDecl.pos);
114+
} else {
115+
const start = (<ImportClause>namespaceImport.parent).name.end;
116+
return createCodeFix("", start, (<ImportClause>namespaceImport.parent).namedBindings.end - start);
101117
}
102-
break;
103118
}
104119
break;
105120

@@ -109,8 +124,24 @@ namespace ts.codefix {
109124
case SyntaxKind.NamespaceImport:
110125
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos);
111126
}
127+
if (isDeclarationName(token)) {
128+
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos);
129+
}
130+
else if (isLiteralComputedPropertyDeclarationName(token)) {
131+
return createCodeFix("", token.parent.parent.pos, token.parent.parent.end - token.parent.parent.pos);
132+
}
133+
else {
134+
return undefined;
135+
}
112136

113-
return undefined;
137+
function findImportDeclaration(token: Node): Node {
138+
let importDecl = token;
139+
while (importDecl.kind != SyntaxKind.ImportDeclaration && importDecl.parent) {
140+
importDecl = importDecl.parent;
141+
}
142+
143+
return importDecl;
144+
}
114145

115146
function createCodeFix(newText: string, start: number, length: number): CodeAction[] {
116147
return [{
@@ -133,3 +164,19 @@ namespace ts.codefix {
133164
}
134165
});
135166
}
167+
168+
const s = "hello";
169+
170+
class C {
171+
172+
173+
174+
private ["string"]: string;
175+
private "b iz": string;
176+
177+
bar() {
178+
this
179+
}
180+
}
181+
182+

tests/cases/fourslash/unusedImports12FS.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
//// export function f2(s: string){};
1111
//// export default f1;
1212

13-
verify.codeFixAtPosition('import f1 "./file1";');
13+
verify.codeFixAtPosition('import f1 from "./file1";');

tests/cases/fourslash/unusedImports1FS.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
// @noUnusedLocals: true
44
// @Filename: file2.ts
5-
//// [| import { Calculator } from "./file1" |]
5+
//// [|import { Calculator } from "./file1" |]
66

77
// @Filename: file1.ts
88
//// export class Calculator {

tests/cases/fourslash/unusedImports2FS.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
// @noUnusedLocals: true
44
// @Filename: file2.ts
5-
//// [| import {Calculator} from "./file1"
6-
//// import {test} from "./file1" |]
5+
//// [|import {Calculator} from "./file1"
6+
//// import {test} from "./file1"|]
77

88
//// var x = new Calculator();
99
//// x.handleChar();
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @noUnusedLocals: true
4+
//// [|class C {
5+
//// private ["string"] (){}
6+
//// }|]
7+
8+
verify.codeFixAtPosition("class C { }");
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @noUnusedLocals: true
4+
//// [|class C {
5+
//// private "string" (){}
6+
//// }|]
7+
8+
verify.codeFixAtPosition("class C { }");

0 commit comments

Comments
 (0)