From be18ada22f2560fd0a2790a780fd89ba1095c66a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 17 Sep 2014 18:13:06 -0700 Subject: [PATCH] Finally using new tree. --- .../getScriptLexicalStructureWalker.ts | 297 ++++++++++-------- src/services/services.ts | 4 +- 2 files changed, 159 insertions(+), 142 deletions(-) diff --git a/src/services/getScriptLexicalStructureWalker.ts b/src/services/getScriptLexicalStructureWalker.ts index f30810ee2f4..d65e1d4a48d 100644 --- a/src/services/getScriptLexicalStructureWalker.ts +++ b/src/services/getScriptLexicalStructureWalker.ts @@ -1,17 +1,17 @@ /// -module TypeScript.Services { - export function getNavigationBarItemsHelper(sourceUnit: TypeScript.SourceUnitSyntax): ts.NavigationBarItem[] { +module ts { + export function getNavigationBarItemsHelper(sourceFile: SourceFile): ts.NavigationBarItem[] { var hasGlobalNode = false; - return getItemsWorker(getTopLevelNodes(sourceUnit), createTopLevelItem); + return getItemsWorker(getTopLevelNodes(sourceFile), createTopLevelItem); - function getIndent(node: ISyntaxNode): number { + function getIndent(node: Node): number { var indent = hasGlobalNode ? 1 : 0; var current = node.parent; while (current) { - if (current.kind() === SyntaxKind.ModuleDeclaration || current.kind() === SyntaxKind.FunctionDeclaration) { + if (current.kind === SyntaxKind.ModuleDeclaration || current.kind === SyntaxKind.FunctionDeclaration) { indent++; } @@ -21,47 +21,38 @@ module TypeScript.Services { return indent; } - function getKindModifiers(modifiers: TypeScript.ISyntaxToken[]): string { - var result: string[] = []; - - for (var i = 0, n = modifiers.length; i < n; i++) { - result.push(modifiers[i].text()); - } - - return result.length > 0 ? result.join(',') : ts.ScriptElementKindModifier.none; - } - - function getChildNodes(nodes: IModuleElementSyntax[]): ISyntaxNode[] { - var childNodes: ISyntaxNode[] = []; + function getChildNodes(nodes: Node[]): Node[] { + var childNodes: Node[] = []; for (var i = 0, n = nodes.length; i < n; i++) { - var node = nodes[i]; + var node = nodes[i]; - if (node.kind() === SyntaxKind.FunctionDeclaration) { + if (node.kind === SyntaxKind.FunctionDeclaration) { childNodes.push(node); } - else if (node.kind() === SyntaxKind.VariableStatement) { - var variableDeclaration = (node).variableDeclaration; - childNodes.push.apply(childNodes, variableDeclaration.variableDeclarators); + else if (node.kind === SyntaxKind.VariableStatement) { + forEach((node).declarations, declaration => { + childNodes.push(declaration); + }); } } return childNodes; } - function getTopLevelNodes(node: SourceUnitSyntax): ISyntaxNode[] { - var topLevelNodes: ISyntaxNode[] = []; + function getTopLevelNodes(node: SourceFile): Node[] { + var topLevelNodes: Node[] = []; topLevelNodes.push(node); - addTopLevelNodes(node.moduleElements, topLevelNodes); + addTopLevelNodes(node.statements, topLevelNodes); return topLevelNodes; } - function addTopLevelNodes(nodes: IModuleElementSyntax[], topLevelNodes: ISyntaxNode[]): void { + function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void { for (var i = 0, n = nodes.length; i < n; i++) { var node = nodes[i]; - switch (node.kind()) { + switch (node.kind) { case SyntaxKind.ClassDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.InterfaceDeclaration: @@ -69,32 +60,39 @@ module TypeScript.Services { break; case SyntaxKind.ModuleDeclaration: - var moduleDeclaration = node; + var moduleDeclaration = node; topLevelNodes.push(node); - addTopLevelNodes(moduleDeclaration.moduleElements, topLevelNodes); + addTopLevelNodes((getInnermostModule(moduleDeclaration).body).statements, topLevelNodes); break; case SyntaxKind.FunctionDeclaration: - var functionDeclaration = node; + var functionDeclaration = node; if (isTopLevelFunctionDeclaration(functionDeclaration)) { topLevelNodes.push(node); - addTopLevelNodes(functionDeclaration.block.statements, topLevelNodes); + addTopLevelNodes((functionDeclaration.body).statements, topLevelNodes); } break; } } } - function isTopLevelFunctionDeclaration(functionDeclaration: FunctionDeclarationSyntax) { + function isTopLevelFunctionDeclaration(functionDeclaration: FunctionDeclaration) { // A function declaration is 'top level' if it contains any function declarations // within it. - return functionDeclaration.block && ArrayUtilities.any(functionDeclaration.block.statements, s => s.kind() === SyntaxKind.FunctionDeclaration); + return functionDeclaration.kind === SyntaxKind.FunctionDeclaration && + functionDeclaration.body && + functionDeclaration.body.kind === SyntaxKind.FunctionBlock && + forEach((functionDeclaration.body).statements, s => s.kind === SyntaxKind.FunctionDeclaration); } - function getItemsWorker(nodes: ISyntaxNode[], createItem: (n: ISyntaxNode) => ts.NavigationBarItem): ts.NavigationBarItem[] { + function getItemsWorker(nodes: Node[], createItem: (n: Node) => ts.NavigationBarItem): ts.NavigationBarItem[]{ var items: ts.NavigationBarItem[] = []; - var keyToItem = createIntrinsicsObject(); + if (!nodes) { + return items; + } + + var keyToItem: Map = {}; for (var i = 0, n = nodes.length; i < n; i++) { var child = nodes[i]; @@ -149,147 +147,135 @@ module TypeScript.Services { } } - function createChildItem(node: ISyntaxNode): ts.NavigationBarItem { - switch (node.kind()) { + function createChildItem(node: Node): ts.NavigationBarItem { + switch (node.kind) { case SyntaxKind.Parameter: - var parameter = node; - if (parameter.modifiers.length === 0) { + var parameter = node; + if ((node.flags & NodeFlags.Modifier) === 0) { return undefined; } - return new ts.NavigationBarItem(parameter.identifier.text(), ts.ScriptElementKind.memberVariableElement, getKindModifiers(parameter.modifiers), [TextSpan.fromBounds(start(node), end(node))]); + return new ts.NavigationBarItem(parameter.name.text, ts.ScriptElementKind.memberVariableElement, getNodeModifiers(node), [getNodeSpan(node)]); - case SyntaxKind.MemberFunctionDeclaration: - var memberFunction = node; - return new ts.NavigationBarItem(memberFunction.propertyName.text(), ts.ScriptElementKind.memberFunctionElement, getKindModifiers(memberFunction.modifiers), [TextSpan.fromBounds(start(node), end(node))]); + case SyntaxKind.Method: + var memberFunction = node; + return new ts.NavigationBarItem(memberFunction.name.text, ts.ScriptElementKind.memberFunctionElement, getNodeModifiers(node), [getNodeSpan(node)]); case SyntaxKind.GetAccessor: - var getAccessor = node; - return new ts.NavigationBarItem(getAccessor.propertyName.text(), ts.ScriptElementKind.memberGetAccessorElement, getKindModifiers(getAccessor.modifiers), [TextSpan.fromBounds(start(node), end(node))]); + var getAccessor = node; + return new ts.NavigationBarItem(getAccessor.name.text, ts.ScriptElementKind.memberGetAccessorElement, getNodeModifiers(node), [getNodeSpan(node)]); case SyntaxKind.SetAccessor: - var setAccessor = node; - return new ts.NavigationBarItem(setAccessor.propertyName.text(), ts.ScriptElementKind.memberSetAccessorElement, getKindModifiers(setAccessor.modifiers), [TextSpan.fromBounds(start(node), end(node))]); + var setAccessor = node; + return new ts.NavigationBarItem(setAccessor.name.text, ts.ScriptElementKind.memberSetAccessorElement, getNodeModifiers(node), [getNodeSpan(node)]); case SyntaxKind.IndexSignature: - var indexSignature = node; - return new ts.NavigationBarItem("[]", ts.ScriptElementKind.indexSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]); + return new ts.NavigationBarItem("[]", ts.ScriptElementKind.indexSignatureElement, ts.ScriptElementKindModifier.none, [getNodeSpan(node)]); - case SyntaxKind.EnumElement: - var enumElement = node; - return new ts.NavigationBarItem(enumElement.propertyName.text(), ts.ScriptElementKind.memberVariableElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]); + case SyntaxKind.EnumMember: + var enumElement = node; + return new ts.NavigationBarItem(enumElement.name.text, ts.ScriptElementKind.memberVariableElement, ts.ScriptElementKindModifier.none, [getNodeSpan(node)]); case SyntaxKind.CallSignature: - var callSignature = node; - return new ts.NavigationBarItem("()", ts.ScriptElementKind.callSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]); + return new ts.NavigationBarItem("()", ts.ScriptElementKind.callSignatureElement, ts.ScriptElementKindModifier.none, []); case SyntaxKind.ConstructSignature: - var constructSignature = node; - return new ts.NavigationBarItem("new()", ts.ScriptElementKind.constructSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]); + return new ts.NavigationBarItem("new()", ts.ScriptElementKind.constructSignatureElement, ts.ScriptElementKindModifier.none, [getNodeSpan(node)]); - case SyntaxKind.MethodSignature: - var methodSignature = node; - return new ts.NavigationBarItem(methodSignature.propertyName.text(), ts.ScriptElementKind.memberFunctionElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]); - - case SyntaxKind.PropertySignature: - var propertySignature = node; - return new ts.NavigationBarItem(propertySignature.propertyName.text(), ts.ScriptElementKind.memberVariableElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]); + case SyntaxKind.Property: + var propertySignature = node; + return new ts.NavigationBarItem(propertySignature.name.text, ts.ScriptElementKind.memberVariableElement, getNodeModifiers(node), [getNodeSpan(node)]); case SyntaxKind.FunctionDeclaration: - var functionDeclaration = node; + var functionDeclaration = node; if (!isTopLevelFunctionDeclaration(functionDeclaration)) { - return new ts.NavigationBarItem(functionDeclaration.identifier.text(), ts.ScriptElementKind.functionElement, getKindModifiers(functionDeclaration.modifiers), [TextSpan.fromBounds(start(node), end(node))]); + return new ts.NavigationBarItem(functionDeclaration.name.text, ts.ScriptElementKind.functionElement, getNodeModifiers(node), [getNodeSpan(node)]); } break; - case SyntaxKind.MemberVariableDeclaration: - var memberVariableDeclaration = node; - return new ts.NavigationBarItem(memberVariableDeclaration.variableDeclarator.propertyName.text(), ts.ScriptElementKind.memberVariableElement, getKindModifiers(memberVariableDeclaration.modifiers), [TextSpan.fromBounds(start(memberVariableDeclaration.variableDeclarator), end(memberVariableDeclaration.variableDeclarator))]); + case SyntaxKind.VariableDeclaration: + var variableDeclaration = node; + return new ts.NavigationBarItem(variableDeclaration.name.text, ts.ScriptElementKind.variableElement, ts.ScriptElementKindModifier.none, [getNodeSpan(node)]); - case SyntaxKind.VariableDeclarator: - var variableDeclarator = node; - return new ts.NavigationBarItem(variableDeclarator.propertyName.text(), ts.ScriptElementKind.variableElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(variableDeclarator), end(variableDeclarator))]); - - case SyntaxKind.ConstructorDeclaration: - var constructorDeclaration = node; - return new ts.NavigationBarItem("constructor", ts.ScriptElementKind.constructorImplementationElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]); + case SyntaxKind.Constructor: + return new ts.NavigationBarItem("constructor", ts.ScriptElementKind.constructorImplementationElement, ts.ScriptElementKindModifier.none, [getNodeSpan(node)]); } return undefined; } - function createTopLevelItem(node: ISyntaxNode): ts.NavigationBarItem { - switch (node.kind()) { - case SyntaxKind.SourceUnit: - return createSourceUnitItem(node); + function createTopLevelItem(node: Node): ts.NavigationBarItem { + switch (node.kind) { + case SyntaxKind.SourceFile: + return createSourceFileItem(node); case SyntaxKind.ClassDeclaration: - return createClassItem(node); + return createClassItem(node); case SyntaxKind.EnumDeclaration: - return createEnumItem(node); + return createEnumItem(node); case SyntaxKind.InterfaceDeclaration: - return createIterfaceItem(node); + return createIterfaceItem(node); case SyntaxKind.ModuleDeclaration: - return createModuleItem(node); + return createModuleItem(node); case SyntaxKind.FunctionDeclaration: - return createFunctionItem(node); + return createFunctionItem(node); } return undefined; - function getModuleNames(node: TypeScript.ModuleDeclarationSyntax): string[] { + function getModuleNames(moduleDeclaration: ModuleDeclaration): string[]{ + // We want to maintain quotation marks. + if (moduleDeclaration.name.kind === SyntaxKind.StringLiteral) { + return [getSourceTextOfNode(moduleDeclaration.name)]; + } + + // Otherwise, we need to aggregate each identifier of the qualified name. var result: string[] = []; - if (node.stringLiteral) { - result.push(node.stringLiteral.text()); - } - else { - getModuleNamesHelper(node.name, result); - } + result.push(moduleDeclaration.name.text); + + while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) { + moduleDeclaration = moduleDeclaration.body; + + result.push(moduleDeclaration.name.text); + } return result; } - function getModuleNamesHelper(name: TypeScript.INameSyntax, result: string[]): void { - if (name.kind() === TypeScript.SyntaxKind.QualifiedName) { - var qualifiedName = name; - getModuleNamesHelper(qualifiedName.left, result); - result.push(qualifiedName.right.text()); - } - else { - result.push((name).text()); - } - } - - function createModuleItem(node: ModuleDeclarationSyntax): ts.NavigationBarItem { + function createModuleItem(node: ModuleDeclaration): NavigationBarItem { var moduleNames = getModuleNames(node); - - var childItems = getItemsWorker(getChildNodes(node.moduleElements), n => createChildItem(n)); + + var childItems = getItemsWorker(getChildNodes((getInnermostModule(node).body).statements), createChildItem); return new ts.NavigationBarItem(moduleNames.join("."), ts.ScriptElementKind.moduleElement, - getKindModifiers(node.modifiers), - [TextSpan.fromBounds(start(node), end(node))], + getNodeModifiers(node), + [getNodeSpan(node)], childItems, getIndent(node)); } - function createFunctionItem(node: FunctionDeclarationSyntax) { - var childItems = getItemsWorker(node.block.statements, n => createChildItem(n)); + function createFunctionItem(node: FunctionDeclaration) { + if (node.name && node.body && node.body.kind === SyntaxKind.FunctionBlock) { + var childItems = getItemsWorker((node.body).statements, createChildItem); - return new ts.NavigationBarItem(node.identifier.text(), - ts.ScriptElementKind.functionElement, - getKindModifiers(node.modifiers), - [TextSpan.fromBounds(start(node), end(node))], - childItems, - getIndent(node)); + return new ts.NavigationBarItem(node.name.text, + ts.ScriptElementKind.functionElement, + getNodeModifiers(node), + [getNodeSpan(node)], + childItems, + getIndent(node)); + } + + return undefined; } - function createSourceUnitItem(node: SourceUnitSyntax): ts.NavigationBarItem { - var childItems = getItemsWorker(getChildNodes(node.moduleElements), n => createChildItem(n)); + function createSourceFileItem(node: SourceFile): ts.NavigationBarItem { + var childItems = getItemsWorker(getChildNodes(node.statements), createChildItem); if (childItems === undefined || childItems.length === 0) { return undefined; @@ -299,50 +285,83 @@ module TypeScript.Services { return new ts.NavigationBarItem("", ts.ScriptElementKind.moduleElement, ts.ScriptElementKindModifier.none, - [TextSpan.fromBounds(start(node), end(node))], + [getNodeSpan(node)], childItems); } - function createClassItem(node: ClassDeclarationSyntax): ts.NavigationBarItem { - var constructor = ArrayUtilities.firstOrDefault( - node.classElements, n => n.kind() === SyntaxKind.ConstructorDeclaration); + function createClassItem(node: ClassDeclaration): ts.NavigationBarItem { + var childItems: NavigationBarItem[]; - // Add the constructor parameters in as children of the class (for property parameters). - var nodes: ISyntaxNode[] = constructor - ? (constructor.callSignature.parameterList.parameters).concat(node.classElements) - : node.classElements; + if (node.members) { + var constructor = forEach(node.members, member => { + return member.kind === SyntaxKind.Constructor && member; + }); + + // Add the constructor parameters in as children of the class (for property parameters). + var nodes: Node[] = constructor + ? (constructor.parameters).concat(node.members) + : node.members; + + var childItems = getItemsWorker(nodes, createChildItem); + } - var childItems = getItemsWorker(nodes, n => createChildItem(n)); return new ts.NavigationBarItem( - node.identifier.text(), + node.name.text, ts.ScriptElementKind.classElement, - getKindModifiers(node.modifiers), - [TextSpan.fromBounds(start(node), end(node))], + getNodeModifiers(node), + [getNodeSpan(node)], childItems, getIndent(node)); } - function createEnumItem(node: TypeScript.EnumDeclarationSyntax): ts.NavigationBarItem { - var childItems = getItemsWorker(node.enumElements, n => createChildItem(n)); + function createEnumItem(node: EnumDeclaration): ts.NavigationBarItem { + var childItems = getItemsWorker(node.members, createChildItem); return new ts.NavigationBarItem( - node.identifier.text(), + node.name.text, ts.ScriptElementKind.enumElement, - getKindModifiers(node.modifiers), - [TextSpan.fromBounds(start(node), end(node))], + getNodeModifiers(node), + [getNodeSpan(node)], childItems, getIndent(node)); } - function createIterfaceItem(node: TypeScript.InterfaceDeclarationSyntax): ts.NavigationBarItem { - var childItems = getItemsWorker(node.body.typeMembers, n => createChildItem(n)); + function createIterfaceItem(node: InterfaceDeclaration): ts.NavigationBarItem { + var childItems = getItemsWorker(node.members, createChildItem); return new ts.NavigationBarItem( - node.identifier.text(), + node.name.text, ts.ScriptElementKind.interfaceElement, - getKindModifiers(node.modifiers), - [TextSpan.fromBounds(start(node), end(node))], + getNodeModifiers(node), + [getNodeSpan(node)], childItems, getIndent(node)); } } + + // TODO: use implementation in services.ts + function getNodeModifiers(node: Node): string { + var flags = node.flags; + var result: string[] = []; + + if (flags & NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier); + if (flags & NodeFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier); + if (flags & NodeFlags.Static) result.push(ScriptElementKindModifier.staticModifier); + if (flags & NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier); + if (isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier); + + return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none; + } + + function getInnermostModule(node: ModuleDeclaration): ModuleDeclaration { + + while (node.body.kind === SyntaxKind.ModuleDeclaration) { + node = node.body; + } + + return node; + } + + function getNodeSpan(node: Node) { + return TypeScript.TextSpan.fromBounds(node.getStart(), node.getEnd()); + } } } \ No newline at end of file diff --git a/src/services/services.ts b/src/services/services.ts index ed32721a1ac..daaeb6d21bc 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3121,9 +3121,7 @@ module ts { function getNavigationBarItems(filename: string): NavigationBarItem[] { filename = TypeScript.switchToForwardSlashes(filename); - - var syntaxTree = getSyntaxTree(filename); - return TypeScript.Services.getNavigationBarItemsHelper(syntaxTree.sourceUnit()); + return getNavigationBarItemsHelper(getCurrentSourceFile(filename)); } function getOutliningSpans(filename: string): OutliningSpan[] {