Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2605,14 +2605,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return diagnostic;
}

function isDeprecatedSymbol(symbol: Symbol) {
const parentSymbol = getParentOfSymbol(symbol);
if (parentSymbol && length(symbol.declarations) > 1) {
return parentSymbol.flags & SymbolFlags.Interface ? some(symbol.declarations, isDeprecatedDeclaration) : every(symbol.declarations, isDeprecatedDeclaration);
}
return !!symbol.valueDeclaration && isDeprecatedDeclaration(symbol.valueDeclaration)
|| length(symbol.declarations) && every(symbol.declarations, isDeprecatedDeclaration);
}
function isDeprecatedSymbol(symbol: Symbol) {
const parentSymbol = getParentOfSymbol(symbol);
if (parentSymbol && length(symbol.declarations) > 1) {
if (parentSymbol.flags & SymbolFlags.Interface || symbol.flags & SymbolFlags.Accessor) {
return some(symbol.declarations, isDeprecatedDeclaration);
}
return every(symbol.declarations, isDeprecatedDeclaration);
}
return !!symbol.valueDeclaration && isDeprecatedDeclaration(symbol.valueDeclaration)
|| length(symbol.declarations) && every(symbol.declarations, isDeprecatedDeclaration);
}

function isDeprecatedDeclaration(declaration: Declaration) {
return !!(getCombinedNodeFlagsCached(declaration) & NodeFlags.Deprecated);
Expand Down
12 changes: 8 additions & 4 deletions src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6084,10 +6084,14 @@ function symbolCanBeReferencedAtTypeLocation(symbol: Symbol, checker: TypeChecke
}
}

function isDeprecated(symbol: Symbol, checker: TypeChecker) {
const declarations = skipAlias(symbol, checker).declarations;
return !!length(declarations) && every(declarations, isDeprecatedDeclaration);
}
function isDeprecated(symbol: Symbol, checker: TypeChecker) {
const resolvedSymbol = skipAlias(symbol, checker);
const declarations = resolvedSymbol.declarations;
if (resolvedSymbol.flags & SymbolFlags.Accessor) {
return !!length(declarations) && some(declarations, isDeprecatedDeclaration);
}
return !!length(declarations) && every(declarations, isDeprecatedDeclaration);
}

/**
* True if the first character of `lowercaseCharacters` is the first character
Expand Down
33 changes: 19 additions & 14 deletions src/services/symbolDisplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,20 +213,25 @@ function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeCheck
return ScriptElementKind.unknown;
}

function getNormalizedSymbolModifiers(symbol: Symbol) {
if (symbol.declarations && symbol.declarations.length) {
const [declaration, ...declarations] = symbol.declarations;
// omit deprecated flag if some declarations are not deprecated
const excludeFlags = length(declarations) && isDeprecatedDeclaration(declaration) && some(declarations, d => !isDeprecatedDeclaration(d))
? ModifierFlags.Deprecated
: ModifierFlags.None;
const modifiers = getNodeModifiers(declaration, excludeFlags);
if (modifiers) {
return modifiers.split(",");
}
}
return [];
}
function getNormalizedSymbolModifiers(symbol: Symbol) {
if (symbol.declarations && symbol.declarations.length) {
const [declaration, ...declarations] = symbol.declarations;
// omit deprecated flag if some declarations are not deprecated
const excludeFlags = length(declarations) && isDeprecatedDeclaration(declaration) && some(declarations, d => !isDeprecatedDeclaration(d))
? ModifierFlags.Deprecated
: ModifierFlags.None;
const modifiers = getNodeModifiers(declaration, excludeFlags);
if (modifiers) {
const result = modifiers.split(",");
// For getter/setter pairs, include deprecated if any accessor has @deprecated
if (symbol.flags & SymbolFlags.Accessor && !result.includes("deprecated") && some(symbol.declarations, isDeprecatedDeclaration)) {
result.push("deprecated");
}
return result;
}
}
return [];
}

/** @internal */
export function getSymbolModifiers(typeChecker: TypeChecker, symbol: Symbol): string {
Expand Down
35 changes: 35 additions & 0 deletions tests/cases/fourslash/completionsWithDeprecatedGetterSetter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/// <reference path="fourslash.ts" />

// Tests that @deprecated on getter/setter pairs correctly marks the property as deprecated in completions.
// Regression from #41941, reported in #62965.

//// class Test {
//// /** @deprecated */
//// public get test1() { return 0; }
//// public set test1(_value: number) {}
////
//// public get test2() { return 0; }
//// /** @deprecated */
//// public set test2(_value: number) {}
////
//// /** @deprecated */
//// public get test3() { return 0; }
//// /** @deprecated */
//// public set test3(_value: number) {}
////
//// public get test4() { return 0; }
//// public set test4(_value: number) {}
//// }
////
//// const t = new Test();
//// t./*1*/;

verify.completions({
marker: "1",
includes: [
{ name: "test1", kind: "getter", kindModifiers: "public,deprecated", sortText: completion.SortText.Deprecated(completion.SortText.LocationPriority) },
{ name: "test2", kind: "getter", kindModifiers: "public,deprecated", sortText: completion.SortText.Deprecated(completion.SortText.LocationPriority) },
{ name: "test3", kind: "getter", kindModifiers: "public,deprecated", sortText: completion.SortText.Deprecated(completion.SortText.LocationPriority) },
{ name: "test4", kind: "getter", kindModifiers: "public", sortText: completion.SortText.LocationPriority },
],
});
50 changes: 50 additions & 0 deletions tests/cases/fourslash/jsdocDeprecated_suggestionGetterSetter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/// <reference path="fourslash.ts" />

// Tests that @deprecated on getter/setter pairs produces suggestion diagnostics.
// Regression from #41941, reported in #62965.

//// class Test {
//// /** @deprecated */
//// public get test1() { return 0; }
//// public set test1(_value: number) {}
////
//// public get test2() { return 0; }
//// /** @deprecated */
//// public set test2(_value: number) {}
////
//// /** @deprecated */
//// public get test3() { return 0; }
//// /** @deprecated */
//// public set test3(_value: number) {}
////
//// public get test4() { return 0; }
//// public set test4(_value: number) {}
//// }
////
//// const t = new Test();
//// const a = t.[|test1|];
//// const b = t.[|test2|];
//// const c = t.[|test3|];
//// const d = t.test4;

const ranges = test.ranges();
verify.getSuggestionDiagnostics([
{
"code": 6385,
"message": "'test1' is deprecated.",
"reportsDeprecated": true,
"range": ranges[0],
},
{
"code": 6385,
"message": "'test2' is deprecated.",
"reportsDeprecated": true,
"range": ranges[1],
},
{
"code": 6385,
"message": "'test3' is deprecated.",
"reportsDeprecated": true,
"range": ranges[2],
},
]);