Add typedef declaration space, unify typedef name gathering (#18172)

* Add typedef declaration space, unify typedef name gathering, strengthen errorUnusedLocal

* Bonus round: make jsdoc presence way mroe typesafe

* Be exhaustive in nameForNamelessJSDocTypedef

* Remove nonrequired casts

* Replace more casts with guards

* Cannot be internal

* Debug.fail returns never, assert never no longer needs unreachable throw to satisfy checker

* Rename type

* Add replacement message as in 18287
This commit is contained in:
Wesley Wigham
2017-09-07 10:28:58 -07:00
committed by GitHub
parent 39d0590869
commit c1f2afd645
17 changed files with 279 additions and 91 deletions
+4 -13
View File
@@ -282,17 +282,8 @@ namespace ts {
const index = indexOf(functionType.parameters, node);
return "arg" + index as __String;
case SyntaxKind.JSDocTypedefTag:
const parentNode = node.parent && node.parent.parent;
let nameFromParentNode: __String;
if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) {
if ((<VariableStatement>parentNode).declarationList.declarations.length > 0) {
const nameIdentifier = (<VariableStatement>parentNode).declarationList.declarations[0].name;
if (isIdentifier(nameIdentifier)) {
nameFromParentNode = nameIdentifier.escapedText;
}
}
}
return nameFromParentNode;
const name = getNameOfJSDocTypedef(node as JSDocTypedefTag);
return typeof name !== "undefined" ? name.escapedText : undefined;
}
}
@@ -598,7 +589,7 @@ namespace ts {
// Binding of JsDocComment should be done before the current block scope container changes.
// because the scope of JsDocComment should not be affected by whether the current node is a
// container or not.
if (node.jsDoc) {
if (hasJSDocNodes(node)) {
if (isInJavaScriptFile(node)) {
for (const j of node.jsDoc) {
bind(j);
@@ -1931,7 +1922,7 @@ namespace ts {
}
function bindJSDocTypedefTagIfAny(node: Node) {
if (!node.jsDoc) {
if (!hasJSDocNodes(node)) {
return;
}
+6 -3
View File
@@ -19158,6 +19158,8 @@ namespace ts {
switch (d.kind) {
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
// A jsdoc typedef is, by definition, a type alias
case SyntaxKind.JSDocTypedefTag:
return DeclarationSpaces.ExportType;
case SyntaxKind.ModuleDeclaration:
return isAmbientModule(d) || getModuleInstanceState(d) !== ModuleInstanceState.NonInstantiated
@@ -19827,7 +19829,7 @@ namespace ts {
}
}
else if (compilerOptions.noUnusedLocals) {
forEach(local.declarations, d => errorUnusedLocal(getNameOfDeclaration(d) || d, unescapeLeadingUnderscores(local.escapedName)));
forEach(local.declarations, d => errorUnusedLocal(d, unescapeLeadingUnderscores(local.escapedName)));
}
}
});
@@ -19842,7 +19844,8 @@ namespace ts {
return false;
}
function errorUnusedLocal(node: Node, name: string) {
function errorUnusedLocal(declaration: Declaration, name: string) {
const node = getNameOfDeclaration(declaration) || declaration;
if (isIdentifierThatStartsWithUnderScore(node)) {
const declaration = getRootDeclaration(node.parent);
if (declaration.kind === SyntaxKind.VariableDeclaration && isForInOrOfStatement(declaration.parent.parent)) {
@@ -19909,7 +19912,7 @@ namespace ts {
if (!local.isReferenced && !local.exportSymbol) {
for (const declaration of local.declarations) {
if (!isAmbientModule(declaration)) {
errorUnusedLocal(getNameOfDeclaration(declaration), unescapeLeadingUnderscores(local.escapedName));
errorUnusedLocal(declaration, unescapeLeadingUnderscores(local.escapedName));
}
}
}
+5 -1
View File
@@ -2441,7 +2441,7 @@ namespace ts {
}
}
export function fail(message?: string, stackCrawlMark?: Function): void {
export function fail(message?: string, stackCrawlMark?: Function): never {
debugger;
const e = new Error(message ? `Debug Failure. ${message}` : "Debug Failure.");
if ((<any>Error).captureStackTrace) {
@@ -2450,6 +2450,10 @@ namespace ts {
throw e;
}
export function assertNever(member: never, message?: string, stackCrawlMark?: Function): never {
return fail(message || `Illegal value: ${member}`, stackCrawlMark || assertNever);
}
export function getFunctionName(func: Function) {
if (typeof func !== "function") {
return "";
+8 -8
View File
@@ -729,7 +729,7 @@ namespace ts {
}
function addJSDocComment<T extends Node>(node: T): T {
function addJSDocComment<T extends HasJSDoc>(node: T): T {
const comments = getJSDocCommentRanges(node, sourceFile.text);
if (comments) {
for (const comment of comments) {
@@ -768,7 +768,7 @@ namespace ts {
const saveParent = parent;
parent = n;
forEachChild(n, visitNode);
if (n.jsDoc) {
if (hasJSDocNodes(n)) {
for (const jsDoc of n.jsDoc) {
jsDoc.parent = n;
parent = jsDoc;
@@ -2158,7 +2158,7 @@ namespace ts {
const result = <JSDocFunctionType>createNode(SyntaxKind.JSDocFunctionType);
nextToken();
fillSignature(SyntaxKind.ColonToken, SignatureFlags.Type | SignatureFlags.JSDoc, result);
return finishNode(result);
return addJSDocComment(finishNode(result));
}
const node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
node.typeName = parseIdentifierName();
@@ -2365,7 +2365,7 @@ namespace ts {
parseSemicolon();
}
function parseSignatureMember(kind: SyntaxKind): CallSignatureDeclaration | ConstructSignatureDeclaration {
function parseSignatureMember(kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration {
const node = <CallSignatureDeclaration | ConstructSignatureDeclaration>createNode(kind);
if (kind === SyntaxKind.ConstructSignature) {
parseExpected(SyntaxKind.NewKeyword);
@@ -2445,7 +2445,7 @@ namespace ts {
node.parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
node.type = parseTypeAnnotation();
parseTypeMemberSemicolon();
return finishNode(node);
return addJSDocComment(finishNode(node));
}
function parsePropertyOrMethodSignature(fullStart: number, modifiers: NodeArray<Modifier>): PropertySignature | MethodSignature {
@@ -2605,7 +2605,7 @@ namespace ts {
parseExpected(SyntaxKind.NewKeyword);
}
fillSignature(SyntaxKind.EqualsGreaterThanToken, SignatureFlags.Type, node);
return finishNode(node);
return addJSDocComment(finishNode(node));
}
function parseKeywordAndNoDot(): TypeNode | undefined {
@@ -6182,7 +6182,7 @@ namespace ts {
return jsDoc ? { jsDoc, diagnostics } : undefined;
}
export function parseJSDocComment(parent: Node, start: number, length: number): JSDoc {
export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc {
const saveToken = currentToken;
const saveParseDiagnosticsLength = parseDiagnostics.length;
const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
@@ -6997,7 +6997,7 @@ namespace ts {
}
forEachChild(node, visitNode, visitArray);
if (node.jsDoc) {
if (hasJSDocNodes(node)) {
for (const jsDocComment of node.jsDoc) {
forEachChild(jsDocComment, visitNode, visitArray);
}
+92 -51
View File
@@ -516,8 +516,6 @@ namespace ts {
parent?: Node; // Parent node (initialized by binding)
/* @internal */ original?: Node; // The original node if this is an updated node.
/* @internal */ startsOnNewLine?: boolean; // Whether a synthesized node should start on a new line (used by transforms).
/* @internal */ jsDoc?: JSDoc[]; // JSDoc that directly precedes this node
/* @internal */ jsDocCache?: ReadonlyArray<JSDocTag>; // Cache for getJSDocTags
/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
@@ -528,6 +526,44 @@ namespace ts {
/* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type
}
export interface JSDocContainer {
/* @internal */ jsDoc?: JSDoc[]; // JSDoc that directly precedes this node
/* @internal */ jsDocCache?: ReadonlyArray<JSDocTag>; // Cache for getJSDocTags
}
export type HasJSDoc =
| ParameterDeclaration
| CallSignatureDeclaration
| ConstructSignatureDeclaration
| MethodSignature
| PropertySignature
| ArrowFunction
| ParenthesizedExpression
| SpreadAssignment
| ShorthandPropertyAssignment
| PropertyAssignment
| FunctionExpression
| LabeledStatement
| ExpressionStatement
| VariableStatement
| FunctionDeclaration
| ConstructorDeclaration
| MethodDeclaration
| PropertyDeclaration
| AccessorDeclaration
| ClassLikeDeclaration
| InterfaceDeclaration
| TypeAliasDeclaration
| EnumMember
| EnumDeclaration
| ModuleDeclaration
| ImportEqualsDeclaration
| IndexSignatureDeclaration
| FunctionTypeNode
| ConstructorTypeNode
| JSDocFunctionType
| EndOfFileToken;
/* @internal */
export type MutableNodeArray<T extends Node> = NodeArray<T> & T[];
@@ -546,7 +582,7 @@ namespace ts {
export type EqualsToken = Token<SyntaxKind.EqualsToken>;
export type AsteriskToken = Token<SyntaxKind.AsteriskToken>;
export type EqualsGreaterThanToken = Token<SyntaxKind.EqualsGreaterThanToken>;
export type EndOfFileToken = Token<SyntaxKind.EndOfFileToken>;
export type EndOfFileToken = Token<SyntaxKind.EndOfFileToken> & JSDocContainer;
export type AtToken = Token<SyntaxKind.AtToken>;
export type ReadonlyToken = Token<SyntaxKind.ReadonlyKeyword>;
export type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
@@ -651,32 +687,34 @@ namespace ts {
expression?: Expression;
}
export interface SignatureDeclaration extends NamedDeclaration {
kind: SyntaxKind.CallSignature
| SyntaxKind.ConstructSignature
| SyntaxKind.MethodSignature
| SyntaxKind.IndexSignature
| SyntaxKind.FunctionType
| SyntaxKind.ConstructorType
| SyntaxKind.JSDocFunctionType
| SyntaxKind.FunctionDeclaration
| SyntaxKind.MethodDeclaration
| SyntaxKind.Constructor
| SyntaxKind.GetAccessor
| SyntaxKind.SetAccessor
| SyntaxKind.FunctionExpression
| SyntaxKind.ArrowFunction;
export interface SignatureDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SignatureDeclaration["kind"];
name?: PropertyName;
typeParameters?: NodeArray<TypeParameterDeclaration>;
parameters: NodeArray<ParameterDeclaration>;
type: TypeNode | undefined;
}
export interface CallSignatureDeclaration extends SignatureDeclaration, TypeElement {
export type SignatureDeclaration =
| CallSignatureDeclaration
| ConstructSignatureDeclaration
| MethodSignature
| IndexSignatureDeclaration
| FunctionTypeNode
| ConstructorTypeNode
| JSDocFunctionType
| FunctionDeclaration
| MethodDeclaration
| ConstructorDeclaration
| AccessorDeclaration
| FunctionExpression
| ArrowFunction;
export interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.CallSignature;
}
export interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement {
export interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.ConstructSignature;
}
@@ -696,7 +734,7 @@ namespace ts {
declarations: NodeArray<VariableDeclaration>;
}
export interface ParameterDeclaration extends NamedDeclaration {
export interface ParameterDeclaration extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.Parameter;
parent?: SignatureDeclaration;
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
@@ -715,7 +753,7 @@ namespace ts {
initializer?: Expression; // Optional initializer
}
export interface PropertySignature extends TypeElement {
export interface PropertySignature extends TypeElement, JSDocContainer {
kind: SyntaxKind.PropertySignature;
name: PropertyName; // Declared property name
questionToken?: QuestionToken; // Present on optional property
@@ -723,7 +761,7 @@ namespace ts {
initializer?: Expression; // Optional initializer
}
export interface PropertyDeclaration extends ClassElement {
export interface PropertyDeclaration extends ClassElement, JSDocContainer {
kind: SyntaxKind.PropertyDeclaration;
questionToken?: QuestionToken; // Present for use with reporting a grammar error
name: PropertyName;
@@ -744,7 +782,7 @@ namespace ts {
| AccessorDeclaration
;
export interface PropertyAssignment extends ObjectLiteralElement {
export interface PropertyAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.PropertyAssignment;
name: PropertyName;
@@ -752,7 +790,7 @@ namespace ts {
initializer: Expression;
}
export interface ShorthandPropertyAssignment extends ObjectLiteralElement {
export interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.ShorthandPropertyAssignment;
name: Identifier;
@@ -763,7 +801,7 @@ namespace ts {
objectAssignmentInitializer?: Expression;
}
export interface SpreadAssignment extends ObjectLiteralElement {
export interface SpreadAssignment extends ObjectLiteralElement, JSDocContainer {
parent: ObjectLiteralExpression;
kind: SyntaxKind.SpreadAssignment;
expression: Expression;
@@ -816,7 +854,7 @@ namespace ts {
* - MethodDeclaration
* - AccessorDeclaration
*/
export interface FunctionLikeDeclarationBase extends SignatureDeclaration {
export interface FunctionLikeDeclarationBase extends SignatureDeclarationBase {
_functionLikeDeclarationBrand: any;
asteriskToken?: AsteriskToken;
@@ -847,7 +885,7 @@ namespace ts {
body?: FunctionBody;
}
export interface MethodSignature extends SignatureDeclaration, TypeElement {
export interface MethodSignature extends SignatureDeclarationBase, TypeElement {
kind: SyntaxKind.MethodSignature;
name: PropertyName;
}
@@ -861,13 +899,13 @@ namespace ts {
// Because of this, it may be necessary to determine what sort of MethodDeclaration you have
// at later stages of the compiler pipeline. In that case, you can either check the parent kind
// of the method, or use helpers like isObjectLiteralMethodDeclaration
export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.MethodDeclaration;
name: PropertyName;
body?: FunctionBody;
}
export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement {
export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer {
kind: SyntaxKind.Constructor;
parent?: ClassDeclaration | ClassExpression;
body?: FunctionBody;
@@ -881,7 +919,7 @@ namespace ts {
// See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a
// ClassElement and an ObjectLiteralElement.
export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.GetAccessor;
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
name: PropertyName;
@@ -890,7 +928,7 @@ namespace ts {
// See the comment on MethodDeclaration for the intuition behind SetAccessorDeclaration being a
// ClassElement and an ObjectLiteralElement.
export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement {
export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer {
kind: SyntaxKind.SetAccessor;
parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression;
name: PropertyName;
@@ -899,7 +937,7 @@ namespace ts {
export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration;
export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement, TypeElement {
export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement {
kind: SyntaxKind.IndexSignature;
parent?: ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeLiteralNode;
}
@@ -928,11 +966,11 @@ namespace ts {
export type FunctionOrConstructorTypeNode = FunctionTypeNode | ConstructorTypeNode;
export interface FunctionTypeNode extends TypeNode, SignatureDeclaration {
export interface FunctionTypeNode extends TypeNode, SignatureDeclarationBase {
kind: SyntaxKind.FunctionType;
}
export interface ConstructorTypeNode extends TypeNode, SignatureDeclaration {
export interface ConstructorTypeNode extends TypeNode, SignatureDeclarationBase {
kind: SyntaxKind.ConstructorType;
}
@@ -1355,13 +1393,13 @@ namespace ts {
export type FunctionBody = Block;
export type ConciseBody = FunctionBody | Expression;
export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase {
export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer {
kind: SyntaxKind.FunctionExpression;
name?: Identifier;
body: FunctionBody; // Required, whereas the member inherited from FunctionDeclaration is optional
}
export interface ArrowFunction extends Expression, FunctionLikeDeclarationBase {
export interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer {
kind: SyntaxKind.ArrowFunction;
equalsGreaterThanToken: EqualsGreaterThanToken;
body: ConciseBody;
@@ -1440,7 +1478,7 @@ namespace ts {
literal: TemplateMiddle | TemplateTail;
}
export interface ParenthesizedExpression extends PrimaryExpression {
export interface ParenthesizedExpression extends PrimaryExpression, JSDocContainer {
kind: SyntaxKind.ParenthesizedExpression;
expression: Expression;
}
@@ -1696,12 +1734,12 @@ namespace ts {
/*@internal*/ multiLine?: boolean;
}
export interface VariableStatement extends Statement {
export interface VariableStatement extends Statement, JSDocContainer {
kind: SyntaxKind.VariableStatement;
declarationList: VariableDeclarationList;
}
export interface ExpressionStatement extends Statement {
export interface ExpressionStatement extends Statement, JSDocContainer {
kind: SyntaxKind.ExpressionStatement;
expression: Expression;
}
@@ -1807,7 +1845,7 @@ namespace ts {
export type CaseOrDefaultClause = CaseClause | DefaultClause;
export interface LabeledStatement extends Statement {
export interface LabeledStatement extends Statement, JSDocContainer {
kind: SyntaxKind.LabeledStatement;
label: Identifier;
statement: Statement;
@@ -1834,7 +1872,7 @@ namespace ts {
export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag;
export interface ClassLikeDeclaration extends NamedDeclaration {
export interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
name?: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
@@ -1842,15 +1880,17 @@ namespace ts {
members: NodeArray<ClassElement>;
}
export interface ClassDeclaration extends ClassLikeDeclaration, DeclarationStatement {
export interface ClassDeclaration extends ClassLikeDeclarationBase, DeclarationStatement {
kind: SyntaxKind.ClassDeclaration;
name?: Identifier;
}
export interface ClassExpression extends ClassLikeDeclaration, PrimaryExpression {
export interface ClassExpression extends ClassLikeDeclarationBase, PrimaryExpression {
kind: SyntaxKind.ClassExpression;
}
export type ClassLikeDeclaration = ClassDeclaration | ClassExpression;
export interface ClassElement extends NamedDeclaration {
_classElementBrand: any;
name?: PropertyName;
@@ -1862,7 +1902,7 @@ namespace ts {
questionToken?: QuestionToken;
}
export interface InterfaceDeclaration extends DeclarationStatement {
export interface InterfaceDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.InterfaceDeclaration;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
@@ -1877,14 +1917,14 @@ namespace ts {
types: NodeArray<ExpressionWithTypeArguments>;
}
export interface TypeAliasDeclaration extends DeclarationStatement {
export interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.TypeAliasDeclaration;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
type: TypeNode;
}
export interface EnumMember extends NamedDeclaration {
export interface EnumMember extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.EnumMember;
parent?: EnumDeclaration;
// This does include ComputedPropertyName, but the parser will give an error
@@ -1893,7 +1933,7 @@ namespace ts {
initializer?: Expression;
}
export interface EnumDeclaration extends DeclarationStatement {
export interface EnumDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.EnumDeclaration;
name: Identifier;
members: NodeArray<EnumMember>;
@@ -1903,7 +1943,7 @@ namespace ts {
export type ModuleBody = NamespaceBody | JSDocNamespaceBody;
export interface ModuleDeclaration extends DeclarationStatement {
export interface ModuleDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ModuleDeclaration;
parent?: ModuleBody | SourceFile;
name: ModuleName;
@@ -1937,7 +1977,7 @@ namespace ts {
* - import x = require("mod");
* - import x = M.x;
*/
export interface ImportEqualsDeclaration extends DeclarationStatement {
export interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer {
kind: SyntaxKind.ImportEqualsDeclaration;
parent?: SourceFile | ModuleBlock;
name: Identifier;
@@ -2090,7 +2130,7 @@ namespace ts {
type: TypeNode;
}
export interface JSDocFunctionType extends JSDocType, SignatureDeclaration {
export interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase {
kind: SyntaxKind.JSDocFunctionType;
}
@@ -2103,6 +2143,7 @@ namespace ts {
export interface JSDoc extends Node {
kind: SyntaxKind.JSDocComment;
parent?: HasJSDoc;
tags: NodeArray<JSDocTag> | undefined;
comment: string | undefined;
}
+76 -6
View File
@@ -277,7 +277,7 @@ namespace ts {
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
}
if (includeJsDoc && node.jsDoc && node.jsDoc.length > 0) {
if (includeJsDoc && hasJSDocNodes(node)) {
return getTokenPosOfNode(node.jsDoc[0]);
}
@@ -1510,10 +1510,10 @@ namespace ts {
}
export function getJSDocTags(node: Node): ReadonlyArray<JSDocTag> | undefined {
let tags = node.jsDocCache;
let tags = (node as JSDocContainer).jsDocCache;
// If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing.
if (tags === undefined) {
node.jsDocCache = tags = flatMap(getJSDocCommentsAndTags(node), j => isJSDoc(j) ? j.tags : j);
(node as JSDocContainer).jsDocCache = tags = flatMap(getJSDocCommentsAndTags(node), j => isJSDoc(j) ? j.tags : j);
}
return tags;
}
@@ -1567,11 +1567,13 @@ namespace ts {
result = addRange(result, getJSDocParameterTags(node as ParameterDeclaration));
}
if (isVariableLike(node) && node.initializer) {
if (isVariableLike(node) && node.initializer && hasJSDocNodes(node.initializer)) {
result = addRange(result, node.initializer.jsDoc);
}
result = addRange(result, node.jsDoc);
if (hasJSDocNodes(node)) {
result = addRange(result, node.jsDoc);
}
}
}
@@ -3958,7 +3960,66 @@ namespace ts {
return id;
}
export function getNameOfDeclaration(declaration: Declaration): DeclarationName | undefined {
/**
* A JSDocTypedef tag has an _optional_ name field - if a name is not directly present, we should
* attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol
* will be merged with)
*/
function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined {
const hostNode = declaration.parent.parent;
if (!hostNode) {
return undefined;
}
// Covers classes, functions - any named declaration host node
if (isDeclaration(hostNode)) {
return getDeclarationIdentifier(hostNode);
}
// Covers remaining cases
switch (hostNode.kind) {
case SyntaxKind.VariableStatement:
if ((hostNode as VariableStatement).declarationList &&
(hostNode as VariableStatement).declarationList.declarations[0]) {
return getDeclarationIdentifier((hostNode as VariableStatement).declarationList.declarations[0]);
}
return undefined;
case SyntaxKind.ExpressionStatement:
const expr = (hostNode as ExpressionStatement).expression;
switch (expr.kind) {
case SyntaxKind.PropertyAccessExpression:
return (expr as PropertyAccessExpression).name;
case SyntaxKind.ElementAccessExpression:
const arg = (expr as ElementAccessExpression).argumentExpression;
if (isIdentifier(arg)) {
return arg;
}
}
return undefined;
case SyntaxKind.EndOfFileToken:
return undefined;
case SyntaxKind.ParenthesizedExpression: {
return getDeclarationIdentifier(hostNode.expression);
}
case SyntaxKind.LabeledStatement: {
if (isDeclaration(hostNode.statement) || isExpression(hostNode.statement)) {
return getDeclarationIdentifier(hostNode.statement);
}
return undefined;
}
default:
Debug.assertNever(hostNode, "Found typedef tag attached to node which it should not be!");
}
}
function getDeclarationIdentifier(node: Declaration | Expression) {
const name = getNameOfDeclaration(node);
return isIdentifier(name) ? name : undefined;
}
export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined {
return declaration.name || nameForNamelessJSDocTypedef(declaration as JSDocTypedefTag);
}
export function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined {
if (!declaration) {
return undefined;
}
@@ -3977,6 +4038,9 @@ namespace ts {
return undefined;
}
}
else if (declaration.kind === SyntaxKind.JSDocTypedefTag) {
return getNameOfJSDocTypedef(declaration as JSDocTypedefTag);
}
else {
return (declaration as NamedDeclaration).name;
}
@@ -5365,4 +5429,10 @@ namespace ts {
export function isJSDocTag(node: Node): boolean {
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
}
/** True if has jsdoc nodes attached to it. */
/* @internal */
export function hasJSDocNodes(node: Node): node is HasJSDoc {
return !!(node as JSDocContainer).jsDoc && (node as JSDocContainer).jsDoc.length > 0;
}
}
+2 -1
View File
@@ -699,7 +699,8 @@ namespace ts {
// specially.
const docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width);
if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDoc) {
docCommentAndDiagnostics.jsDoc.parent = token;
// TODO: This should be predicated on `token["kind"]` being compatible with `HasJSDoc["kind"]`
docCommentAndDiagnostics.jsDoc.parent = token as HasJSDoc;
classifyJSDocComment(docCommentAndDiagnostics.jsDoc);
return;
}
+1 -1
View File
@@ -1739,7 +1739,7 @@ namespace ts.Completions {
/** Get the corresponding JSDocTag node if the position is in a jsDoc comment */
function getJsDocTagAtPosition(node: Node, position: number): JSDocTag | undefined {
const { jsDoc } = getJsDocHavingNode(node);
const { jsDoc } = getJsDocHavingNode(node) as JSDocContainer;
if (!jsDoc) return undefined;
for (const { pos, end, tags } of jsDoc) {
+8 -6
View File
@@ -263,13 +263,15 @@ namespace ts.NavigationBar {
break;
default:
forEach(node.jsDoc, jsDoc => {
forEach(jsDoc.tags, tag => {
if (tag.kind === SyntaxKind.JSDocTypedefTag) {
addLeafNode(tag);
}
if (hasJSDocNodes(node)) {
forEach(node.jsDoc, jsDoc => {
forEach(jsDoc.tags, tag => {
if (tag.kind === SyntaxKind.JSDocTypedefTag) {
addLeafNode(tag);
}
});
});
});
}
forEachChild(node, addChildrenRecursively);
}
+1 -1
View File
@@ -2111,7 +2111,7 @@ namespace ts {
}
forEachChild(node, walk);
if (node.jsDoc) {
if (hasJSDocNodes(node)) {
for (const jsDoc of node.jsDoc) {
forEachChild(jsDoc, walk);
}
@@ -0,0 +1,13 @@
//// [export.js]
/**
* @typedef {{
* }}
*/
export const foo = 5;
//// [export.js]
/**
* @typedef {{
* }}
*/
export const foo = 5;
@@ -0,0 +1,8 @@
=== tests/cases/compiler/export.js ===
/**
* @typedef {{
* }}
*/
export const foo = 5;
>foo : Symbol(foo, Decl(export.js, 4, 12))
@@ -0,0 +1,9 @@
=== tests/cases/compiler/export.js ===
/**
* @typedef {{
* }}
*/
export const foo = 5;
>foo : 5
>5 : 5
@@ -0,0 +1,12 @@
tests/cases/compiler/export.js(1,13): error TS8008: 'type aliases' can only be used in a .ts file.
==== tests/cases/compiler/export.js (1 errors) ====
export type foo = 5;
~~~
!!! error TS8008: 'type aliases' can only be used in a .ts file.
/**
* @typedef {{
* }}
*/
export const foo = 5;
@@ -0,0 +1,14 @@
//// [export.js]
export type foo = 5;
/**
* @typedef {{
* }}
*/
export const foo = 5;
//// [export.js]
/**
* @typedef {{
* }}
*/
export const foo = 5;
@@ -0,0 +1,9 @@
// @target: es6
// @allowJs: true
// @outDir: ./dist
// @filename: export.js
/**
* @typedef {{
* }}
*/
export const foo = 5;
@@ -0,0 +1,11 @@
// @target: es6
// @allowJs: true
// @outDir: ./dist
// @filename: export.js
export type foo = 5;
/**
* @typedef {{
* }}
*/
export const foo = 5;