Add deprecated related feature (#38523)

* Add deprecated related feature

* Add more support

* fix navtree

* Add identifier check

* Add more deprecated

* fix crash

* fix more crash

* fix crash

* improve diagnostic

* avoid new tag

* avoid tags

* accept baseline

* Check deprecated in binder

* fix baseline

* fix jsdoc cache

* fix incorrect fix

* Avoid useless changes

* Accept baseline

* Add tests

* fix perf

* fix public api

* Adjust deprecated mark on qualifed name

* Revolve alias symbol

* Use modifier flags insted of symbol props

* Fix modifier flag resolve

* Make lint happy

* Fix crash

* fix crash

* Add cached utils function

* Accept baseline

* Add more tests

* try pinning octokit again

* Avoid tests

* Use utils some

* Deprecated perf test (#3)

* check valueDeclaration only

* check without modifierFlags

* donot check alias

* use cached tag

* remove call to jsdoc

* use deprecated tag

* revert changes

* Revert mission changes

* use node flags

* cache result

* cache

* avoid modifier flags

* Opts

* fix jsdoc include modifier

* fix tests

* fix again

* use symbol flag

* set @octokit/rest back to latest

* fix trailing spacel int

Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
This commit is contained in:
Wenlu Wang 2020-06-19 08:41:26 +08:00 committed by GitHub
parent 520103fab0
commit 59ad375234
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 493 additions and 105 deletions

View File

@ -5,6 +5,7 @@ interface DiagnosticDetails {
category: string;
code: number;
reportsUnnecessary?: {};
reportsDeprecated?: {};
isEarly?: boolean;
elidedInCompatabilityPyramid?: boolean;
}
@ -64,15 +65,17 @@ function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, inputFil
"// generated from '" + inputFilePathRel + "' by '" + thisFilePathRel.replace(/\\/g, "/") + "'\r\n" +
"/* @internal */\r\n" +
"namespace ts {\r\n" +
" function diag(code: number, category: DiagnosticCategory, key: string, message: string, reportsUnnecessary?: {}, elidedInCompatabilityPyramid?: boolean): DiagnosticMessage {\r\n" +
" return { code, category, key, message, reportsUnnecessary, elidedInCompatabilityPyramid };\r\n" +
" function diag(code: number, category: DiagnosticCategory, key: string, message: string, reportsUnnecessary?: {}, elidedInCompatabilityPyramid?: boolean, reportsDeprecated?: {}): DiagnosticMessage {\r\n" +
" return { code, category, key, message, reportsUnnecessary, elidedInCompatabilityPyramid, reportsDeprecated };\r\n" +
" }\r\n" +
" export const Diagnostics = {\r\n";
messageTable.forEach(({ code, category, reportsUnnecessary, elidedInCompatabilityPyramid }, name) => {
messageTable.forEach(({ code, category, reportsUnnecessary, elidedInCompatabilityPyramid, reportsDeprecated }, name) => {
const propName = convertPropertyName(name);
const argReportsUnnecessary = reportsUnnecessary ? `, /*reportsUnnecessary*/ ${reportsUnnecessary}` : "";
const argElidedInCompatabilityPyramid = elidedInCompatabilityPyramid ? `${!reportsUnnecessary ? ", /*reportsUnnecessary*/ undefined" : ""}, /*elidedInCompatabilityPyramid*/ ${elidedInCompatabilityPyramid}` : "";
result += ` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${JSON.stringify(name)}${argReportsUnnecessary}${argElidedInCompatabilityPyramid}),\r\n`;
const argReportsDeprecated = reportsDeprecated ? `${!argElidedInCompatabilityPyramid ? ", /*reportsUnnecessary*/ undefined, /*elidedInCompatabilityPyramid*/ undefined" : ""}, /*reportsDeprecated*/ ${reportsDeprecated}` : "";
result += ` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${JSON.stringify(name)}${argReportsUnnecessary}${argElidedInCompatabilityPyramid}${argReportsDeprecated}),\r\n`;
});
result += " };\r\n}";

View File

@ -537,6 +537,10 @@ namespace ts {
symbol.parent = parent;
}
if (node.flags & NodeFlags.Deprecated) {
symbol.flags |= SymbolFlags.Deprecated;
}
return symbol;
}

View File

@ -3,6 +3,7 @@ namespace ts {
export interface ReusableDiagnostic extends ReusableDiagnosticRelatedInformation {
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
reportDeprecated?: {}
source?: string;
relatedInformation?: ReusableDiagnosticRelatedInformation[];
skippedOn?: keyof CompilerOptions;
@ -268,6 +269,7 @@ namespace ts {
return diagnostics.map(diagnostic => {
const result: Diagnostic = convertToDiagnosticRelatedInformation(diagnostic, newProgram, toPath);
result.reportsUnnecessary = diagnostic.reportsUnnecessary;
result.reportsDeprecated = diagnostic.reportDeprecated;
result.source = diagnostic.source;
result.skippedOn = diagnostic.skippedOn;
const { relatedInformation } = diagnostic;
@ -817,6 +819,7 @@ namespace ts {
return diagnostics.map(diagnostic => {
const result: ReusableDiagnostic = convertToReusableDiagnosticRelatedInformation(diagnostic, relativeToBuildInfo);
result.reportsUnnecessary = diagnostic.reportsUnnecessary;
result.reportDeprecated = diagnostic.reportsDeprecated;
result.source = diagnostic.source;
result.skippedOn = diagnostic.skippedOn;
const { relatedInformation } = diagnostic;

View File

@ -13168,6 +13168,10 @@ namespace ts {
if (propName !== undefined) {
const prop = getPropertyOfType(objectType, propName);
if (prop) {
if (accessNode && prop.flags & SymbolFlags.Deprecated) {
const deprecatedNode = accessExpression?.argumentExpression ?? (isIndexedAccessTypeNode(accessNode) ? accessNode.indexType : accessNode);
errorOrSuggestion(/* isError */ false, deprecatedNode, Diagnostics._0_is_deprecated, propName as string);
}
if (accessExpression) {
markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === SyntaxKind.ThisKeyword);
if (isAssignmentToReadonlyEntity(accessExpression, prop, getAssignmentTargetKind(accessExpression))) {
@ -21698,6 +21702,10 @@ namespace ts {
const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
let declaration: Declaration | undefined = localOrExportSymbol.valueDeclaration;
const target = (symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol);
if (target.flags & SymbolFlags.Deprecated) {
errorOrSuggestion(/* isError */ false, node, Diagnostics._0_is_deprecated, node.escapedText as string);
}
if (localOrExportSymbol.flags & SymbolFlags.Class) {
// Due to the emit for class decorators, any reference to the class from inside of the class body
// must instead be rewritten to point to a temporary variable to avoid issues with the double-bind
@ -24679,6 +24687,10 @@ namespace ts {
propType = indexInfo.type;
}
else {
if (prop.flags & SymbolFlags.Deprecated) {
errorOrSuggestion(/* isError */ false, right, Diagnostics._0_is_deprecated, right.escapedText as string);
}
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword);
getNodeLinks(node).resolvedSymbol = prop;
@ -30499,8 +30511,15 @@ namespace ts {
checkTypeArgumentConstraints(node, typeParameters);
}
}
if (type.flags & TypeFlags.Enum && getNodeLinks(node).resolvedSymbol!.flags & SymbolFlags.EnumMember) {
error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type));
const symbol = getNodeLinks(node).resolvedSymbol;
if (symbol) {
if (symbol.flags & SymbolFlags.Deprecated) {
const diagLocation = isTypeReferenceNode(node) && isQualifiedName(node.typeName) ? node.typeName.right : node;
errorOrSuggestion(/* isError */ false, diagLocation, Diagnostics._0_is_deprecated, symbol.escapedName as string);
}
if (type.flags & TypeFlags.Enum && symbol.flags & SymbolFlags.EnumMember) {
error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type));
}
}
}
}
@ -31644,6 +31663,7 @@ namespace ts {
error(classLike, Diagnostics.JSDoc_0_is_not_attached_to_a_class, idText(node.tagName));
}
}
function checkJSDocAugmentsTag(node: JSDocAugmentsTag): void {
const classLike = getEffectiveJSDocHost(node);
if (!classLike || !isClassDeclaration(classLike) && !isClassExpression(classLike)) {
@ -34803,33 +34823,39 @@ namespace ts {
let symbol = getSymbolOfNode(node);
const target = resolveAlias(symbol);
const shouldSkipWithJSExpandoTargets = symbol.flags & SymbolFlags.Assignment;
if (!shouldSkipWithJSExpandoTargets && target !== unknownSymbol) {
// For external modules symbol represents local symbol for an alias.
// This local symbol will merge any other local declarations (excluding other aliases)
// and symbol.flags will contains combined representation for all merged declaration.
// Based on symbol.flags we can compute a set of excluded meanings (meaning that resolved alias should not have,
// otherwise it will conflict with some local declaration). Note that in addition to normal flags we include matching SymbolFlags.Export*
// in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names).
symbol = getMergedSymbol(symbol.exportSymbol || symbol);
const excludedMeanings =
(symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) |
(symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) |
(symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0);
if (target.flags & excludedMeanings) {
const message = node.kind === SyntaxKind.ExportSpecifier ?
Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 :
Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0;
error(node, message, symbolToString(symbol));
if (target !== unknownSymbol) {
const shouldSkipWithJSExpandoTargets = symbol.flags & SymbolFlags.Assignment;
if (!shouldSkipWithJSExpandoTargets) {
// For external modules symbol represents local symbol for an alias.
// This local symbol will merge any other local declarations (excluding other aliases)
// and symbol.flags will contains combined representation for all merged declaration.
// Based on symbol.flags we can compute a set of excluded meanings (meaning that resolved alias should not have,
// otherwise it will conflict with some local declaration). Note that in addition to normal flags we include matching SymbolFlags.Export*
// in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names).
symbol = getMergedSymbol(symbol.exportSymbol || symbol);
const excludedMeanings =
(symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) |
(symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) |
(symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0);
if (target.flags & excludedMeanings) {
const message = node.kind === SyntaxKind.ExportSpecifier ?
Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 :
Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0;
error(node, message, symbolToString(symbol));
}
// Don't allow to re-export something with no value side when `--isolatedModules` is set.
if (compilerOptions.isolatedModules
&& node.kind === SyntaxKind.ExportSpecifier
&& !node.parent.parent.isTypeOnly
&& !(target.flags & SymbolFlags.Value)
&& !(node.flags & NodeFlags.Ambient)) {
error(node, Diagnostics.Re_exporting_a_type_when_the_isolatedModules_flag_is_provided_requires_using_export_type);
}
}
// Don't allow to re-export something with no value side when `--isolatedModules` is set.
if (compilerOptions.isolatedModules
&& node.kind === SyntaxKind.ExportSpecifier
&& !node.parent.parent.isTypeOnly
&& !(target.flags & SymbolFlags.Value)
&& !(node.flags & NodeFlags.Ambient)) {
error(node, Diagnostics.Re_exporting_a_type_when_the_isolatedModules_flag_is_provided_requires_using_export_type);
if (isImportSpecifier(node) && target.flags & SymbolFlags.Deprecated) {
errorOrSuggestion(/* isError */ false, node.name, Diagnostics._0_is_deprecated, symbol.escapedName as string);
}
}
}

View File

@ -4602,6 +4602,11 @@
"category": "Message",
"code": 6384
},
"'{0}' is deprecated": {
"category": "Suggestion",
"code": 6385,
"reportsDeprecated": true
},
"The expected type comes from property '{0}' which is declared here on type '{1}'": {
"category": "Message",

View File

@ -358,6 +358,8 @@ namespace ts {
get updateJSDocProtectedTag() { return getJSDocSimpleTagUpdateFunction<JSDocProtectedTag>(SyntaxKind.JSDocProtectedTag); },
get createJSDocReadonlyTag() { return getJSDocSimpleTagCreateFunction<JSDocReadonlyTag>(SyntaxKind.JSDocReadonlyTag); },
get updateJSDocReadonlyTag() { return getJSDocSimpleTagUpdateFunction<JSDocReadonlyTag>(SyntaxKind.JSDocReadonlyTag); },
get createJSDocDeprecatedTag() { return getJSDocSimpleTagCreateFunction<JSDocDeprecatedTag>(SyntaxKind.JSDocDeprecatedTag); },
get updateJSDocDeprecatedTag() { return getJSDocSimpleTagUpdateFunction<JSDocDeprecatedTag>(SyntaxKind.JSDocDeprecatedTag); },
createJSDocUnknownTag,
updateJSDocUnknownTag,
createJSDocComment,
@ -4225,6 +4227,7 @@ namespace ts {
// createJSDocPrivateTag
// createJSDocProtectedTag
// createJSDocReadonlyTag
// createJSDocDeprecatedTag
function createJSDocSimpleTagWorker<T extends JSDocTag>(kind: T["kind"], tagName: Identifier | undefined, comment?: string) {
const node = createBaseJSDocTag<T>(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment);
return node;
@ -4237,6 +4240,7 @@ namespace ts {
// updateJSDocPrivateTag
// updateJSDocProtectedTag
// updateJSDocReadonlyTag
// updateJSDocDeprecatedTag
function updateJSDocSimpleTagWorker<T extends JSDocTag>(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), comment: string | undefined) {
return node.tagName !== tagName
|| node.comment !== comment

View File

@ -769,6 +769,10 @@ namespace ts {
return node.kind === SyntaxKind.JSDocReadonlyTag;
}
export function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag {
return node.kind === SyntaxKind.JSDocDeprecatedTag;
}
export function isJSDocEnumTag(node: Node): node is JSDocEnumTag {
return node.kind === SyntaxKind.JSDocEnumTag;
}

View File

@ -1014,10 +1014,15 @@ namespace ts {
return hasJSDoc ? addJSDocComment(node) : node;
}
let hasDeprecatedTag = false;
function addJSDocComment<T extends HasJSDoc>(node: T): T {
Debug.assert(!node.jsDoc); // Should only be called once per node
const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos));
if (jsDoc.length) node.jsDoc = jsDoc;
if (hasDeprecatedTag) {
hasDeprecatedTag = false;
(node as Mutable<T>).flags |= NodeFlags.Deprecated;
}
return node;
}
@ -7178,6 +7183,10 @@ namespace ts {
case "readonly":
tag = parseSimpleTag(start, factory.createJSDocReadonlyTag, tagName, margin, indentText);
break;
case "deprecated":
hasDeprecatedTag = true;
tag = parseSimpleTag(start, factory.createJSDocDeprecatedTag, tagName, margin, indentText);
break;
case "this":
tag = parseThisTag(start, tagName, margin, indentText);
break;

View File

@ -375,6 +375,7 @@ namespace ts {
JSDocAugmentsTag,
JSDocImplementsTag,
JSDocAuthorTag,
JSDocDeprecatedTag,
JSDocClassTag,
JSDocPublicTag,
JSDocPrivateTag,
@ -753,6 +754,7 @@ namespace ts {
/* @internal */ InWithStatement = 1 << 24, // If any ancestor of node was the `statement` of a WithStatement (not the `expression`)
JsonFile = 1 << 25, // If node was parsed in a Json
/* @internal */ TypeCached = 1 << 26, // If a type was cached for node at any point
/* @internal */ Deprecated = 1 << 27, // If has '@deprecated' JSDoc tag
BlockScoped = Let | Const,
@ -785,6 +787,8 @@ namespace ts {
Default = 1 << 9, // Function/Class (export default declaration)
Const = 1 << 11, // Const enum
HasComputedJSDocModifiers = 1 << 12, // Indicates the computed modifier flags include modifiers from JSDoc.
Deprecated = 1 << 13, // Deprecated tag.
HasComputedFlags = 1 << 29, // Modifier flags have been computed
AccessibilityModifier = Public | Private | Protected,
@ -794,7 +798,7 @@ namespace ts {
TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const,
ExportDefault = Export | Default,
All = Export | Ambient | Public | Private | Protected | Static | Readonly | Abstract | Async | Default | Const
All = Export | Ambient | Public | Private | Protected | Static | Readonly | Abstract | Async | Default | Const | Deprecated
}
export const enum JsxFlags {
@ -3131,6 +3135,10 @@ namespace ts {
readonly kind: SyntaxKind.JSDocAuthorTag;
}
export interface JSDocDeprecatedTag extends JSDocTag {
kind: SyntaxKind.JSDocDeprecatedTag;
}
export interface JSDocClassTag extends JSDocTag {
readonly kind: SyntaxKind.JSDocClassTag;
}
@ -4503,10 +4511,10 @@ namespace ts {
Transient = 1 << 25, // Transient symbol (created during type check)
Assignment = 1 << 26, // Assignment treated as declaration (eg `this.prop = 1`)
ModuleExports = 1 << 27, // Symbol for CommonJS `module` of `module.exports`
Deprecated = 1 << 28, // Symbol has Deprecated declaration tag (eg `@deprecated`)
/* @internal */
All = FunctionScopedVariable | BlockScopedVariable | Property | EnumMember | Function | Class | Interface | ConstEnum | RegularEnum | ValueModule | NamespaceModule | TypeLiteral
| ObjectLiteral | Method | Constructor | GetAccessor | SetAccessor | Signature | TypeParameter | TypeAlias | ExportValue | Alias | Prototype | ExportStar | Optional | Transient,
| ObjectLiteral | Method | Constructor | GetAccessor | SetAccessor | Signature | TypeParameter | TypeAlias | ExportValue | Alias | Prototype | ExportStar | Optional | Transient | Deprecated,
Enum = RegularEnum | ConstEnum,
Variable = FunctionScopedVariable | BlockScopedVariable,
@ -5503,6 +5511,7 @@ namespace ts {
code: number;
message: string;
reportsUnnecessary?: {};
reportsDeprecated?: {};
/* @internal */
elidedInCompatabilityPyramid?: boolean;
}
@ -5523,6 +5532,8 @@ namespace ts {
export interface Diagnostic extends DiagnosticRelatedInformation {
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
reportsDeprecated?: {}
source?: string;
relatedInformation?: DiagnosticRelatedInformation[];
/* @internal */ skippedOn?: keyof CompilerOptions;
@ -6956,6 +6967,8 @@ namespace ts {
updateJSDocReadonlyTag(node: JSDocReadonlyTag, tagName: Identifier | undefined, comment: string | undefined): JSDocReadonlyTag;
createJSDocUnknownTag(tagName: Identifier, comment?: string): JSDocUnknownTag;
updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | undefined): JSDocUnknownTag;
createJSDocDeprecatedTag(tagName: Identifier, comment?: string): JSDocDeprecatedTag;
updateJSDocDeprecatedTag(node: JSDocDeprecatedTag, tagName: Identifier, comment?: string): JSDocDeprecatedTag;
createJSDocComment(comment?: string | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc;
updateJSDocComment(node: JSDoc, comment: string | undefined, tags: readonly JSDocTag[] | undefined): JSDoc;

View File

@ -4555,7 +4555,7 @@ namespace ts {
return getSyntacticModifierFlags(node) & flags;
}
function getModifierFlagsWorker(node: Node, includeJSDoc: boolean): ModifierFlags {
function getModifierFlagsWorker(node: Node, includeJSDoc: boolean, alwaysIncludeJSDoc?: boolean): ModifierFlags {
if (node.kind >= SyntaxKind.FirstToken && node.kind <= SyntaxKind.LastToken) {
return ModifierFlags.None;
}
@ -4564,7 +4564,7 @@ namespace ts {
node.modifierFlagsCache = getSyntacticModifierFlagsNoCache(node) | ModifierFlags.HasComputedFlags;
}
if (includeJSDoc && !(node.modifierFlagsCache & ModifierFlags.HasComputedJSDocModifiers) && isInJSFile(node) && node.parent) {
if (includeJSDoc && !(node.modifierFlagsCache & ModifierFlags.HasComputedJSDocModifiers) && (alwaysIncludeJSDoc || isInJSFile(node)) && node.parent) {
node.modifierFlagsCache |= getJSDocModifierFlagsNoCache(node) | ModifierFlags.HasComputedJSDocModifiers;
}
@ -4580,6 +4580,10 @@ namespace ts {
return getModifierFlagsWorker(node, /*includeJSDoc*/ true);
}
export function getEffectiveModifierFlagsAlwaysIncludeJSDoc(node: Node): ModifierFlags {
return getModifierFlagsWorker(node, /*includeJSDOc*/ true, /*alwaysIncludeJSDOc*/ true);
}
/**
* Gets the ModifierFlags for syntactic modifiers on the provided node. The modifiers will be cached on the node to improve performance.
*
@ -4591,12 +4595,16 @@ namespace ts {
function getJSDocModifierFlagsNoCache(node: Node): ModifierFlags {
let flags = ModifierFlags.None;
if (isInJSFile(node) && !!node.parent && !isParameter(node)) {
if (getJSDocPublicTagNoCache(node)) flags |= ModifierFlags.Public;
if (getJSDocPrivateTagNoCache(node)) flags |= ModifierFlags.Private;
if (getJSDocProtectedTagNoCache(node)) flags |= ModifierFlags.Protected;
if (getJSDocReadonlyTagNoCache(node)) flags |= ModifierFlags.Readonly;
if (!!node.parent && !isParameter(node)) {
if (isInJSFile(node)) {
if (getJSDocPublicTagNoCache(node)) flags |= ModifierFlags.Public;
if (getJSDocPrivateTagNoCache(node)) flags |= ModifierFlags.Private;
if (getJSDocProtectedTagNoCache(node)) flags |= ModifierFlags.Protected;
if (getJSDocReadonlyTagNoCache(node)) flags |= ModifierFlags.Readonly;
}
if (getJSDocDeprecatedTagNoCache(node)) flags |= ModifierFlags.Deprecated;
}
return flags;
}
@ -5679,6 +5687,7 @@ namespace ts {
category: message.category,
code: message.code,
reportsUnnecessary: message.reportsUnnecessary,
reportsDeprecated: message.reportsDeprecated
};
}
@ -5710,6 +5719,7 @@ namespace ts {
category: message.category,
code: message.code,
reportsUnnecessary: message.reportsUnnecessary,
reportsDeprecated: message.reportsDeprecated
};
}

View File

@ -302,6 +302,11 @@ namespace ts {
return getCombinedFlags(node, getEffectiveModifierFlags);
}
/* @internal */
export function getCombinedNodeFlagsAlwaysIncludeJSDoc(node: Declaration): ModifierFlags {
return getCombinedFlags(node, getEffectiveModifierFlagsAlwaysIncludeJSDoc);
}
// Returns the node flags for this node and all relevant parent nodes. This is done so that
// nodes like variable declarations and binding elements can returned a view of their flags
// that includes the modifiers from their container. i.e. flags like export/declare aren't
@ -740,6 +745,16 @@ namespace ts {
return getFirstJSDocTag(node, isJSDocReadonlyTag, /*noCache*/ true);
}
/** Gets the JSDoc deprecated tag for the node if present */
export function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined {
return getFirstJSDocTag(node, isJSDocDeprecatedTag);
}
/*@internal */
export function getJSDocDeprecatedTagNoCache(node: Node): JSDocDeprecatedTag | undefined {
return getFirstJSDocTag(node, isJSDocDeprecatedTag, /*noCache*/ true);
}
/** Gets the JSDoc enum tag for the node if present */
export function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined {
return getFirstJSDocTag(node, isJSDocEnumTag);

View File

@ -388,6 +388,7 @@ namespace ts.server {
category: Debug.checkDefined(category, "convertDiagnostic: category should not be undefined"),
code: entry.code,
reportsUnnecessary: entry.reportsUnnecessary,
reportsDeprecated: entry.reportsDeprecated,
};
});
}
@ -748,6 +749,7 @@ namespace ts.server {
file: item.file,
name: item.name,
kind: item.kind,
kindModifiers: item.kindModifiers,
span: this.decodeSpan(item.span, item.file),
selectionSpan: this.decodeSpan(item.selectionSpan, item.file)
};

View File

@ -1218,6 +1218,7 @@ namespace FourSlash {
code: e.code,
...ts.createTextSpanFromRange(range),
reportsUnnecessary: e.reportsUnnecessary,
reportsDeprecated: e.reportsDeprecated
};
}));
}

View File

@ -1612,6 +1612,7 @@ namespace FourSlashInterface {
range?: FourSlash.Range;
code: number;
reportsUnnecessary?: true;
reportsDeprecated?: true;
}
export interface GetEditsForFileRenameOptions {

View File

@ -498,6 +498,7 @@ namespace ts.server.protocol {
code: number;
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
reportsDeprecated?: {};
relatedInformation?: DiagnosticRelatedInformation[];
}
@ -2535,6 +2536,8 @@ namespace ts.server.protocol {
reportsUnnecessary?: {};
reportsDeprecated?: {};
/**
* Any related spans the diagnostic may have, such as other locations relevant to an error, such as declarartion sites
*/
@ -3066,6 +3069,7 @@ namespace ts.server.protocol {
export interface CallHierarchyItem {
name: string;
kind: ScriptElementKind;
kindModifiers?: string
file: string;
span: TextSpan;
selectionSpan: TextSpan;

View File

@ -56,6 +56,7 @@ namespace ts.server {
code: diag.code,
category: diagnosticCategoryName(diag),
reportsUnnecessary: diag.reportsUnnecessary,
reportsDeprecated: diag.reportsDeprecated,
source: diag.source,
relatedInformation: map(diag.relatedInformation, formatRelatedInformation),
};
@ -100,6 +101,7 @@ namespace ts.server {
code,
category,
reportsUnnecessary: diag.reportsUnnecessary,
reportsDeprecated: diag.reportsDeprecated,
source,
relatedInformation: map(diag.relatedInformation, formatRelatedInformation),
};
@ -1063,6 +1065,7 @@ namespace ts.server {
startLocation: (d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start!)))!, // TODO: GH#18217
endLocation: (d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start! + d.length!)))!, // TODO: GH#18217
reportsUnnecessary: d.reportsUnnecessary,
reportsDeprecated: d.reportsDeprecated,
relatedInformation: map(d.relatedInformation, formatRelatedInformation)
}));
}
@ -1092,6 +1095,7 @@ namespace ts.server {
startLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start!), // TODO: GH#18217
endLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start! + d.length!),
reportsUnnecessary: d.reportsUnnecessary,
reportsDeprecated: d.reportsDeprecated,
relatedInformation: map(d.relatedInformation, formatRelatedInformation),
});
}
@ -1927,6 +1931,7 @@ namespace ts.server {
const bakedItem: protocol.NavtoItem = {
name: navItem.name,
kind: navItem.kind,
kindModifiers: navItem.kindModifiers,
isCaseSensitive: navItem.isCaseSensitive,
matchKind: navItem.matchKind,
file: navItem.fileName,
@ -2266,6 +2271,7 @@ namespace ts.server {
return {
name: item.name,
kind: item.kind,
kindModifiers: item.kindModifiers,
file: item.file,
span: toProtocolTextSpan(item.span, scriptInfo),
selectionSpan: toProtocolTextSpan(item.selectionSpan, scriptInfo)

View File

@ -272,9 +272,10 @@ namespace ts.CallHierarchy {
const name = getCallHierarchyItemName(program, node);
const containerName = getCallHierarchItemContainerName(node);
const kind = getNodeKind(node);
const kindModifiers = getNodeModifiers(node);
const span = createTextSpanFromBounds(skipTrivia(sourceFile.text, node.getFullStart(), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true), node.getEnd());
const selectionSpan = createTextSpanFromBounds(name.pos, name.end);
return { file: sourceFile.fileName, kind, name: name.text, containerName, span, selectionSpan };
return { file: sourceFile.fileName, kind, kindModifiers, name: name.text, containerName, span, selectionSpan };
}
function isDefined<T>(x: T): x is NonNullable<T> {

View File

@ -601,6 +601,7 @@ namespace ts {
category: string;
code: number;
reportsUnnecessary?: {};
reportsDeprecated?: {};
}
export function realizeDiagnostics(diagnostics: readonly Diagnostic[], newLine: string): RealizedDiagnostic[] {
return diagnostics.map(d => realizeDiagnostic(d, newLine));
@ -614,6 +615,7 @@ namespace ts {
category: diagnosticCategoryName(diagnostic),
code: diagnostic.code,
reportsUnnecessary: diagnostic.reportsUnnecessary,
reportsDeprecated: diagnostic.reportsDeprecated
};
}

View File

@ -612,6 +612,7 @@ namespace ts {
export interface CallHierarchyItem {
name: string;
kind: ScriptElementKind;
kindModifiers?: string;
file: string;
span: TextSpan;
selectionSpan: TextSpan;
@ -1298,6 +1299,8 @@ namespace ts {
abstractModifier = "abstract",
optionalModifier = "optional",
deprecatedModifier = "deprecated",
dtsModifier = ".d.ts",
tsModifier = ".ts",
tsxModifier = ".tsx",

View File

@ -1495,7 +1495,7 @@ namespace ts {
}
export function getNodeModifiers(node: Node): string {
const flags = isDeclaration(node) ? getCombinedModifierFlags(node) : ModifierFlags.None;
const flags = isDeclaration(node) ? getCombinedNodeFlagsAlwaysIncludeJSDoc(node) : ModifierFlags.None;
const result: string[] = [];
if (flags & ModifierFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
@ -1504,6 +1504,7 @@ namespace ts {
if (flags & ModifierFlags.Static) result.push(ScriptElementKindModifier.staticModifier);
if (flags & ModifierFlags.Abstract) result.push(ScriptElementKindModifier.abstractModifier);
if (flags & ModifierFlags.Export) result.push(ScriptElementKindModifier.exportedModifier);
if (flags & ModifierFlags.Deprecated) result.push(ScriptElementKindModifier.deprecatedModifier);
if (node.flags & NodeFlags.Ambient) result.push(ScriptElementKindModifier.ambientModifier);
if (node.kind === SyntaxKind.ExportAssignment) result.push(ScriptElementKindModifier.exportedModifier);

View File

@ -128,6 +128,7 @@ namespace ts {
messageText: error.messageText,
start: undefined,
reportsUnnecessary: undefined,
reportsDeprecated: undefined
}));
assertParsed(actual, expected);
}

View File

@ -615,7 +615,8 @@ export = C;
"D.ts",
"d.ts",
),
reportsUnnecessary: undefined
reportsUnnecessary: undefined,
reportsDeprecated: undefined
}]
);
});
@ -641,7 +642,8 @@ export = C;
"/a/b/D.ts",
"d.ts",
),
reportsUnnecessary: undefined
reportsUnnecessary: undefined,
reportsDeprecated: undefined
}]
);
});
@ -667,7 +669,8 @@ export = C;
"ModuleB.ts",
"moduleB.ts",
),
reportsUnnecessary: undefined
reportsUnnecessary: undefined,
reportsDeprecated: undefined
}]
);
});
@ -694,7 +697,8 @@ export = C;
"/a/b/D.ts",
"d.ts",
),
reportsUnnecessary: undefined
reportsUnnecessary: undefined,
reportsDeprecated: undefined
}]
);
});
@ -722,7 +726,8 @@ export = C;
"ModuleC.ts",
"moduleC.ts",
),
reportsUnnecessary: undefined
reportsUnnecessary: undefined,
reportsDeprecated: undefined
},
{
...tscWatch.getDiagnosticOfFileFromProgram(
@ -734,7 +739,8 @@ export = C;
"moduleC.ts",
"ModuleC.ts"
),
reportsUnnecessary: undefined
reportsUnnecessary: undefined,
reportsDeprecated: undefined
}
]
);
@ -766,7 +772,8 @@ import b = require("./moduleB");
"/a/B/c/moduleC.ts",
"/a/B/c/ModuleC.ts"
),
reportsUnnecessary: undefined
reportsUnnecessary: undefined,
reportsDeprecated: undefined
}]
);
});

View File

@ -194,6 +194,7 @@ namespace ts.tscWatch {
messageText: "Type 'number' is not assignable to type 'string'.",
relatedInformation: undefined,
reportsUnnecessary: undefined,
reportsDeprecated: undefined,
source: undefined,
skippedOn: undefined,
}]);

View File

@ -868,6 +868,7 @@ namespace ts.projectSystem {
code: Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file.code,
category: diagnosticCategoryName(Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file),
reportsUnnecessary: undefined,
reportsDeprecated: undefined,
relatedInformation: undefined,
source: undefined
}]

View File

@ -204,6 +204,7 @@ namespace ts.projectSystem {
category: DiagnosticCategory;
code: number;
reportsUnnecessary?: {};
reportsDeprecated?: {};
source?: string;
relatedInformation?: DiagnosticRelatedInformation[];
}
@ -699,8 +700,8 @@ namespace ts.projectSystem {
checkNthEvent(session, server.toEvent(eventName, diagnostics), 0, isMostRecent);
}
export function createDiagnostic(start: protocol.Location, end: protocol.Location, message: DiagnosticMessage, args: readonly string[] = [], category = diagnosticCategoryName(message), reportsUnnecessary?: {}, relatedInformation?: protocol.DiagnosticRelatedInformation[]): protocol.Diagnostic {
return { start, end, text: formatStringFromArgs(message.message, args), code: message.code, category, reportsUnnecessary, relatedInformation, source: undefined };
export function createDiagnostic(start: protocol.Location, end: protocol.Location, message: DiagnosticMessage, args: readonly string[] = [], category = diagnosticCategoryName(message), reportsUnnecessary?: {}, relatedInformation?: protocol.DiagnosticRelatedInformation[], reportsDeprecated?: {}): protocol.Diagnostic {
return { start, end, text: formatStringFromArgs(message.message, args), code: message.code, category, reportsUnnecessary, reportsDeprecated, relatedInformation, source: undefined };
}
export function checkCompleteEvent(session: TestSession, numberOfCurrentEvents: number, expectedSequenceId: number, isMostRecent = true): void {

View File

@ -1,7 +1,11 @@
namespace ts.projectSystem {
describe("unittests:: tsserver:: navigate-to for javascript project", () => {
function findNavToItem(items: protocol.NavtoItem[], itemName: string, itemKind: string) {
return find(items, item => item.name === itemName && item.kind === itemKind);
}
function containsNavToItem(items: protocol.NavtoItem[], itemName: string, itemKind: string) {
return find(items, item => item.name === itemName && item.kind === itemKind) !== undefined;
return findNavToItem(items, itemName, itemKind) !== undefined;
}
it("should not include type symbols", () => {
@ -67,5 +71,26 @@ export const ghijkl = a.abcdef;`
assert.strictEqual(item.name, "abcdef");
assert.strictEqual(item.file, file1.path);
});
it("should work with Deprecated", () => {
const file1: File = {
path: "/a/b/file1.js",
content: "/** @deprecated */\nfunction foo () {}"
};
const configFile: File = {
path: "/a/b/jsconfig.json",
content: "{}"
};
const host = createServerHost([file1, configFile, libFile]);
const session = createSession(host);
openFilesForSession([file1], session);
// Try to find some interface type defined in lib.d.ts
const libTypeNavToRequest = makeSessionRequest<protocol.NavtoRequestArgs>(CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path });
const items = session.executeCommand(libTypeNavToRequest).response as protocol.NavtoItem[];
const fooItem = findNavToItem(items, "foo", "function");
assert.isNotNull(fooItem, `Cannot find function symbol "foo".`);
assert.isTrue(fooItem?.kindModifiers?.includes("deprecated"));
});
});
}

View File

@ -534,7 +534,8 @@ declare module '@custom/plugin' {
messageText: formatStringFromArgs(d.message, didYouMean ? [prop, didYouMean] : [prop]),
category: d.category,
code: d.code,
reportsUnnecessary: undefined
reportsUnnecessary: undefined,
reportsDeprecated: undefined
};
}
@ -549,7 +550,8 @@ declare module '@custom/plugin' {
messageText: formatStringFromArgs(d.message, [`${getDirectoryPath(configFile.path)}/${relativeFileName}`]),
category: d.category,
code: d.code,
reportsUnnecessary: undefined
reportsUnnecessary: undefined,
reportsDeprecated: undefined
};
}
@ -908,6 +910,7 @@ declare module '@custom/plugin' {
code: Diagnostics.Unused_label.code,
relatedInformation: undefined,
reportsUnnecessary: true,
reportsDeprecated: undefined,
source: undefined,
},
]);

View File

@ -390,28 +390,29 @@ declare namespace ts {
JSDocAugmentsTag = 311,
JSDocImplementsTag = 312,
JSDocAuthorTag = 313,
JSDocClassTag = 314,
JSDocPublicTag = 315,
JSDocPrivateTag = 316,
JSDocProtectedTag = 317,
JSDocReadonlyTag = 318,
JSDocCallbackTag = 319,
JSDocEnumTag = 320,
JSDocParameterTag = 321,
JSDocReturnTag = 322,
JSDocThisTag = 323,
JSDocTypeTag = 324,
JSDocTemplateTag = 325,
JSDocTypedefTag = 326,
JSDocPropertyTag = 327,
SyntaxList = 328,
NotEmittedStatement = 329,
PartiallyEmittedExpression = 330,
CommaListExpression = 331,
MergeDeclarationMarker = 332,
EndOfDeclarationMarker = 333,
SyntheticReferenceExpression = 334,
Count = 335,
JSDocDeprecatedTag = 314,
JSDocClassTag = 315,
JSDocPublicTag = 316,
JSDocPrivateTag = 317,
JSDocProtectedTag = 318,
JSDocReadonlyTag = 319,
JSDocCallbackTag = 320,
JSDocEnumTag = 321,
JSDocParameterTag = 322,
JSDocReturnTag = 323,
JSDocThisTag = 324,
JSDocTypeTag = 325,
JSDocTemplateTag = 326,
JSDocTypedefTag = 327,
JSDocPropertyTag = 328,
SyntaxList = 329,
NotEmittedStatement = 330,
PartiallyEmittedExpression = 331,
CommaListExpression = 332,
MergeDeclarationMarker = 333,
EndOfDeclarationMarker = 334,
SyntheticReferenceExpression = 335,
Count = 336,
FirstAssignment = 62,
LastAssignment = 77,
FirstCompoundAssignment = 63,
@ -440,9 +441,9 @@ declare namespace ts {
LastStatement = 245,
FirstNode = 156,
FirstJSDocNode = 298,
LastJSDocNode = 327,
LastJSDocNode = 328,
FirstJSDocTagNode = 310,
LastJSDocTagNode = 327,
LastJSDocTagNode = 328,
}
export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia;
export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral;
@ -498,13 +499,14 @@ declare namespace ts {
Default = 512,
Const = 2048,
HasComputedJSDocModifiers = 4096,
Deprecated = 8192,
HasComputedFlags = 536870912,
AccessibilityModifier = 28,
ParameterPropertyModifier = 92,
NonPublicAccessibilityModifier = 24,
TypeScriptModifier = 2270,
ExportDefault = 513,
All = 3071
All = 11263
}
export enum JsxFlags {
None = 0,
@ -1718,6 +1720,9 @@ declare namespace ts {
export interface JSDocAuthorTag extends JSDocTag {
readonly kind: SyntaxKind.JSDocAuthorTag;
}
export interface JSDocDeprecatedTag extends JSDocTag {
kind: SyntaxKind.JSDocDeprecatedTag;
}
export interface JSDocClassTag extends JSDocTag {
readonly kind: SyntaxKind.JSDocClassTag;
}
@ -2308,6 +2313,7 @@ declare namespace ts {
Transient = 33554432,
Assignment = 67108864,
ModuleExports = 134217728,
Deprecated = 268435456,
Enum = 384,
Variable = 3,
Value = 111551,
@ -2637,6 +2643,7 @@ declare namespace ts {
code: number;
message: string;
reportsUnnecessary?: {};
reportsDeprecated?: {};
}
/**
* A linked list of formatted diagnostic messages to be used as part of a multiline message.
@ -2653,6 +2660,7 @@ declare namespace ts {
export interface Diagnostic extends DiagnosticRelatedInformation {
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
reportsDeprecated?: {};
source?: string;
relatedInformation?: DiagnosticRelatedInformation[];
}
@ -3404,6 +3412,8 @@ declare namespace ts {
updateJSDocReadonlyTag(node: JSDocReadonlyTag, tagName: Identifier | undefined, comment: string | undefined): JSDocReadonlyTag;
createJSDocUnknownTag(tagName: Identifier, comment?: string): JSDocUnknownTag;
updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | undefined): JSDocUnknownTag;
createJSDocDeprecatedTag(tagName: Identifier, comment?: string): JSDocDeprecatedTag;
updateJSDocDeprecatedTag(node: JSDocDeprecatedTag, tagName: Identifier, comment?: string): JSDocDeprecatedTag;
createJSDocComment(comment?: string | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc;
updateJSDocComment(node: JSDoc, comment: string | undefined, tags: readonly JSDocTag[] | undefined): JSDoc;
createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement;
@ -4039,6 +4049,8 @@ declare namespace ts {
function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined;
/** Gets the JSDoc protected tag for the node if present */
function getJSDocReadonlyTag(node: Node): JSDocReadonlyTag | undefined;
/** Gets the JSDoc deprecated tag for the node if present */
function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined;
/** Gets the JSDoc enum tag for the node if present */
function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined;
/** Gets the JSDoc this tag for the node if present */
@ -4398,6 +4410,7 @@ declare namespace ts {
function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag;
function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag;
function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag;
function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag;
function isJSDocEnumTag(node: Node): node is JSDocEnumTag;
function isJSDocParameterTag(node: Node): node is JSDocParameterTag;
function isJSDocReturnTag(node: Node): node is JSDocReturnTag;
@ -5549,6 +5562,7 @@ declare namespace ts {
interface CallHierarchyItem {
name: string;
kind: ScriptElementKind;
kindModifiers?: string;
file: string;
span: TextSpan;
selectionSpan: TextSpan;
@ -6098,6 +6112,7 @@ declare namespace ts {
staticModifier = "static",
abstractModifier = "abstract",
optionalModifier = "optional",
deprecatedModifier = "deprecated",
dtsModifier = ".d.ts",
tsModifier = ".ts",
tsxModifier = ".tsx",
@ -6720,6 +6735,7 @@ declare namespace ts.server.protocol {
code: number;
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
reportsDeprecated?: {};
relatedInformation?: DiagnosticRelatedInformation[];
}
/**
@ -8273,6 +8289,7 @@ declare namespace ts.server.protocol {
*/
category: string;
reportsUnnecessary?: {};
reportsDeprecated?: {};
/**
* Any related spans the diagnostic may have, such as other locations relevant to an error, such as declarartion sites
*/
@ -8709,6 +8726,7 @@ declare namespace ts.server.protocol {
interface CallHierarchyItem {
name: string;
kind: ScriptElementKind;
kindModifiers?: string;
file: string;
span: TextSpan;
selectionSpan: TextSpan;

View File

@ -390,28 +390,29 @@ declare namespace ts {
JSDocAugmentsTag = 311,
JSDocImplementsTag = 312,
JSDocAuthorTag = 313,
JSDocClassTag = 314,
JSDocPublicTag = 315,
JSDocPrivateTag = 316,
JSDocProtectedTag = 317,
JSDocReadonlyTag = 318,
JSDocCallbackTag = 319,
JSDocEnumTag = 320,
JSDocParameterTag = 321,
JSDocReturnTag = 322,
JSDocThisTag = 323,
JSDocTypeTag = 324,
JSDocTemplateTag = 325,
JSDocTypedefTag = 326,
JSDocPropertyTag = 327,
SyntaxList = 328,
NotEmittedStatement = 329,
PartiallyEmittedExpression = 330,
CommaListExpression = 331,
MergeDeclarationMarker = 332,
EndOfDeclarationMarker = 333,
SyntheticReferenceExpression = 334,
Count = 335,
JSDocDeprecatedTag = 314,
JSDocClassTag = 315,
JSDocPublicTag = 316,
JSDocPrivateTag = 317,
JSDocProtectedTag = 318,
JSDocReadonlyTag = 319,
JSDocCallbackTag = 320,
JSDocEnumTag = 321,
JSDocParameterTag = 322,
JSDocReturnTag = 323,
JSDocThisTag = 324,
JSDocTypeTag = 325,
JSDocTemplateTag = 326,
JSDocTypedefTag = 327,
JSDocPropertyTag = 328,
SyntaxList = 329,
NotEmittedStatement = 330,
PartiallyEmittedExpression = 331,
CommaListExpression = 332,
MergeDeclarationMarker = 333,
EndOfDeclarationMarker = 334,
SyntheticReferenceExpression = 335,
Count = 336,
FirstAssignment = 62,
LastAssignment = 77,
FirstCompoundAssignment = 63,
@ -440,9 +441,9 @@ declare namespace ts {
LastStatement = 245,
FirstNode = 156,
FirstJSDocNode = 298,
LastJSDocNode = 327,
LastJSDocNode = 328,
FirstJSDocTagNode = 310,
LastJSDocTagNode = 327,
LastJSDocTagNode = 328,
}
export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia;
export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral;
@ -498,13 +499,14 @@ declare namespace ts {
Default = 512,
Const = 2048,
HasComputedJSDocModifiers = 4096,
Deprecated = 8192,
HasComputedFlags = 536870912,
AccessibilityModifier = 28,
ParameterPropertyModifier = 92,
NonPublicAccessibilityModifier = 24,
TypeScriptModifier = 2270,
ExportDefault = 513,
All = 3071
All = 11263
}
export enum JsxFlags {
None = 0,
@ -1718,6 +1720,9 @@ declare namespace ts {
export interface JSDocAuthorTag extends JSDocTag {
readonly kind: SyntaxKind.JSDocAuthorTag;
}
export interface JSDocDeprecatedTag extends JSDocTag {
kind: SyntaxKind.JSDocDeprecatedTag;
}
export interface JSDocClassTag extends JSDocTag {
readonly kind: SyntaxKind.JSDocClassTag;
}
@ -2308,6 +2313,7 @@ declare namespace ts {
Transient = 33554432,
Assignment = 67108864,
ModuleExports = 134217728,
Deprecated = 268435456,
Enum = 384,
Variable = 3,
Value = 111551,
@ -2637,6 +2643,7 @@ declare namespace ts {
code: number;
message: string;
reportsUnnecessary?: {};
reportsDeprecated?: {};
}
/**
* A linked list of formatted diagnostic messages to be used as part of a multiline message.
@ -2653,6 +2660,7 @@ declare namespace ts {
export interface Diagnostic extends DiagnosticRelatedInformation {
/** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */
reportsUnnecessary?: {};
reportsDeprecated?: {};
source?: string;
relatedInformation?: DiagnosticRelatedInformation[];
}
@ -3404,6 +3412,8 @@ declare namespace ts {
updateJSDocReadonlyTag(node: JSDocReadonlyTag, tagName: Identifier | undefined, comment: string | undefined): JSDocReadonlyTag;
createJSDocUnknownTag(tagName: Identifier, comment?: string): JSDocUnknownTag;
updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | undefined): JSDocUnknownTag;
createJSDocDeprecatedTag(tagName: Identifier, comment?: string): JSDocDeprecatedTag;
updateJSDocDeprecatedTag(node: JSDocDeprecatedTag, tagName: Identifier, comment?: string): JSDocDeprecatedTag;
createJSDocComment(comment?: string | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc;
updateJSDocComment(node: JSDoc, comment: string | undefined, tags: readonly JSDocTag[] | undefined): JSDoc;
createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement;
@ -4039,6 +4049,8 @@ declare namespace ts {
function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined;
/** Gets the JSDoc protected tag for the node if present */
function getJSDocReadonlyTag(node: Node): JSDocReadonlyTag | undefined;
/** Gets the JSDoc deprecated tag for the node if present */
function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined;
/** Gets the JSDoc enum tag for the node if present */
function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined;
/** Gets the JSDoc this tag for the node if present */
@ -4398,6 +4410,7 @@ declare namespace ts {
function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag;
function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag;
function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag;
function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag;
function isJSDocEnumTag(node: Node): node is JSDocEnumTag;
function isJSDocParameterTag(node: Node): node is JSDocParameterTag;
function isJSDocReturnTag(node: Node): node is JSDocReturnTag;
@ -5549,6 +5562,7 @@ declare namespace ts {
interface CallHierarchyItem {
name: string;
kind: ScriptElementKind;
kindModifiers?: string;
file: string;
span: TextSpan;
selectionSpan: TextSpan;
@ -6098,6 +6112,7 @@ declare namespace ts {
staticModifier = "static",
abstractModifier = "abstract",
optionalModifier = "optional",
deprecatedModifier = "deprecated",
dtsModifier = ".d.ts",
tsModifier = ".ts",
tsxModifier = ".tsx",

View File

@ -0,0 +1,32 @@
/// <reference path="fourslash.ts" />
// @strict: true
//// /** @deprecated */
//// interface Foo {
//// /** @deprecated */
//// bar(): void
//// /** @deprecated */
//// prop: number
//// }
//// declare const foo: Foo;
//// declare const foooo: Fo/*1*/;
//// foo.ba/*2*/;
//// foo.pro/*3*/;
verify.completions({
marker: "1",
includes: [
{ name: "Foo", kind: "interface", kindModifiers: "deprecated" }
]
}, {
marker: "2",
includes: [
{ name: "bar", kind: "method", kindModifiers: "deprecated" }
]
}, {
marker: "3",
includes: [
{ name: "prop", kind: "property", kindModifiers: "deprecated" }
]
});

View File

@ -586,6 +586,7 @@ declare namespace FourSlashInterface {
range?: Range;
code: number;
reportsUnnecessary?: true;
reportsDeprecated?: true;
}
interface VerifyDocumentHighlightsOptions {
filesToSearch?: ReadonlyArray<string>;

View File

@ -0,0 +1,166 @@
// @Filename: a.ts
//// export namespace foo {
//// /** @deprecated */
//// export function faff () { }
//// [|faff|]()
//// }
//// const [|a|] = foo.[|faff|]()
//// foo[[|"faff"|]]
//// const { [|faff|] } = foo
//// faff()
//// /** @deprecated */
//// export function bar () {
//// foo?.[|faff|]()
//// }
//// foo?.[[|"faff"|]]?.()
//// [|bar|]();
//// /** @deprecated */
//// export interface Foo {
//// /** @deprecated */
//// zzz: number
//// }
//// /** @deprecated */
//// export type QW = [|Foo|][[|"zzz"|]]
//// export type WQ = [|QW|]
// @Filename: b.ts
//// import * as f from './a';
//// import { [|bar|], [|QW|] } from './a';
//// f.[|bar|]();
//// f.foo.[|faff|]();
//// [|bar|]();
//// type Z = [|QW|];
//// type A = f.[|Foo|];
//// type B = f.[|QW|];
//// type C = f.WQ;
//// type [|O|] = Z | A | B | C;
goTo.file('a.ts')
const ranges = test.ranges();
verify.getSuggestionDiagnostics([
{
message: "'faff' is deprecated",
code: 6385,
range: ranges[0],
reportsDeprecated: true,
},
{
message: "'a' is declared but its value is never read.",
code: 6133,
range: ranges[1],
reportsUnnecessary: true
},
{
message: "'faff' is deprecated",
code: 6385,
range: ranges[2],
reportsDeprecated: true,
},
{
message: "'faff' is deprecated",
code: 6385,
range: ranges[3],
reportsDeprecated: true,
},
{
message: "'faff' is deprecated",
code: 6385,
range: ranges[4],
reportsDeprecated: true,
},
{
message: "'faff' is deprecated",
code: 6385,
range: ranges[5],
reportsDeprecated: true,
},
{
message: "'faff' is deprecated",
code: 6385,
range: ranges[6],
reportsDeprecated: true,
},
{
message: "'bar' is deprecated",
code: 6385,
range: ranges[7],
reportsDeprecated: true,
},
{
message: "'Foo' is deprecated",
code: 6385,
range: ranges[8],
reportsDeprecated: true,
},
{
message: "'zzz' is deprecated",
code: 6385,
range: ranges[9],
reportsDeprecated: true,
},
{
message: "'QW' is deprecated",
code: 6385,
range: ranges[10],
reportsDeprecated: true,
}
])
goTo.file('b.ts')
verify.getSuggestionDiagnostics([
{
message: "'bar' is deprecated",
code: 6385,
range: ranges[11],
reportsDeprecated: true,
},
{
message: "'QW' is deprecated",
code: 6385,
range: ranges[12],
reportsDeprecated: true,
},
{
message: "'bar' is deprecated",
code: 6385,
range: ranges[13],
reportsDeprecated: true,
},
{
message: "'faff' is deprecated",
code: 6385,
range: ranges[14],
reportsDeprecated: true,
},
{
message: "'bar' is deprecated",
code: 6385,
range: ranges[15],
reportsDeprecated: true,
},
{
message: "'QW' is deprecated",
code: 6385,
range: ranges[16],
reportsDeprecated: true,
},
{
message: "'Foo' is deprecated",
code: 6385,
range: ranges[17],
reportsDeprecated: true,
},
{
message: "'QW' is deprecated",
code: 6385,
range: ranges[18],
reportsDeprecated: true,
},
{
message: "'O' is declared but never used.",
code: 6196,
range: ranges[19],
reportsUnnecessary: true
}
])