Skip to content

Commit e81cfa1

Browse files
committed
Clean cache code and streamline other code
Cache only uses one property now. getJSDocs isn't generic and doesn't take a function parameter any more. The code is overall easier to read.
1 parent ddffe20 commit e81cfa1

2 files changed

Lines changed: 36 additions & 48 deletions

File tree

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ namespace ts {
498498
/* @internal */ original?: Node; // The original node if this is an updated node.
499499
/* @internal */ startsOnNewLine?: boolean; // Whether a synthesized node should start on a new line (used by transforms).
500500
/* @internal */ jsDocComments?: JSDoc[]; // JSDoc for the node, if it has any.
501+
/* @internal */ jsDocCache?: (JSDoc | JSDocParameterTag)[]; // JSDoc for the node, plus JSDoc retrieved from its parents
501502
/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
502503
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
503504
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)

src/compiler/utilities.ts

Lines changed: 35 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,49 +1416,42 @@ namespace ts {
14161416
(<JSDocFunctionType>node).parameters[0].type.kind === SyntaxKind.JSDocConstructorType;
14171417
}
14181418

1419-
function getJSDocTag(node: Node, kind: SyntaxKind): JSDocTag {
1420-
if (!node) {
1421-
return undefined;
1422-
}
1423-
1424-
const jsDocTags = getJSDocTags(node);
1425-
if (!jsDocTags) {
1426-
return undefined;
1427-
}
1428-
1429-
for (const tag of jsDocTags) {
1430-
if (tag.kind === kind) {
1431-
return tag;
1432-
}
1433-
}
1434-
}
1435-
14361419
export function getJSDocComments(node: Node): string[] {
1437-
return getJSDocs(node, docs => map(docs, doc => doc.comment), tags => map(tags, tag => tag.comment));
1420+
return map(getJSDocs(node), doc => doc.comment);
14381421
}
14391422

1440-
function getJSDocTags(node: Node): JSDocTag[] {
1441-
return getJSDocs(node, docs => {
1423+
function getJSDocTags(node: Node, kind: SyntaxKind): JSDocTag[] {
1424+
const docs = getJSDocs(node);
1425+
if (docs) {
14421426
const result: JSDocTag[] = [];
14431427
for (const doc of docs) {
1444-
if (doc.tags) {
1445-
result.push(...doc.tags);
1428+
if (doc.kind === SyntaxKind.JSDocParameterTag) {
1429+
if (doc.kind === kind) {
1430+
result.push(doc as JSDocParameterTag);
1431+
}
1432+
}
1433+
else {
1434+
result.push(...filter((doc as JSDoc).tags, tag => tag.kind === kind));
14461435
}
14471436
}
14481437
return result;
1449-
}, tags => tags);
1438+
}
1439+
}
1440+
1441+
function getFirstJSDocTag(node: Node, kind: SyntaxKind): JSDocTag {
1442+
return node && firstOrUndefined(getJSDocTags(node, kind));
14501443
}
14511444

1452-
function getJSDocs<T>(node: Node, getContent: (docs: JSDoc[]) => T[], getContentFromParam: (tags: JSDocTag[]) => T[]): T[] {
1453-
return getJSDocsWorker(node);
1445+
function getJSDocs(node: Node): (JSDoc | JSDocParameterTag)[] {
1446+
let cache: (JSDoc | JSDocParameterTag)[] = node.jsDocCache;
1447+
if (!cache) {
1448+
getJSDocsWorker(node);
1449+
node.jsDocCache = cache;
1450+
}
1451+
return cache;
14541452

14551453
function getJSDocsWorker(node: Node) {
1456-
// TODO: A lot of this work should be cached, maybe. I guess it's only used in services right now...
1457-
// This will be hard because it may need to cache parentvariable versions and nonparent versions
1458-
// maybe I should eliminate checkParent first ...
14591454
const parent = node.parent;
1460-
let result: T[] = undefined;
1461-
14621455
// Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement.
14631456
// /**
14641457
// * @param {number} name
@@ -1476,7 +1469,7 @@ namespace ts {
14761469
isVariableOfVariableDeclarationStatement ? parent.parent :
14771470
undefined;
14781471
if (variableStatementNode) {
1479-
result = concatenate(result, getJSDocsWorker(variableStatementNode));
1472+
getJSDocsWorker(variableStatementNode);
14801473
}
14811474

14821475
// Also recognize when the node is the RHS of an assignment expression
@@ -1486,32 +1479,26 @@ namespace ts {
14861479
(parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken &&
14871480
parent.parent.kind === SyntaxKind.ExpressionStatement;
14881481
if (isSourceOfAssignmentExpressionStatement) {
1489-
result = concatenate(result, getJSDocsWorker(parent.parent));
1482+
getJSDocsWorker(parent.parent);
14901483
}
14911484

14921485
const isModuleDeclaration = node.kind === SyntaxKind.ModuleDeclaration &&
14931486
parent && parent.kind === SyntaxKind.ModuleDeclaration;
14941487
const isPropertyAssignmentExpression = parent && parent.kind === SyntaxKind.PropertyAssignment;
14951488
if (isModuleDeclaration || isPropertyAssignmentExpression) {
1496-
result = concatenate(result, getJSDocsWorker(parent));
1489+
getJSDocsWorker(parent);
14971490
}
14981491

14991492
// Pull parameter comments from declaring function as well
15001493
if (node.kind === SyntaxKind.Parameter) {
1501-
result = concatenate(result, getContentFromParam(getJSDocParameterTag(node)));
1494+
cache = concatenate(cache, getJSDocParameterTag(node));
15021495
}
15031496

15041497
if (isVariableLike(node) && node.initializer) {
1505-
result = concatenate(result, getOwnJSDocs(node.initializer));
1498+
cache = concatenate(cache, node.initializer.jsDocComments);
15061499
}
15071500

1508-
return concatenate(result, getOwnJSDocs(node));
1509-
}
1510-
1511-
function getOwnJSDocs(node: Node) {
1512-
if (node.jsDocComments) {
1513-
return getContent(node.jsDocComments);
1514-
}
1501+
cache = concatenate(cache, node.jsDocComments);
15151502
}
15161503
}
15171504

@@ -1520,18 +1507,18 @@ namespace ts {
15201507
return undefined;
15211508
}
15221509
const func = param.parent as FunctionLikeDeclaration;
1523-
const tags = getJSDocTags(func);
1510+
const tags = getJSDocTags(func, SyntaxKind.JSDocParameterTag) as JSDocParameterTag[];
15241511
if (!param.name) {
15251512
// this is an anonymous jsdoc param from a `function(type1, type2): type3` specification
15261513
const i = func.parameters.indexOf(param);
1527-
const paramTags = filter(tags, tag => tag.kind === SyntaxKind.JSDocParameterTag) as JSDocParameterTag[];
1514+
const paramTags = filter(tags, tag => tag.kind === SyntaxKind.JSDocParameterTag);
15281515
if (paramTags && 0 <= i && i < paramTags.length) {
15291516
return [paramTags[i]];
15301517
}
15311518
}
15321519
else if (param.name.kind === SyntaxKind.Identifier) {
15331520
const name = (param.name as Identifier).text;
1534-
return filter(tags as JSDocParameterTag[], tag => tag.kind === SyntaxKind.JSDocParameterTag && tag.parameterName.text === name);
1521+
return filter(tags, tag => tag.kind === SyntaxKind.JSDocParameterTag && tag.parameterName.text === name);
15351522
}
15361523
else {
15371524
// TODO: it's a destructured parameter, so it should look up an "object type" series of multiple lines
@@ -1541,7 +1528,7 @@ namespace ts {
15411528
}
15421529

15431530
export function getJSDocType(node: Node): JSDocType {
1544-
let tag: JSDocTypeTag | JSDocParameterTag = getJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag;
1531+
let tag: JSDocTypeTag | JSDocParameterTag = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag;
15451532
if (!tag && node.kind === SyntaxKind.Parameter) {
15461533
const paramTags = getJSDocParameterTag(node);
15471534
if (paramTags) {
@@ -1553,11 +1540,11 @@ namespace ts {
15531540
}
15541541

15551542
export function getJSDocReturnTag(node: Node): JSDocReturnTag {
1556-
return getJSDocTag(node, SyntaxKind.JSDocReturnTag) as JSDocReturnTag;
1543+
return getFirstJSDocTag(node, SyntaxKind.JSDocReturnTag) as JSDocReturnTag;
15571544
}
15581545

15591546
export function getJSDocTemplateTag(node: Node): JSDocTemplateTag {
1560-
return getJSDocTag(node, SyntaxKind.JSDocTemplateTag) as JSDocTemplateTag;
1547+
return getFirstJSDocTag(node, SyntaxKind.JSDocTemplateTag) as JSDocTemplateTag;
15611548
}
15621549

15631550
export function hasRestParameter(s: SignatureDeclaration): boolean {

0 commit comments

Comments
 (0)