Skip to content

Commit 24842b4

Browse files
author
Andy
authored
When --noUnusedLocals/--noUnusedParameters is disabled, add suggestions instead of errors (#22361)
* When --noUnusedLocals/--noUnusedParameters is disabled, add suggestions instead of errors * Improve performance: do not add unused suggestion diagnostics unless asking for a suggestion * Add "unused" flag to diagnostics * Code review * reportsUnused -> reportsUnnecessary * Fix test
1 parent f61f126 commit 24842b4

File tree

67 files changed

+335
-200
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+335
-200
lines changed

src/compiler/checker.ts

Lines changed: 151 additions & 121 deletions
Large diffs are not rendered by default.

src/compiler/core.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,7 @@ namespace ts {
16061606
messageText: text,
16071607
category: message.category,
16081608
code: message.code,
1609+
reportsUnnecessary: message.unused,
16091610
};
16101611
}
16111612

@@ -1635,7 +1636,8 @@ namespace ts {
16351636

16361637
messageText: text,
16371638
category: message.category,
1638-
code: message.code
1639+
code: message.code,
1640+
reportsUnnecessary: message.unused,
16391641
};
16401642
}
16411643

@@ -1647,7 +1649,7 @@ namespace ts {
16471649

16481650
code: chain.code,
16491651
category: chain.category,
1650-
messageText: chain.next ? chain : chain.messageText
1652+
messageText: chain.next ? chain : chain.messageText,
16511653
};
16521654
}
16531655

src/compiler/diagnosticMessages.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3282,7 +3282,8 @@
32823282
},
32833283
"'{0}' is declared but its value is never read.": {
32843284
"category": "Error",
3285-
"code": 6133
3285+
"code": 6133,
3286+
"unused": true
32863287
},
32873288
"Report errors on unused locals.": {
32883289
"category": "Message",
@@ -3302,7 +3303,8 @@
33023303
},
33033304
"Property '{0}' is declared but its value is never read.": {
33043305
"category": "Error",
3305-
"code": 6138
3306+
"code": 6138,
3307+
"unused": true
33063308
},
33073309
"Import emit helpers from 'tslib'.": {
33083310
"category": "Message",
@@ -3514,7 +3516,8 @@
35143516
},
35153517
"All imports in import declaration are unused.": {
35163518
"category": "Error",
3517-
"code": 6192
3519+
"code": 6192,
3520+
"unused": true
35183521
},
35193522
"Found 1 error.": {
35203523
"category": "Message",
@@ -3602,7 +3605,8 @@
36023605
},
36033606
"Unused label.": {
36043607
"category": "Error",
3605-
"code": 7028
3608+
"code": 7028,
3609+
"unused": true
36063610
},
36073611
"Fallthrough case in switch.": {
36083612
"category": "Error",

src/compiler/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4069,6 +4069,7 @@ namespace ts {
40694069
category: DiagnosticCategory;
40704070
code: number;
40714071
message: string;
4072+
unused?: {};
40724073
}
40734074

40744075
/**
@@ -4090,6 +4091,8 @@ namespace ts {
40904091
length: number | undefined;
40914092
messageText: string | DiagnosticMessageChain;
40924093
category: DiagnosticCategory;
4094+
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
4095+
reportsUnnecessary?: {};
40934096
code: number;
40944097
source?: string;
40954098
}

src/harness/fourslash.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2577,7 +2577,7 @@ Actual: ${stringify(fullActual)}`);
25772577
}
25782578
const range = ts.first(ranges);
25792579

2580-
const codeFixes = this.getCodeFixes(fileName, errorCode, preferences);
2580+
const codeFixes = this.getCodeFixes(fileName, errorCode, preferences).filter(f => f.fixId === undefined); // TODO: GH#20315 filter out those that use the import fix ID;
25812581

25822582
if (codeFixes.length === 0) {
25832583
if (expectedTextArray.length !== 0) {

src/harness/unittests/matchFiles.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,14 @@ namespace ts {
123123
}
124124
{
125125
const actual = parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack);
126-
expected.errors = expected.errors.map<Diagnostic>(error => ({
126+
expected.errors = expected.errors.map((error): Diagnostic => ({
127127
category: error.category,
128128
code: error.code,
129129
file: undefined,
130130
length: undefined,
131131
messageText: error.messageText,
132132
start: undefined,
133+
reportsUnnecessary: undefined,
133134
}));
134135
assertParsed(actual, expected);
135136
}

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4068,7 +4068,7 @@ namespace ts.projectSystem {
40684068
const folderPath = "/a/b/projects/temp";
40694069
const file1: FileOrFolder = {
40704070
path: `${folderPath}/a.ts`,
4071-
content: 'import f = require("pad")'
4071+
content: 'import f = require("pad"); f;'
40724072
};
40734073
const files = [file1, libFile];
40744074
const host = createServerHost(files);

src/server/client.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,11 @@ namespace ts.server {
353353
return this.getDiagnostics(file, CommandNames.SuggestionDiagnosticsSync);
354354
}
355355

356-
private getDiagnostics(file: string, command: CommandNames) {
356+
private getDiagnostics(file: string, command: CommandNames): Diagnostic[] {
357357
const request = this.processRequest<protocol.SyntacticDiagnosticsSyncRequest | protocol.SemanticDiagnosticsSyncRequest | protocol.SuggestionDiagnosticsSyncRequest>(command, { file, includeLinePosition: true });
358358
const response = this.processResponse<protocol.SyntacticDiagnosticsSyncResponse | protocol.SemanticDiagnosticsSyncResponse | protocol.SuggestionDiagnosticsSyncResponse>(request);
359359

360-
return (<protocol.DiagnosticWithLinePosition[]>response.body).map(entry => {
360+
return (<protocol.DiagnosticWithLinePosition[]>response.body).map((entry): Diagnostic => {
361361
const category = firstDefined(Object.keys(DiagnosticCategory), id =>
362362
isString(id) && entry.category === id.toLowerCase() ? (<any>DiagnosticCategory)[id] : undefined);
363363
return {
@@ -366,7 +366,8 @@ namespace ts.server {
366366
length: entry.length,
367367
messageText: entry.message,
368368
category: Debug.assertDefined(category, "convertDiagnostic: category should not be undefined"),
369-
code: entry.code
369+
code: entry.code,
370+
reportsUnnecessary: entry.reportsUnnecessary,
370371
};
371372
});
372373
}

src/server/protocol.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,8 @@ namespace ts.server.protocol {
455455
endLocation: Location;
456456
category: string;
457457
code: number;
458+
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
459+
reportsUnnecessary?: {};
458460
}
459461

460462
/**

src/services/shims.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ namespace ts {
588588
length: number;
589589
category: string;
590590
code: number;
591+
unused?: {};
591592
}
592593
export function realizeDiagnostics(diagnostics: ReadonlyArray<Diagnostic>, newLine: string): RealizedDiagnostic[] {
593594
return diagnostics.map(d => realizeDiagnostic(d, newLine));

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2271,6 +2271,7 @@ declare namespace ts {
22712271
category: DiagnosticCategory;
22722272
code: number;
22732273
message: string;
2274+
unused?: {};
22742275
}
22752276
/**
22762277
* A linked list of formatted diagnostic messages to be used as part of a multiline message.
@@ -2290,6 +2291,8 @@ declare namespace ts {
22902291
length: number | undefined;
22912292
messageText: string | DiagnosticMessageChain;
22922293
category: DiagnosticCategory;
2294+
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
2295+
reportsUnnecessary?: {};
22932296
code: number;
22942297
source?: string;
22952298
}
@@ -5398,6 +5401,8 @@ declare namespace ts.server.protocol {
53985401
endLocation: Location;
53995402
category: string;
54005403
code: number;
5404+
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
5405+
reportsUnnecessary?: {};
54015406
}
54025407
/**
54035408
* Response message for "projectInfo" request

tests/baselines/reference/api/typescript.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2271,6 +2271,7 @@ declare namespace ts {
22712271
category: DiagnosticCategory;
22722272
code: number;
22732273
message: string;
2274+
unused?: {};
22742275
}
22752276
/**
22762277
* A linked list of formatted diagnostic messages to be used as part of a multiline message.
@@ -2290,6 +2291,8 @@ declare namespace ts {
22902291
length: number | undefined;
22912292
messageText: string | DiagnosticMessageChain;
22922293
category: DiagnosticCategory;
2294+
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
2295+
reportsUnnecessary?: {};
22932296
code: number;
22942297
source?: string;
22952298
}

tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//// * @return {...*}
66
//// */
77
//// m(x) {
8+
//// return [x];
89
//// }
910
////}
1011

@@ -16,6 +17,7 @@ verify.codeFix({
1617
* @return {...*}
1718
*/
1819
m(x): any[] {
20+
return [x];
1921
}
2022
}`,
2123
});

tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//// * @param {promise<String>} zeta
1313
//// */
1414
////function f(x, y, z, alpha, beta, gamma, delta, epsilon, zeta) {
15+
//// x; y; z; alpha; beta; gamma; delta; epsilon; zeta;
1516
////}
1617

1718
verify.codeFix({
@@ -29,5 +30,6 @@ verify.codeFix({
2930
* @param {promise<String>} zeta
3031
*/
3132
function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise<any>, delta: Array<any>, epsilon: Array<number>, zeta: Promise<string>) {
33+
x; y; z; alpha; beta; gamma; delta; epsilon; zeta;
3234
}`,
3335
});
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/// <reference path='fourslash.ts' />
22
// @strict: true
33
/////** @type {function(*, ...number, ...boolean): void} */
4-
////var x = (x, ys, ...zs) => { };
4+
////var x = (x, ys, ...zs) => { x; ys; zs; };
55

66
verify.codeFix({
77
description: "Annotate with type from JSDoc",
88
index: 0,
99
newFileContent:
1010
`/** @type {function(*, ...number, ...boolean): void} */
11-
var x: (arg0: any, arg1: number[], ...rest: boolean[]) => void = (x, ys, ...zs) => { };`,
11+
var x: (arg0: any, arg1: number[], ...rest: boolean[]) => void = (x, ys, ...zs) => { x; ys; zs; };`,
1212
});

tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//// /**
44
//// * @param {number} x - the first parameter
55
//// */
6-
//// constructor(x) {
6+
//// constructor(readonly x) {
77
//// }
88
////}
99

@@ -14,7 +14,7 @@ verify.codeFix({
1414
/**
1515
* @param {number} x - the first parameter
1616
*/
17-
constructor(x: number) {
17+
constructor(readonly x: number) {
1818
}
1919
}`,
2020
});
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
/// <reference path='fourslash.ts' />
22
////class C {
33
//// /** @param {number} value */
4-
//// set c(value) { return 12 }
4+
//// set c(value) { return value }
55
////}
66

77
verify.codeFix({
88
description: "Annotate with type from JSDoc",
99
newFileContent:
1010
`class C {
1111
/** @param {number} value */
12-
set c(value: number) { return 12 }
12+
set c(value: number) { return value }
1313
}`,
1414
});

tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//// * @param {T} b
77
//// */
88
////function f(a, b) {
9+
//// return a || b;
910
////}
1011

1112
verify.codeFix({
@@ -17,5 +18,6 @@ verify.codeFix({
1718
* @param {T} b
1819
*/
1920
function f<T>(a: number, b: T) {
21+
return a || b;
2022
}`,
2123
});

tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
//// * @param {number} a
55
//// * @param {T} b
66
//// */
7-
////function /*1*/f<T>(a, b) {
7+
////function f<T>(a, b) {
88
////}
99

1010
verify.codeFix({
1111
description: "Annotate with type from JSDoc",
12+
errorCode: 80004, // ignore 'unused T'
1213
newFileContent:
1314
`/**
1415
* @param {number} a

tests/cases/fourslash/annotateWithTypeFromJSDoc21.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,35 @@
44
//// * @return {number}
55
//// */
66
////function [|f|](x, y) {
7+
//// return x + y;
78
////}
89
////
910
/////**
1011
//// * @return {number}
1112
//// */
1213
////function g(x, y): number {
13-
//// return 0;
14+
//// return x + y;
1415
////}
1516
/////**
1617
//// * @param {number} x
1718
//// */
1819
////function h(x: number, y): number {
19-
//// return 0;
20+
//// return x + y;
2021
////}
2122
////
2223
/////**
2324
//// * @param {number} x
2425
//// * @param {string} y
2526
//// */
2627
////function i(x: number, y: string) {
28+
//// return x + y;
2729
////}
2830
/////**
2931
//// * @param {number} x
3032
//// * @return {boolean}
3133
//// */
3234
////function j(x: number, y): boolean {
33-
//// return true;
35+
//// return x < y;
3436
////}
3537

3638
// Only first location triggers a suggestion
@@ -41,37 +43,40 @@ verify.getSuggestionDiagnostics([{
4143

4244
verify.codeFix({
4345
description: "Annotate with type from JSDoc",
44-
newFileContent:
46+
errorCode: 80004,
47+
newFileContent:
4548
`/**
4649
* @return {number}
4750
*/
4851
function f(x, y): number {
52+
return x + y;
4953
}
5054
5155
/**
5256
* @return {number}
5357
*/
5458
function g(x, y): number {
55-
return 0;
59+
return x + y;
5660
}
5761
/**
5862
* @param {number} x
5963
*/
6064
function h(x: number, y): number {
61-
return 0;
65+
return x + y;
6266
}
6367
6468
/**
6569
* @param {number} x
6670
* @param {string} y
6771
*/
6872
function i(x: number, y: string) {
73+
return x + y;
6974
}
7075
/**
7176
* @param {number} x
7277
* @return {boolean}
7378
*/
7479
function j(x: number, y): boolean {
75-
return true;
80+
return x < y;
7681
}`,
7782
});

0 commit comments

Comments
 (0)