More removal of getNodeId uses.

This commit is contained in:
Daniel Rosenwasser 2021-11-06 07:59:41 +00:00 committed by GitHub
parent e83d14434d
commit 044de3ec63
11 changed files with 94 additions and 90 deletions

View file

@ -277,12 +277,23 @@ namespace ts {
this.flags = 0;
}
const idCache = new Map<Node, number>();
export function getNodeId(node: Node): number {
if (!node.id) {
node.id = nextNodeId;
let result = idCache.get(node);
if (!result) {
result = nextNodeId;
idCache.set(node, result);
nextNodeId++;
}
return node.id;
return result;
}
export function getNodeIdOrDefault(node: Node): number {
return idCache.get(node) || 0;
}
export function setNodeIdForStrangeRedirect(node: Node, id: number): void {
idCache.set(node, id);
}
export function getSymbolId(symbol: Symbol): SymbolId {
@ -974,7 +985,7 @@ namespace ts {
const maximumSuggestionCount = 10;
const mergedSymbols: Symbol[] = [];
const symbolLinks: SymbolLinks[] = [];
const nodeLinks: ESMap<Node, NodeLinks> = new Map();
const nodeLinks = new Map<Node, NodeLinks>();
const flowLoopCaches: ESMap<string, Type>[] = [];
const flowLoopNodes: FlowNode[] = [];
const flowLoopKeys: string[] = [];
@ -40319,7 +40330,7 @@ namespace ts {
const enclosingFile = getSourceFileOfNode(node);
const links = getNodeLinks(enclosingFile);
if (!(links.flags & NodeCheckFlags.TypeChecked)) {
links.deferredNodes = links.deferredNodes || new Set();
links.deferredNodes ||= new Set();
links.deferredNodes.add(node);
}
}
@ -41601,6 +41612,9 @@ namespace ts {
}
function getNodeCheckFlags(node: Node): NodeCheckFlags {
// TODO: probably not meaningful, right?
// const nodeId = getNodeIdOrDefault(node);
// if (nodeId < 0 || nodeId >= nodeLinks.length) return 0;
return nodeLinks.get(node)?.flags || 0;
}

View file

@ -5339,7 +5339,7 @@ namespace ts {
}
function flattenCommaElements(node: Expression): Expression | readonly Expression[] {
if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) {
if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !getNodeIdOrDefault(node)) {
if (isCommaListExpression(node)) {
return node.elements;
}

View file

@ -2593,8 +2593,8 @@ namespace ts {
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
Object.defineProperties(redirect, {
id: {
get(this: SourceFile) { return this.redirectInfo!.redirectTarget.id; },
set(this: SourceFile, value: SourceFile["id"]) { this.redirectInfo!.redirectTarget.id = value; },
get(this: SourceFile) { return getNodeIdOrDefault(this.redirectInfo!.redirectTarget); },
set(this: SourceFile, value: number) { setNodeIdForStrangeRedirect(this.redirectInfo!.redirectTarget, value); },
},
symbol: {
get(this: SourceFile) { return this.redirectInfo!.redirectTarget.symbol; },

View file

@ -147,7 +147,7 @@ namespace ts {
let enabledSubstitutions: ClassPropertySubstitutionFlags;
let classAliases: Identifier[];
let classAliases: ESMap<Node, Identifier>;
/**
* Tracks what computed name expressions originating from elided names must be inlined
@ -162,7 +162,7 @@ namespace ts {
let pendingStatements: Statement[] | undefined;
const classLexicalEnvironmentStack: (ClassLexicalEnvironment | undefined)[] = [];
const classLexicalEnvironmentMap = new Map<number, ClassLexicalEnvironment>();
const classLexicalEnvironmentMap = new WeakMap<Node, ClassLexicalEnvironment>();
let currentClassLexicalEnvironment: ClassLexicalEnvironment | undefined;
let currentComputedPropertyNameClassLexicalEnvironment: ClassLexicalEnvironment | undefined;
let currentStaticPropertyDeclarationOrStaticBlock: PropertyDeclaration | ClassStaticBlockDeclaration | undefined;
@ -738,7 +738,7 @@ namespace ts {
function transformClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration) {
if (shouldTransformPrivateElementsOrClassStaticBlocks) {
if (currentClassLexicalEnvironment) {
classLexicalEnvironmentMap.set(getOriginalNodeId(node), currentClassLexicalEnvironment);
classLexicalEnvironmentMap.set(getOriginalNode(node), currentClassLexicalEnvironment);
}
startLexicalEnvironment();
@ -1128,7 +1128,7 @@ namespace ts {
enableSubstitutionForClassAliases();
const alias = factory.cloneNode(temp) as GeneratedIdentifier;
alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes;
classAliases[getOriginalNodeId(node)] = alias;
classAliases.set(getOriginalNode(node), alias);
}
// To preserve the behavior of the old emitter, we explicitly indent
@ -1375,7 +1375,7 @@ namespace ts {
// capture the lexical environment for the member
setOriginalNode(transformed, property);
addEmitFlags(transformed, EmitFlags.AdviseOnEmitNode);
classLexicalEnvironmentMap.set(getOriginalNodeId(transformed), currentClassLexicalEnvironment);
classLexicalEnvironmentMap.set(getOriginalNode(transformed), currentClassLexicalEnvironment);
}
currentStaticPropertyDeclarationOrStaticBlock = savedCurrentStaticPropertyDeclarationOrStaticBlock;
return transformed;
@ -1453,7 +1453,7 @@ namespace ts {
context.enableSubstitution(SyntaxKind.Identifier);
// Keep track of class aliases.
classAliases = [];
classAliases = new Map<Node, Identifier>();
}
}
@ -1516,18 +1516,16 @@ namespace ts {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
const original = getOriginalNode(node);
if (original.id) {
const classLexicalEnvironment = classLexicalEnvironmentMap.get(original.id);
if (classLexicalEnvironment) {
const savedClassLexicalEnvironment = currentClassLexicalEnvironment;
const savedCurrentComputedPropertyNameClassLexicalEnvironment = currentComputedPropertyNameClassLexicalEnvironment;
currentClassLexicalEnvironment = classLexicalEnvironment;
currentComputedPropertyNameClassLexicalEnvironment = classLexicalEnvironment;
previousOnEmitNode(hint, node, emitCallback);
currentClassLexicalEnvironment = savedClassLexicalEnvironment;
currentComputedPropertyNameClassLexicalEnvironment = savedCurrentComputedPropertyNameClassLexicalEnvironment;
return;
}
const classLexicalEnvironment = classLexicalEnvironmentMap.get(original);
if (classLexicalEnvironment) {
const savedClassLexicalEnvironment = currentClassLexicalEnvironment;
const savedCurrentComputedPropertyNameClassLexicalEnvironment = currentComputedPropertyNameClassLexicalEnvironment;
currentClassLexicalEnvironment = classLexicalEnvironment;
currentComputedPropertyNameClassLexicalEnvironment = classLexicalEnvironment;
previousOnEmitNode(hint, node, emitCallback);
currentClassLexicalEnvironment = savedClassLexicalEnvironment;
currentComputedPropertyNameClassLexicalEnvironment = savedCurrentComputedPropertyNameClassLexicalEnvironment;
return;
}
switch (node.kind) {
@ -1633,7 +1631,7 @@ namespace ts {
// constructor references in static property initializers.
const declaration = resolver.getReferencedValueDeclaration(node);
if (declaration) {
const classAlias = classAliases[declaration.id!]; // TODO: GH#18217
const classAlias = classAliases.get(declaration);
if (classAlias) {
const clone = factory.cloneNode(classAlias);
setSourceMapRange(clone, node);

View file

@ -11,14 +11,14 @@ namespace ts {
// enable emit notification only if using --jsx preserve or react-native
let previousOnEmitNode: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
let noSubstitution: boolean[];
let noSubstitution: Set<Node>;
if (compilerOptions.jsx === JsxEmit.Preserve || compilerOptions.jsx === JsxEmit.ReactNative) {
previousOnEmitNode = context.onEmitNode;
context.onEmitNode = onEmitNode;
context.enableEmitNotification(SyntaxKind.JsxOpeningElement);
context.enableEmitNotification(SyntaxKind.JsxClosingElement);
context.enableEmitNotification(SyntaxKind.JsxSelfClosingElement);
noSubstitution = [];
noSubstitution = new Set<Node>();
}
const previousOnSubstituteNode = context.onSubstituteNode;
@ -49,7 +49,7 @@ namespace ts {
case SyntaxKind.JsxClosingElement:
case SyntaxKind.JsxSelfClosingElement:
const tagName = (node as JsxOpeningElement | JsxClosingElement | JsxSelfClosingElement).tagName;
noSubstitution[getOriginalNodeId(tagName)] = true;
noSubstitution.add(getOriginalNode(tagName));
break;
}
@ -63,7 +63,8 @@ namespace ts {
* @param node The node to substitute.
*/
function onSubstituteNode(hint: EmitHint, node: Node) {
if (node.id && noSubstitution && noSubstitution[node.id]) {
// TODO: do we need to check for a Node ID here?
if (getNodeIdOrDefault(node) && noSubstitution?.has(node)) {
return previousOnSubstituteNode(hint, node);
}

View file

@ -45,7 +45,7 @@ namespace ts {
let currentSourceFile: SourceFile; // The current file.
let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file.
const noSubstitution: boolean[] = []; // Set of nodes for which substitution rules should be ignored.
const noSubstitution = new Set<Node>(); // Set of nodes for which substitution rules should be ignored.
let needUMDDynamicImportHelper: boolean;
return chainBundle(context, transformSourceFile);
@ -692,13 +692,13 @@ namespace ts {
}
for (const exportName of exportedNames) {
noSubstitution[getNodeId(expression)] = true;
noSubstitution.add(expression);
expression = createExportExpression(exportName, expression);
setTextRange(expression, node);
}
if (temp) {
noSubstitution[getNodeId(expression)] = true;
noSubstitution.add(expression);;
expression = factory.createComma(expression, temp);
setTextRange(expression, node);
}
@ -1794,7 +1794,7 @@ namespace ts {
*/
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (node.id && noSubstitution[node.id]) {
if (noSubstitution.has(node)) {
return node;
}
@ -1852,7 +1852,7 @@ namespace ts {
function substituteCallExpression(node: CallExpression) {
if (isIdentifier(node.expression)) {
const expression = substituteExpressionIdentifier(node.expression);
noSubstitution[getNodeId(expression)] = true;
noSubstitution.add(expression);;
if (!isIdentifier(expression)) {
return addEmitFlags(
factory.updateCallExpression(node,
@ -1871,7 +1871,7 @@ namespace ts {
function substituteTaggedTemplateExpression(node: TaggedTemplateExpression) {
if (isIdentifier(node.tag)) {
const tag = substituteExpressionIdentifier(node.tag);
noSubstitution[getNodeId(tag)] = true;
noSubstitution.add(tag);
if (!isIdentifier(tag)) {
return addEmitFlags(
factory.updateTaggedTemplateExpression(node,
@ -1962,7 +1962,7 @@ namespace ts {
let expression: Expression = node;
for (const exportName of exportedNames) {
// Mark the node to prevent triggering this rule again.
noSubstitution[getNodeId(expression)] = true;
noSubstitution.add(expression);;
expression = createExportExpression(exportName, expression, /*location*/ node);
}

View file

@ -26,11 +26,11 @@ namespace ts {
context.enableSubstitution(SyntaxKind.MetaProperty); // Substitutes 'import.meta'
context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file.
const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file.
const deferredExports: (Statement[] | undefined)[] = []; // Exports to defer until an EndOfDeclarationMarker is found.
const exportFunctionsMap: Identifier[] = []; // The export function associated with a source file.
const noSubstitutionMap: boolean[][] = []; // Set of nodes for which substitution rules should be ignored for each file.
const contextObjectMap: Identifier[] = []; // The context object associated with a source file.
const moduleInfoMap = new Map<Node, ExternalModuleInfo>(); // The ExternalModuleInfo for each file.
const deferredExports = new Map<Node, (Statement[] | undefined)>(); // Exports to defer until an EndOfDeclarationMarker is found.
const exportFunctionsMap = new Map<Node, Identifier>(); // The export function associated with a source file.
const noSubstitutionMap = new Map<Node, Set<Node>>(); // Set of nodes for which substitution rules should be ignored for each file.
const contextObjectMap = new Map<Node, Identifier>(); // The context object associated with a source file.
let currentSourceFile: SourceFile; // The current file.
let moduleInfo: ExternalModuleInfo; // ExternalModuleInfo for the current file.
@ -38,7 +38,7 @@ namespace ts {
let contextObject: Identifier; // The context object for the current file.
let hoistedStatements: Statement[] | undefined;
let enclosingBlockScopedContainer: Node;
let noSubstitution: boolean[] | undefined; // Set of nodes for which substitution rules should be ignored.
let noSubstitution: Set<Node> | undefined; // Set of nodes for which substitution rules should be ignored.
return chainBundle(context, transformSourceFile);
@ -52,7 +52,7 @@ namespace ts {
return node;
}
const id = getOriginalNodeId(node);
const originalNode = getOriginalNode(node);
currentSourceFile = node;
enclosingBlockScopedContainer = node;
@ -70,13 +70,13 @@ namespace ts {
// see comment to 'substitutePostfixUnaryExpression' for more details
// Collect information about the external module and dependency groups.
moduleInfo = moduleInfoMap[id] = collectExternalModuleInfo(context, node, resolver, compilerOptions);
moduleInfoMap.set(originalNode, moduleInfo = collectExternalModuleInfo(context, node, resolver, compilerOptions));
// Make sure that the name of the 'exports' function does not conflict with
// existing identifiers.
exportFunction = factory.createUniqueName("exports");
exportFunctionsMap[id] = exportFunction;
contextObject = contextObjectMap[id] = factory.createUniqueName("context");
exportFunctionsMap.set(originalNode, exportFunction);
contextObjectMap.set(originalNode, contextObject = factory.createUniqueName("context"));
// Add the body of the module.
const dependencyGroups = collectDependencyGroups(moduleInfo.externalImports);
@ -123,7 +123,7 @@ namespace ts {
}
if (noSubstitution) {
noSubstitutionMap[id] = noSubstitution;
noSubstitutionMap.set(originalNode, noSubstitution);
noSubstitution = undefined;
}
@ -596,8 +596,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfImportDeclaration(deferredExports[id], node);
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfImportDeclaration(deferredExports.get(originalNode), node));
}
else {
statements = appendExportsOfImportDeclaration(statements, node);
@ -624,8 +624,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id], node);
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfImportEqualsDeclaration(deferredExports.get(originalNode), node));
}
else {
statements = appendExportsOfImportEqualsDeclaration(statements, node);
@ -649,8 +649,8 @@ namespace ts {
const original = node.original;
if (original && hasAssociatedEndOfDeclarationMarker(original)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportStatement(deferredExports[id], factory.createIdentifier("default"), expression, /*allowComments*/ true);
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportStatement(deferredExports.get(originalNode), factory.createIdentifier("default"), expression, /*allowComments*/ true));
}
else {
return createExportStatement(factory.createIdentifier("default"), expression, /*allowComments*/ true);
@ -682,8 +682,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node);
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfHoistedDeclaration(deferredExports.get(originalNode), node));
}
else {
hoistedStatements = appendExportsOfHoistedDeclaration(hoistedStatements, node);
@ -729,8 +729,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node);
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfHoistedDeclaration(deferredExports.get(originalNode), node));
}
else {
statements = appendExportsOfHoistedDeclaration(statements, node);
@ -769,8 +769,8 @@ namespace ts {
if (isMarkedDeclaration) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node, isExportedDeclaration);
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfVariableStatement(deferredExports.get(originalNode), node, isExportedDeclaration));
}
else {
statements = appendExportsOfVariableStatement(statements, node, /*exportSelf*/ false);
@ -881,9 +881,9 @@ namespace ts {
// To balance the declaration, we defer the exports of the elided variable
// statement until we visit this declaration's `EndOfDeclarationMarker`.
if (hasAssociatedEndOfDeclarationMarker(node) && node.original!.kind === SyntaxKind.VariableStatement) {
const id = getOriginalNodeId(node);
const originalNode = getOriginalNode(node);
const isExportedDeclaration = hasSyntacticModifier(node.original!, ModifierFlags.Export);
deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node.original as VariableStatement, isExportedDeclaration);
deferredExports.set(originalNode, appendExportsOfVariableStatement(deferredExports.get(originalNode), node.original as VariableStatement, isExportedDeclaration));
}
return node;
@ -908,16 +908,15 @@ namespace ts {
// For some transformations we emit an `EndOfDeclarationMarker` to mark the actual
// end of the transformed declaration. We use this marker to emit any deferred exports
// of the declaration.
const id = getOriginalNodeId(node);
const statements = deferredExports[id];
const originalNode = getOriginalNode(node);
const statements = deferredExports.get(originalNode);
if (statements) {
delete deferredExports[id];
deferredExports.delete(originalNode);
return append(statements, node);
}
else {
const original = getOriginalNode(node);
if (isModuleOrEnumDeclaration(original)) {
return append(appendExportsOfDeclaration(statements, original), node);
if (isModuleOrEnumDeclaration(originalNode)) {
return append(appendExportsOfDeclaration(statements, originalNode), node);
}
}
@ -1678,16 +1677,14 @@ namespace ts {
*/
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
if (node.kind === SyntaxKind.SourceFile) {
const id = getOriginalNodeId(node);
const originalNode = getOriginalNode(node);
currentSourceFile = node as SourceFile;
moduleInfo = moduleInfoMap[id];
exportFunction = exportFunctionsMap[id];
noSubstitution = noSubstitutionMap[id];
contextObject = contextObjectMap[id];
moduleInfo = moduleInfoMap.get(originalNode)!;
exportFunction = exportFunctionsMap.get(originalNode)!;
noSubstitution = noSubstitutionMap.get(originalNode)!;
contextObject = contextObjectMap.get(originalNode)!;
if (noSubstitution) {
delete noSubstitutionMap[id];
}
noSubstitutionMap.delete(originalNode);
previousOnEmitNode(hint, node, emitCallback);
@ -1917,8 +1914,7 @@ namespace ts {
* @param node The node which should not be substituted.
*/
function preventSubstitution<T extends Node>(node: T): T {
if (noSubstitution === undefined) noSubstitution = [];
noSubstitution[getNodeId(node)] = true;
(noSubstitution ||= new Set<Node>()).add(node);
return node;
}
@ -1928,7 +1924,7 @@ namespace ts {
* @param node The node to test.
*/
function isSubstitutionPrevented(node: Node) {
return noSubstitution && node.id && noSubstitution[node.id];
return noSubstitution?.has(node);
}
}
}

View file

@ -78,7 +78,7 @@ namespace ts {
* A map that keeps track of aliases created for classes with decorators to avoid issues
* with the double-binding behavior of classes.
*/
let classAliases: Identifier[];
let classAliases: ESMap<Node, Identifier>;
/**
* Keeps track of whether we are within any containing namespaces when performing
@ -1237,7 +1237,7 @@ namespace ts {
return undefined;
}
const classAlias = classAliases && classAliases[getOriginalNodeId(node)];
const classAlias = classAliases?.get(getOriginalNode(node));
// When we transform to ES5/3 this will be moved inside an IIFE and should reference the name
// without any block-scoped variable collision handling
@ -3139,7 +3139,7 @@ namespace ts {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) {
enableSubstitutionForClassAliases();
const classAlias = factory.createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? idText(node.name) : "default");
classAliases[getOriginalNodeId(node)] = classAlias;
classAliases.set(getOriginalNode(node), classAlias);
hoistVariableDeclaration(classAlias);
return classAlias;
}
@ -3171,7 +3171,7 @@ namespace ts {
context.enableSubstitution(SyntaxKind.Identifier);
// Keep track of class aliases.
classAliases = [];
classAliases = new Map<Node, Identifier>();
}
}
@ -3290,7 +3290,7 @@ namespace ts {
// constructor references in static property initializers.
const declaration = resolver.getReferencedValueDeclaration(node);
if (declaration) {
const classAlias = classAliases[declaration.id!]; // TODO: GH#18217
const classAlias = classAliases.get(declaration);
if (classAlias) {
const clone = factory.cloneNode(classAlias);
setSourceMapRange(clone, node);

View file

@ -857,7 +857,6 @@ namespace ts {
/* @internal */ readonly transformFlags: TransformFlags; // Flags for transforms
readonly decorators?: NodeArray<Decorator>; // Array of decorators (in document order)
readonly modifiers?: ModifiersArray; // Array of modifiers
/* @internal */ id?: NodeId; // Unique id (used to look up NodeLinks)
readonly parent: Node; // Parent node (initialized by binding)
/* @internal */ original?: Node; // The original node if this is an updated node.
/* @internal */ symbol: Symbol; // Symbol declared by node (initialized by binding)

View file

@ -5821,7 +5821,6 @@ namespace ts {
this.pos = pos;
this.end = end;
this.kind = kind;
this.id = 0;
this.flags = NodeFlags.None;
this.modifierFlagsCache = ModifierFlags.None;
this.transformFlags = TransformFlags.None;
@ -5833,7 +5832,6 @@ namespace ts {
this.pos = pos;
this.end = end;
this.kind = kind;
this.id = 0;
this.flags = NodeFlags.None;
this.transformFlags = TransformFlags.None;
this.parent = undefined!;
@ -5843,7 +5841,6 @@ namespace ts {
this.pos = pos;
this.end = end;
this.kind = kind;
this.id = 0;
this.flags = NodeFlags.None;
this.transformFlags = TransformFlags.None;
this.parent = undefined!;

View file

@ -219,7 +219,6 @@ namespace Utils {
case "locals":
case "localSymbol":
case "kind":
case "id":
case "nodeCount":
case "symbolCount":
case "identifierCount":