Skip to content

Commit f529115

Browse files
AnyhowStepsandersn
andauthored
fixes #41286 (#41294)
* fixes #41286 * Added period to end of deprecation message * Search Symbol.declarations for deprecated tag instead of Symbol.valueDeclaration * renamed arg0 to deprecatedEntity, narrowed param type * Added different deprecation message if signature is available * address PR comments Co-authored-by: Nathan Shively-Sanders <[email protected]>
1 parent d7d8f33 commit f529115

12 files changed

+146
-101
lines changed

src/compiler/checker.ts

+36-6
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,31 @@ namespace ts {
11211121
return diagnostic;
11221122
}
11231123

1124+
function addDeprecatedSuggestionWorker(declarations: Node | Node[], diagnostic: DiagnosticWithLocation) {
1125+
const deprecatedTag = Array.isArray(declarations) ? forEach(declarations, getJSDocDeprecatedTag) : getJSDocDeprecatedTag(declarations);
1126+
if (deprecatedTag) {
1127+
addRelatedInfo(
1128+
diagnostic,
1129+
createDiagnosticForNode(deprecatedTag, Diagnostics.The_declaration_was_marked_as_deprecated_here)
1130+
);
1131+
}
1132+
// We call `addRelatedInfo()` before adding the diagnostic to prevent duplicates.
1133+
suggestionDiagnostics.add(diagnostic);
1134+
return diagnostic;
1135+
}
1136+
1137+
function addDeprecatedSuggestion(location: Node, declarations: Node[], deprecatedEntity: string) {
1138+
const diagnostic = createDiagnosticForNode(location, Diagnostics._0_is_deprecated, deprecatedEntity);
1139+
return addDeprecatedSuggestionWorker(declarations, diagnostic);
1140+
}
1141+
1142+
function addDeprecatedSuggestionWithSignature(location: Node, declaration: Node, deprecatedEntity: string | undefined, signatureString: string) {
1143+
const diagnostic = deprecatedEntity
1144+
? createDiagnosticForNode(location, Diagnostics.The_signature_0_of_1_is_deprecated, signatureString, deprecatedEntity)
1145+
: createDiagnosticForNode(location, Diagnostics._0_is_deprecated, signatureString);
1146+
return addDeprecatedSuggestionWorker(declaration, diagnostic);
1147+
}
1148+
11241149
function createSymbol(flags: SymbolFlags, name: __String, checkFlags?: CheckFlags) {
11251150
symbolCount++;
11261151
const symbol = <TransientSymbol>(new Symbol(flags | SymbolFlags.Transient, name));
@@ -14147,7 +14172,7 @@ namespace ts {
1414714172
if (prop) {
1414814173
if (reportDeprecated && accessNode && getDeclarationNodeFlagsFromSymbol(prop) & NodeFlags.Deprecated && isUncalledFunctionReference(accessNode, prop)) {
1414914174
const deprecatedNode = accessExpression?.argumentExpression ?? (isIndexedAccessTypeNode(accessNode) ? accessNode.indexType : accessNode);
14150-
errorOrSuggestion(/* isError */ false, deprecatedNode, Diagnostics._0_is_deprecated, propName as string);
14175+
addDeprecatedSuggestion(deprecatedNode, prop.declarations, propName as string);
1415114176
}
1415214177
if (accessExpression) {
1415314178
markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === SyntaxKind.ThisKeyword);
@@ -23309,7 +23334,7 @@ namespace ts {
2330923334
const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
2331023335
const sourceSymbol = localOrExportSymbol.flags & SymbolFlags.Alias ? resolveAlias(localOrExportSymbol) : localOrExportSymbol;
2331123336
if (getDeclarationNodeFlagsFromSymbol(sourceSymbol) & NodeFlags.Deprecated && isUncalledFunctionReference(node, sourceSymbol)) {
23312-
errorOrSuggestion(/* isError */ false, node, Diagnostics._0_is_deprecated, node.escapedText as string);
23337+
addDeprecatedSuggestion(node, sourceSymbol.declarations, node.escapedText as string);
2331323338
}
2331423339

2331523340
let declaration: Declaration | undefined = localOrExportSymbol.valueDeclaration;
@@ -26362,7 +26387,7 @@ namespace ts {
2636226387
}
2636326388
else {
2636426389
if (getDeclarationNodeFlagsFromSymbol(prop) & NodeFlags.Deprecated && isUncalledFunctionReference(node, prop)) {
26365-
errorOrSuggestion(/* isError */ false, right, Diagnostics._0_is_deprecated, right.escapedText as string);
26390+
addDeprecatedSuggestion(right, prop.declarations, right.escapedText as string);
2636626391
}
2636726392
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
2636826393
markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword);
@@ -28971,7 +28996,8 @@ namespace ts {
2897128996
function checkDeprecatedSignature(signature: Signature, node: CallLikeExpression) {
2897228997
if (signature.declaration && signature.declaration.flags & NodeFlags.Deprecated) {
2897328998
const suggestionNode = getDeprecatedSuggestionNode(node);
28974-
errorOrSuggestion(/*isError*/ false, suggestionNode, Diagnostics._0_is_deprecated, signatureToString(signature));
28999+
const name = tryGetPropertyAccessOrIdentifierToString(getInvokedExpression(node));
29000+
addDeprecatedSuggestionWithSignature(suggestionNode, signature.declaration, name, signatureToString(signature));
2897529001
}
2897629002
}
2897729003

@@ -32456,7 +32482,11 @@ namespace ts {
3245632482
const symbol = getNodeLinks(node).resolvedSymbol;
3245732483
if (symbol) {
3245832484
if (some(symbol.declarations, d => isTypeDeclaration(d) && !!(d.flags & NodeFlags.Deprecated))) {
32459-
errorOrSuggestion(/* isError */ false, getDeprecatedSuggestionNode(node), Diagnostics._0_is_deprecated, symbol.escapedName as string);
32485+
addDeprecatedSuggestion(
32486+
getDeprecatedSuggestionNode(node),
32487+
symbol.declarations,
32488+
symbol.escapedName as string
32489+
);
3246032490
}
3246132491
if (type.flags & TypeFlags.Enum && symbol.flags & SymbolFlags.EnumMember) {
3246232492
error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type));
@@ -36903,7 +36933,7 @@ namespace ts {
3690336933
}
3690436934

3690536935
if (isImportSpecifier(node) && every(target.declarations, d => !!(getCombinedNodeFlags(d) & NodeFlags.Deprecated))) {
36906-
errorOrSuggestion(/* isError */ false, node.name, Diagnostics._0_is_deprecated, symbol.escapedName as string);
36936+
addDeprecatedSuggestion(node.name, target.declarations, symbol.escapedName as string);
3690736937
}
3690836938
}
3690936939
}

src/compiler/diagnosticMessages.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -3235,6 +3235,10 @@
32353235
"category": "Error",
32363236
"code": 2797
32373237
},
3238+
"The declaration was marked as deprecated here.": {
3239+
"category": "Error",
3240+
"code": 2798
3241+
},
32383242

32393243
"Import declaration '{0}' is using private name '{1}'.": {
32403244
"category": "Error",
@@ -4898,7 +4902,7 @@
48984902
"category": "Message",
48994903
"code": 6384
49004904
},
4901-
"'{0}' is deprecated": {
4905+
"'{0}' is deprecated.": {
49024906
"category": "Suggestion",
49034907
"code": 6385,
49044908
"reportsDeprecated": true
@@ -4907,6 +4911,11 @@
49074911
"category": "Message",
49084912
"code": 6386
49094913
},
4914+
"The signature '{0}' of '{1}' is deprecated.": {
4915+
"category": "Suggestion",
4916+
"code": 6387,
4917+
"reportsDeprecated": true
4918+
},
49104919

49114920
"The expected type comes from property '{0}' which is declared here on type '{1}'": {
49124921
"category": "Message",

src/compiler/utilities.ts

+6
Original file line numberDiff line numberDiff line change
@@ -4880,6 +4880,12 @@ namespace ts {
48804880
return baseStr + "." + entityNameToString(expr.name);
48814881
}
48824882
}
4883+
else if (isElementAccessExpression(expr)) {
4884+
const baseStr = tryGetPropertyAccessOrIdentifierToString(expr.expression);
4885+
if (baseStr !== undefined && isPropertyName(expr.argumentExpression)) {
4886+
return baseStr + "." + getPropertyNameForPropertyNameNode(expr.argumentExpression);
4887+
}
4888+
}
48834889
else if (isIdentifier(expr)) {
48844890
return unescapeLeadingUnderscores(expr.escapedText);
48854891
}

tests/cases/fourslash/jsdocDeprecated_suggestion1.ts

+47-47
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ goTo.file('a.ts')
8181
const ranges = test.ranges();
8282
verify.getSuggestionDiagnostics([
8383
{
84-
"code": 6385,
85-
"message": "'(): void' is deprecated",
84+
"code": 6387,
85+
"message": "The signature '(): void' of 'faff' is deprecated.",
8686
"reportsDeprecated": true,
8787
"range": ranges[0]
8888
},
@@ -93,92 +93,92 @@ verify.getSuggestionDiagnostics([
9393
"range": ranges[1]
9494
},
9595
{
96-
"code": 6385,
97-
"message": "'(): void' is deprecated",
96+
"code": 6387,
97+
"message": "The signature '(): void' of 'foo.faff' is deprecated.",
9898
"reportsDeprecated": true,
9999
"range": ranges[2]
100100
},
101101
{
102102
"code": 6385,
103-
"message": "'faff' is deprecated",
103+
"message": "'faff' is deprecated.",
104104
"reportsDeprecated": true,
105105
"range": ranges[3]
106106
},
107107
{
108108
"code": 6385,
109-
"message": "'faff' is deprecated",
109+
"message": "'faff' is deprecated.",
110110
"reportsDeprecated": true,
111111
"range": ranges[4]
112112
},
113113
{
114-
"code": 6385,
115-
"message": "'(): void' is deprecated",
114+
"code": 6387,
115+
"message": "The signature '(): void' of 'faff' is deprecated.",
116116
"reportsDeprecated": true,
117117
"range": ranges[5]
118118
},
119119
{
120-
"code": 6385,
121-
"message": "'(): void' is deprecated",
120+
"code": 6387,
121+
"message": "The signature '(): void' of 'foo.faff' is deprecated.",
122122
"reportsDeprecated": true,
123123
"range": ranges[6]
124124
},
125125
{
126-
"code": 6385,
127-
"message": "'(): void' is deprecated",
126+
"code": 6387,
127+
"message": "The signature '(): void' of 'foo.faff' is deprecated.",
128128
"reportsDeprecated": true,
129129
"range": ranges[7]
130130
},
131131
{
132-
"code": 6385,
133-
"message": "'(): void' is deprecated",
132+
"code": 6387,
133+
"message": "The signature '(): void' of 'bar' is deprecated.",
134134
"reportsDeprecated": true,
135135
"range": ranges[8]
136136
},
137137
{
138138
"code": 6385,
139-
"message": "'Foo' is deprecated",
139+
"message": "'Foo' is deprecated.",
140140
"reportsDeprecated": true,
141141
"range": ranges[9]
142142
},
143143
{
144144
"code": 6385,
145-
"message": "'zzz' is deprecated",
145+
"message": "'zzz' is deprecated.",
146146
"reportsDeprecated": true,
147147
"range": ranges[10]
148148
},
149149
{
150150
"code": 6385,
151-
"message": "'QW' is deprecated",
151+
"message": "'QW' is deprecated.",
152152
"reportsDeprecated": true,
153153
"range": ranges[11]
154154
},
155155
{
156-
"code": 6385,
157-
"message": "'(): C' is deprecated",
156+
"code": 6387,
157+
"message": "The signature '(): C' of 'C' is deprecated.",
158158
"reportsDeprecated": true,
159159
"range": ranges[12]
160160
},
161161
{
162-
"code": 6385,
163-
"message": "'(): void' is deprecated",
162+
"code": 6387,
163+
"message": "The signature '(): void' of 'c.m' is deprecated.",
164164
"reportsDeprecated": true,
165165
"range": ranges[13]
166166
},
167167
{
168168
"code": 6385,
169-
"message": "'m' is deprecated",
169+
"message": "'m' is deprecated.",
170170
"reportsDeprecated": true,
171171
"range": ranges[14]
172172
},
173173
{
174174
"code": 6385,
175-
"message": "'D' is deprecated",
175+
"message": "'D' is deprecated.",
176176
"reportsDeprecated": true,
177177
"range": ranges[15]
178178
},
179179
{
180180
"code": 6385,
181-
"message": "'D' is deprecated",
181+
"message": "'D' is deprecated.",
182182
"reportsDeprecated": true,
183183
"range": ranges[16]
184184
},
@@ -188,49 +188,49 @@ goTo.file('j.tsx')
188188
verify.getSuggestionDiagnostics([
189189
{
190190
"code": 6385,
191-
"message": "'Compi' is deprecated",
191+
"message": "'Compi' is deprecated.",
192192
"reportsDeprecated": true,
193193
"range": ranges[17]
194194
},
195195
{
196-
"code": 6385,
197-
"message": "'(_props: Props): any' is deprecated",
196+
"code": 6387,
197+
"message": "The signature '(_props: Props): any' of 'Compi' is deprecated.",
198198
"reportsDeprecated": true,
199199
"range": ranges[18]
200200
},
201201
{
202-
"code": 6385,
203-
"message": "'(_props: Props): any' is deprecated",
202+
"code": 6387,
203+
"message": "The signature '(_props: Props): any' of 'Compi' is deprecated.",
204204
"reportsDeprecated": true,
205205
"range": ranges[19]
206206
},
207207
{
208208
"code": 6385,
209-
"message": "'Compi' is deprecated",
209+
"message": "'Compi' is deprecated.",
210210
"reportsDeprecated": true,
211211
"range": ranges[20]
212212
},
213213
{
214-
"code": 6385,
215-
"message": "'(_x: unknown): void' is deprecated",
214+
"code": 6387,
215+
"message": "The signature '(_x: unknown): void' of 'ttf' is deprecated.",
216216
"reportsDeprecated": true,
217217
"range": ranges[21]
218218
},
219219
{
220220
"code": 6385,
221-
"message": "'ttf' is deprecated",
221+
"message": "'ttf' is deprecated.",
222222
"reportsDeprecated": true,
223223
"range": ranges[22]
224224
},
225225
{
226226
"code": 6385,
227-
"message": "'dec' is deprecated",
227+
"message": "'dec' is deprecated.",
228228
"reportsDeprecated": true,
229229
"range": ranges[23]
230230
},
231231
{
232-
"code": 6385,
233-
"message": "'(_c: unknown): void' is deprecated",
232+
"code": 6387,
233+
"message": "The signature '(_c: unknown): void' of 'dec' is deprecated.",
234234
"reportsDeprecated": true,
235235
"range": ranges[24]
236236
},
@@ -239,49 +239,49 @@ goTo.file('b.ts')
239239
verify.getSuggestionDiagnostics([
240240
{
241241
"code": 6385,
242-
"message": "'bar' is deprecated",
242+
"message": "'bar' is deprecated.",
243243
"reportsDeprecated": true,
244244
"range": ranges[25]
245245
},
246246
{
247247
"code": 6385,
248-
"message": "'QW' is deprecated",
248+
"message": "'QW' is deprecated.",
249249
"reportsDeprecated": true,
250250
"range": ranges[26]
251251
},
252252
{
253-
"code": 6385,
254-
"message": "'(): void' is deprecated",
253+
"code": 6387,
254+
"message": "The signature '(): void' of 'f.bar' is deprecated.",
255255
"reportsDeprecated": true,
256256
"range": ranges[27]
257257
},
258258
{
259-
"code": 6385,
260-
"message": "'(): void' is deprecated",
259+
"code": 6387,
260+
"message": "The signature '(): void' of 'f.foo.faff' is deprecated.",
261261
"reportsDeprecated": true,
262262
"range": ranges[28]
263263
},
264264
{
265-
"code": 6385,
266-
"message": "'(): void' is deprecated",
265+
"code": 6387,
266+
"message": "The signature '(): void' of 'bar' is deprecated.",
267267
"reportsDeprecated": true,
268268
"range": ranges[29]
269269
},
270270
{
271271
"code": 6385,
272-
"message": "'QW' is deprecated",
272+
"message": "'QW' is deprecated.",
273273
"reportsDeprecated": true,
274274
"range": ranges[30]
275275
},
276276
{
277277
"code": 6385,
278-
"message": "'Foo' is deprecated",
278+
"message": "'Foo' is deprecated.",
279279
"reportsDeprecated": true,
280280
"range": ranges[31]
281281
},
282282
{
283283
"code": 6385,
284-
"message": "'QW' is deprecated",
284+
"message": "'QW' is deprecated.",
285285
"reportsDeprecated": true,
286286
"range": ranges[32]
287287
},

0 commit comments

Comments
 (0)