diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 7eb44213e02..d336bdf4b30 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -1,1088 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. // See LICENSE.txt in the project root for complete license information. -module TypeScript.Services.Breakpoints { - function createBreakpointSpanInfo(parentElement: TypeScript.ISyntaxElement, ...childElements: TypeScript.ISyntaxElement[]): TextSpan { - if (!parentElement) { - return null; - } - - if (childElements.length == 0) { - return TextSpan.fromBounds(TypeScript.start(parentElement), TypeScript.end(parentElement)); - } - - var start: number; - var end: number; - for (var i = 0; i < childElements.length; i++) { - var element = childElements[i]; - if (element && !isShared(element)) { - if (start == undefined) { - start = TypeScript.start(element); - } - end = TypeScript.end(element); - } - } - - return TextSpan.fromBounds(start, end); - } - - function createBreakpointSpanInfoWithLimChar(startElement: TypeScript.ISyntaxElement, limChar: number): TextSpan { - return TextSpan.fromBounds(start(startElement), limChar); - } - - class BreakpointResolver { - constructor(private posLine: number, private lineMap: TypeScript.LineMap) { - } - - private breakpointSpanOfToken(positionedToken: TypeScript.ISyntaxToken): TextSpan { - switch (positionedToken.kind()) { - case TypeScript.SyntaxKind.OpenBraceToken: - return this.breakpointSpanOfOpenBrace(positionedToken); - - case TypeScript.SyntaxKind.CloseBraceToken: - return this.breakpointSpanOfCloseBrace(positionedToken); - - case TypeScript.SyntaxKind.CommaToken: - return this.breakpointSpanOfComma(positionedToken); - - case TypeScript.SyntaxKind.SemicolonToken: - case TypeScript.SyntaxKind.EndOfFileToken: - return this.breakpointSpanIfStartsOnSameLine(previousToken(positionedToken)); - - case TypeScript.SyntaxKind.CloseParenToken: - return this.breakpointSpanOfCloseParen(positionedToken); - - case TypeScript.SyntaxKind.DoKeyword: - var parentElement = positionedToken.parent; - if (parentElement && parentElement.kind() == TypeScript.SyntaxKind.DoStatement) { - return this.breakpointSpanIfStartsOnSameLine(nextToken(positionedToken)); - } - break; - } - - return this.breakpointSpanOfContainingNode(positionedToken); - } - - private breakpointSpanOfOpenBrace(openBraceToken: TypeScript.ISyntaxToken): TextSpan { - var container = Syntax.containingNode(openBraceToken); - if (container) { - var originalContainer = container; - if (container && container.kind() == TypeScript.SyntaxKind.Block) { - // We have to check the parent and decide what to do with the breakpoint - container = Syntax.containingNode(container); - if (!container) { - container = originalContainer; - } - } - - switch (container.kind()) { - case TypeScript.SyntaxKind.Block: - if (!this.canHaveBreakpointInBlock(container)) { - return null; - } - return this.breakpointSpanOfFirstStatementInBlock(container); - break; - - case TypeScript.SyntaxKind.ModuleDeclaration: - case TypeScript.SyntaxKind.ClassDeclaration: - case TypeScript.SyntaxKind.FunctionDeclaration: - case TypeScript.SyntaxKind.ConstructorDeclaration: - case TypeScript.SyntaxKind.MemberFunctionDeclaration: - case TypeScript.SyntaxKind.GetAccessor: - case TypeScript.SyntaxKind.SetAccessor: - case TypeScript.SyntaxKind.FunctionExpression: - case TypeScript.SyntaxKind.ParenthesizedArrowFunctionExpression: - case TypeScript.SyntaxKind.SimpleArrowFunctionExpression: - if (!this.canHaveBreakpointInDeclaration(container)) { - return null; - } - if (this.posLine != this.lineMap.getLineNumberFromPosition(start(container))) { - return this.breakpointSpanOfFirstChildOfSyntaxList(this.getSyntaxListOfDeclarationWithElements(container)); - } - else { - return this.breakpointSpanOf(container); - } - - case TypeScript.SyntaxKind.EnumDeclaration: - if (!this.canHaveBreakpointInDeclaration(container)) { - return null; - } - if (this.posLine != this.lineMap.getLineNumberFromPosition(start(container))) { - return this.breakpointSpanOfFirstEnumElement(container); - } - else { - return this.breakpointSpanOf(container); - } - - case TypeScript.SyntaxKind.IfStatement: - case TypeScript.SyntaxKind.ForInStatement: - case TypeScript.SyntaxKind.WhileStatement: - case TypeScript.SyntaxKind.CatchClause: - if (this.posLine != this.lineMap.getLineNumberFromPosition(start(container))) { - return this.breakpointSpanOfFirstStatementInBlock(originalContainer); - } - else { - return this.breakpointSpanOf(container); - } - - case TypeScript.SyntaxKind.DoStatement: - return this.breakpointSpanOfFirstStatementInBlock(originalContainer); - - case TypeScript.SyntaxKind.ForStatement: - if (this.posLine != this.lineMap.getLineNumberFromPosition(start(container))) { - return this.breakpointSpanOfFirstStatementInBlock(originalContainer); - } - else { - return this.breakpointSpanOf(previousToken(openBraceToken)); - } - - case TypeScript.SyntaxKind.ElseClause: - case TypeScript.SyntaxKind.CaseSwitchClause: - case TypeScript.SyntaxKind.DefaultSwitchClause: - case TypeScript.SyntaxKind.WithStatement: - case TypeScript.SyntaxKind.TryStatement: - case TypeScript.SyntaxKind.FinallyClause: - return this.breakpointSpanOfFirstStatementInBlock(originalContainer); - - case TypeScript.SyntaxKind.SwitchStatement: - if (this.posLine != this.lineMap.getLineNumberFromPosition(start(container))) { - return this.breakpointSpanOfFirstStatementOfFirstCaseClause(container); - } - else { - return this.breakpointSpanOf(container); - } - } - } - - return null; - } - - private breakpointSpanOfCloseBrace(closeBraceToken: TypeScript.ISyntaxToken): TextSpan { - var container = Syntax.containingNode(closeBraceToken); - if (container) { - var originalContainer = container; - if (container.kind() == TypeScript.SyntaxKind.Block) { - // We have to check the parent and decide what to do with the breakpoint - container = Syntax.containingNode(container); - if (!container) { - container = originalContainer; - } - } - - switch (container.kind()) { - case TypeScript.SyntaxKind.Block: - if (!this.canHaveBreakpointInBlock(container)) { - return null; - } - return this.breakpointSpanOfLastStatementInBlock(container); - break; - - case TypeScript.SyntaxKind.ModuleDeclaration: - if (!this.canHaveBreakpointInDeclaration(container)) { - return null; - } - var moduleSyntax = container; - if (moduleSyntax.moduleElements && moduleSyntax.moduleElements.length > 0) { - return createBreakpointSpanInfo(closeBraceToken); - } - else { - return null; - } - - case TypeScript.SyntaxKind.ClassDeclaration: - case TypeScript.SyntaxKind.FunctionDeclaration: - case TypeScript.SyntaxKind.ConstructorDeclaration: - case TypeScript.SyntaxKind.MemberFunctionDeclaration: - case TypeScript.SyntaxKind.GetAccessor: - case TypeScript.SyntaxKind.SetAccessor: - case TypeScript.SyntaxKind.FunctionExpression: - if (!this.canHaveBreakpointInDeclaration(container)) { - return null; - } - return createBreakpointSpanInfo(closeBraceToken); - - case TypeScript.SyntaxKind.EnumDeclaration: - if (!this.canHaveBreakpointInDeclaration(container)) { - return null; - } - return createBreakpointSpanInfo(closeBraceToken); - - case TypeScript.SyntaxKind.IfStatement: - case TypeScript.SyntaxKind.ElseClause: - case TypeScript.SyntaxKind.ForInStatement: - case TypeScript.SyntaxKind.ForStatement: - case TypeScript.SyntaxKind.WhileStatement: - case TypeScript.SyntaxKind.DoStatement: - case TypeScript.SyntaxKind.CaseSwitchClause: - case TypeScript.SyntaxKind.DefaultSwitchClause: - case TypeScript.SyntaxKind.WithStatement: - case TypeScript.SyntaxKind.TryStatement: - case TypeScript.SyntaxKind.CatchClause: - case TypeScript.SyntaxKind.FinallyClause: - case TypeScript.SyntaxKind.ParenthesizedArrowFunctionExpression: - case TypeScript.SyntaxKind.SimpleArrowFunctionExpression: - return this.breakpointSpanOfLastStatementInBlock(originalContainer); - - case TypeScript.SyntaxKind.SwitchStatement: - return this.breakpointSpanOfLastStatementOfLastCaseClause(container); - } - } - - return null; - } - - - private breakpointSpanOfComma(commaToken: TypeScript.ISyntaxToken): TextSpan { - var commaParent = commaToken.parent; - if (isSeparatedList(commaParent)) { - var grandParent = commaParent.parent; - if (grandParent) { - switch (grandParent.kind()) { - case TypeScript.SyntaxKind.VariableDeclaration: - case TypeScript.SyntaxKind.EnumDeclaration: - case TypeScript.SyntaxKind.ParameterList: - var index = Syntax.childIndex(commaParent, commaToken); - // Use the previous child - if (index > 0) { - var child = childAt(commaParent, index - 1); - return this.breakpointSpanOf(child); - } - - // If we cant set breakpoint on enum element, just dont set breakpoint - if (grandParent.kind() == TypeScript.SyntaxKind.EnumDeclaration) { - return null; - } - break; - } - } - } - - return this.breakpointSpanOfContainingNode(commaToken); - } - - private breakpointSpanOfCloseParen(closeParenToken: TypeScript.ISyntaxToken): TextSpan { - var closeParenParent = closeParenToken.parent; - if (closeParenParent) { - switch (closeParenParent.kind()) { - case TypeScript.SyntaxKind.ForStatement: - case TypeScript.SyntaxKind.ParameterList: - return this.breakpointSpanOf(previousToken(closeParenToken)); - } - } - - return this.breakpointSpanOfContainingNode(closeParenToken); - } - - private canHaveBreakpointInBlock(blockNode: TypeScript.ISyntaxNode) { - if (!blockNode || TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(blockNode)) { - return false; - } - - var blockSyntax = blockNode; - return blockSyntax.statements && blockSyntax.statements.length != 0; - } - - private breakpointSpanOfFirstStatementInBlock(blockNode: TypeScript.ISyntaxNode): TextSpan { - if (!blockNode) { - return null; - } - - var blockSyntax = blockNode; - var statementsNode = blockSyntax.statements; - if (!statementsNode || statementsNode.length == 0) { - return null; - } - - var firstStatement = childAt(statementsNode, 0); - if (firstStatement && firstStatement.kind() == TypeScript.SyntaxKind.Block) { - if (this.canHaveBreakpointInBlock(firstStatement)) { - return this.breakpointSpanOfFirstStatementInBlock(firstStatement); - } - return null; - } - else { - return this.breakpointSpanOf(firstStatement); - } - } - - private breakpointSpanOfLastStatementInBlock(blockNode: TypeScript.ISyntaxNode): TextSpan { - if (!blockNode) { - return null; - } - - var blockSyntax = blockNode; - var statementsNode = blockSyntax.statements; - if (!statementsNode || statementsNode.length == 0) { - return null; - } - - var lastStatement = childAt(statementsNode, statementsNode.length - 1); - if (lastStatement && lastStatement.kind() == TypeScript.SyntaxKind.Block) { - if (this.canHaveBreakpointInBlock(lastStatement)) { - return this.breakpointSpanOfLastStatementInBlock(lastStatement); - } - return null; - } - else { - return this.breakpointSpanOf(lastStatement); - } - } - - private breakpointSpanOfFirstChildOfSyntaxList(positionedList: TypeScript.ISyntaxNodeOrToken[]): TextSpan { - if (!positionedList) { - return null; - } - - // Find the first syntax element - var listSyntax = positionedList; - if (listSyntax.length == 0) { - return null; - } - - var firstStatement = childAt(positionedList, 0); - if (firstStatement && firstStatement.kind() == TypeScript.SyntaxKind.Block) { - if (this.canHaveBreakpointInBlock(firstStatement)) { - return this.breakpointSpanOfFirstStatementInBlock(firstStatement); - } - - return null; - } - else { - return this.breakpointSpanOf(firstStatement); - } - } - - private breakpointSpanOfLastChildOfSyntaxList(positionedList: TypeScript.ISyntaxNodeOrToken[]): TextSpan { - if (!positionedList) { - return null; - } - - // Find the first syntax element - var listSyntax = positionedList; - if (listSyntax.length == 0) { - return null; - } - var lastStatement = childAt(positionedList, 0); - if (lastStatement && lastStatement.kind() == TypeScript.SyntaxKind.Block) { - if (this.canHaveBreakpointInBlock(lastStatement)) { - return this.breakpointSpanOfLastStatementInBlock(lastStatement); - } - return null; - } - else { - return this.breakpointSpanOf(lastStatement); - } - } - - private breakpointSpanOfNode(positionedNode: ISyntaxNode): TextSpan { - var node = positionedNode; - switch (node.kind()) { - // Declarations with elements - case TypeScript.SyntaxKind.ModuleDeclaration: - case TypeScript.SyntaxKind.ClassDeclaration: - case TypeScript.SyntaxKind.FunctionDeclaration: - case TypeScript.SyntaxKind.ConstructorDeclaration: - case TypeScript.SyntaxKind.MemberFunctionDeclaration: - case TypeScript.SyntaxKind.GetAccessor: - case TypeScript.SyntaxKind.SetAccessor: - case TypeScript.SyntaxKind.FunctionExpression: - return this.breakpointSpanOfDeclarationWithElements(positionedNode); - - // Var, parameter and member variable declaration syntax - case TypeScript.SyntaxKind.VariableDeclarator: - return this.breakpointSpanOfVariableDeclarator(positionedNode); - - case TypeScript.SyntaxKind.VariableDeclaration: - return this.breakpointSpanOfVariableDeclaration(positionedNode); - - case TypeScript.SyntaxKind.VariableStatement: - return this.breakpointSpanOfVariableStatement(positionedNode); - - case TypeScript.SyntaxKind.Parameter: - return this.breakpointSpanOfParameter(positionedNode); - - case TypeScript.SyntaxKind.MemberVariableDeclaration: - return this.breakpointSpanOfMemberVariableDeclaration(positionedNode); - - case TypeScript.SyntaxKind.ImportDeclaration: - return this.breakpointSpanOfImportDeclaration(positionedNode); - - case TypeScript.SyntaxKind.EnumDeclaration: - return this.breakpointSpanOfEnumDeclaration(positionedNode); - - case TypeScript.SyntaxKind.EnumElement: - return this.breakpointSpanOfEnumElement(positionedNode); - - // Statements - case TypeScript.SyntaxKind.IfStatement: - return this.breakpointSpanOfIfStatement(positionedNode); - case TypeScript.SyntaxKind.ElseClause: - return this.breakpointSpanOfElseClause(positionedNode); - case TypeScript.SyntaxKind.ForInStatement: - return this.breakpointSpanOfForInStatement(positionedNode); - case TypeScript.SyntaxKind.ForStatement: - return this.breakpointSpanOfForStatement(positionedNode); - case TypeScript.SyntaxKind.WhileStatement: - return this.breakpointSpanOfWhileStatement(positionedNode); - case TypeScript.SyntaxKind.DoStatement: - return this.breakpointSpanOfDoStatement(positionedNode); - case TypeScript.SyntaxKind.SwitchStatement: - return this.breakpointSpanOfSwitchStatement(positionedNode); - case TypeScript.SyntaxKind.CaseSwitchClause: - return this.breakpointSpanOfCaseSwitchClause(positionedNode); - case TypeScript.SyntaxKind.DefaultSwitchClause: - return this.breakpointSpanOfDefaultSwitchClause(positionedNode); - case TypeScript.SyntaxKind.WithStatement: - return this.breakpointSpanOfWithStatement(positionedNode); - case TypeScript.SyntaxKind.TryStatement: - return this.breakpointSpanOfTryStatement(positionedNode); - case TypeScript.SyntaxKind.CatchClause: - return this.breakpointSpanOfCatchClause(positionedNode); - case TypeScript.SyntaxKind.FinallyClause: - return this.breakpointSpanOfFinallyClause(positionedNode); - - // Arrow expressions - case TypeScript.SyntaxKind.ParenthesizedArrowFunctionExpression: - return this.breakpointSpanOfParenthesizedArrowFunctionExpression(positionedNode); - - case TypeScript.SyntaxKind.SimpleArrowFunctionExpression: - return this.breakpointSpanOfSimpleArrowFunctionExpression(positionedNode); - - // Expressions or statements - default: - if (SyntaxUtilities.isStatement(node)) { - return this.breakpointSpanOfStatement(positionedNode); - } - else { - return this.breakpointOfExpression(positionedNode); - } - } - } - - private isExpressionOfArrowExpressions(expression: ISyntaxElement): boolean { - if (!expression) { - return false; - } - - var expressionParent = expression.parent; - if (expressionParent) { - if (expressionParent.kind() == TypeScript.SyntaxKind.ParenthesizedArrowFunctionExpression) { - var parenthesizedArrowExpression = expressionParent; - var expressionOfParenthesizedArrowExpression = parenthesizedArrowExpression.expression; - return expressionOfParenthesizedArrowExpression == expression; - } - else if (expressionParent.kind() == TypeScript.SyntaxKind.SimpleArrowFunctionExpression) { - var simpleArrowExpression = expressionParent; - var expressionOfSimpleArrowExpression = simpleArrowExpression.expression; - return expressionOfSimpleArrowExpression == expression; - } - else if (expressionParent.kind() == TypeScript.SyntaxKind.CommaExpression) { - return this.isExpressionOfArrowExpressions(expressionParent); - } - } - return false; - } - - private isInitializerOfForStatement(expressionNode: TypeScript.ISyntaxNode): boolean { - if (!expressionNode) { - return false; - } - - var expressionParent = expressionNode.parent; - if (expressionParent && expressionParent.kind() == TypeScript.SyntaxKind.ForStatement) { - - var expression = expressionNode; - var forStatement = expressionParent; - var initializer = forStatement.initializer; - return initializer === expression; - } - else if (expressionParent && expressionParent.kind() == TypeScript.SyntaxKind.CommaExpression) { - return this.isInitializerOfForStatement(expressionParent); - } - - return false; - } - - private isConditionOfForStatement(expressionNode: TypeScript.ISyntaxNode): boolean { - if (!expressionNode) { - return false; - } - - var expressionParent = expressionNode.parent; - if (expressionParent && expressionParent.kind() == TypeScript.SyntaxKind.ForStatement) { - var expression = expressionNode; - var forStatement = expressionParent; - var condition = forStatement.condition; - return condition === expression; - } - else if (expressionParent && expressionParent.kind() == TypeScript.SyntaxKind.CommaExpression) { - return this.isConditionOfForStatement(expressionParent); - } - - return false; - } - - private isIncrememtorOfForStatement(expressionNode: TypeScript.ISyntaxNode): boolean { - if (!expressionNode) { - return false; - } - - var expressionParent = expressionNode.parent; - if (expressionParent && expressionParent.kind() == TypeScript.SyntaxKind.ForStatement) { - var expression = expressionNode; - var forStatement = expressionParent; - var incrementor = forStatement.incrementor; - return incrementor === expression; - } - else if (expressionParent && expressionParent.kind() == TypeScript.SyntaxKind.CommaExpression) { - return this.isIncrememtorOfForStatement(expressionParent); - } - - return false; - } - - private breakpointOfLeftOfCommaExpression(commaExpressionNode: TypeScript.ISyntaxNode): TextSpan { - var commaExpression = commaExpressionNode; - return this.breakpointSpanOf(commaExpression.left); - } - - private breakpointOfExpression(expressionNode: TypeScript.ISyntaxNode): TextSpan { - if (this.isInitializerOfForStatement(expressionNode) || - this.isConditionOfForStatement(expressionNode) || - this.isIncrememtorOfForStatement(expressionNode)) { - if (expressionNode.kind() == TypeScript.SyntaxKind.CommaExpression) { - return this.breakpointOfLeftOfCommaExpression(expressionNode); - } - return createBreakpointSpanInfo(expressionNode); - } - - if (this.isExpressionOfArrowExpressions(expressionNode)) { - if (expressionNode.kind() == TypeScript.SyntaxKind.CommaExpression) { - return this.breakpointOfLeftOfCommaExpression(expressionNode); - } - return createBreakpointSpanInfo(expressionNode); - } - - if (expressionNode.kind() == TypeScript.SyntaxKind.ExportAssignment) { - var exportAssignmentSyntax = expressionNode; - return createBreakpointSpanInfo(expressionNode, exportAssignmentSyntax.exportKeyword, exportAssignmentSyntax.equalsToken, exportAssignmentSyntax.identifier); - } - - return this.breakpointSpanOfContainingNode(expressionNode); - } - - private breakpointSpanOfStatement(statementNode: TypeScript.ISyntaxNode): TextSpan { - var statement = statementNode; - if (statement.kind() == TypeScript.SyntaxKind.EmptyStatement) { - return null; - } - - var containingNode = Syntax.containingNode(statementNode); - if (SyntaxUtilities.isStatement(containingNode)) { - // Check if not the declarations and the compound statements - var useNodeForBreakpoint = false; - switch (containingNode.kind()) { - // Declarations - case TypeScript.SyntaxKind.ModuleDeclaration: - case TypeScript.SyntaxKind.ClassDeclaration: - case TypeScript.SyntaxKind.FunctionDeclaration: - case TypeScript.SyntaxKind.ConstructorDeclaration: - case TypeScript.SyntaxKind.MemberFunctionDeclaration: - case TypeScript.SyntaxKind.GetAccessor: - case TypeScript.SyntaxKind.SetAccessor: - case TypeScript.SyntaxKind.Block: - - // Compound Statements - case TypeScript.SyntaxKind.IfStatement: - case TypeScript.SyntaxKind.ElseClause: - case TypeScript.SyntaxKind.ForInStatement: - case TypeScript.SyntaxKind.ForStatement: - case TypeScript.SyntaxKind.WhileStatement: - case TypeScript.SyntaxKind.DoStatement: - case TypeScript.SyntaxKind.SwitchStatement: - case TypeScript.SyntaxKind.CaseSwitchClause: - case TypeScript.SyntaxKind.DefaultSwitchClause: - case TypeScript.SyntaxKind.WithStatement: - case TypeScript.SyntaxKind.TryStatement: - case TypeScript.SyntaxKind.CatchClause: - case TypeScript.SyntaxKind.FinallyClause: - case TypeScript.SyntaxKind.Block: - useNodeForBreakpoint = true; - } - - if (!useNodeForBreakpoint) { - return this.breakpointSpanOfContainingNode(statementNode); - } - } - - switch (statement.kind()) { - case TypeScript.SyntaxKind.ExpressionStatement: - var expressionSyntax = statement; - return createBreakpointSpanInfo(expressionSyntax.expression); - - case TypeScript.SyntaxKind.ReturnStatement: - var returnStatementSyntax = statement; - return createBreakpointSpanInfo(statementNode, returnStatementSyntax.returnKeyword, returnStatementSyntax.expression); - - case TypeScript.SyntaxKind.ThrowStatement: - var throwStatementSyntax = statement; - return createBreakpointSpanInfo(statementNode, throwStatementSyntax.throwKeyword, throwStatementSyntax.expression); - - case TypeScript.SyntaxKind.BreakStatement: - var breakStatementSyntax = statement; - return createBreakpointSpanInfo(statementNode, breakStatementSyntax.breakKeyword, breakStatementSyntax.identifier); - - case TypeScript.SyntaxKind.ContinueStatement: - var continueStatementSyntax = statement; - return createBreakpointSpanInfo(statementNode, continueStatementSyntax.continueKeyword, continueStatementSyntax.identifier); - - case TypeScript.SyntaxKind.DebuggerStatement: - var debuggerStatementSyntax = statement; - return createBreakpointSpanInfo(debuggerStatementSyntax.debuggerKeyword); - - case TypeScript.SyntaxKind.LabeledStatement: - var labeledStatementSyntax = statement; - return this.breakpointSpanOf(labeledStatementSyntax.statement); - } - - return null; - } - - private getSyntaxListOfDeclarationWithElements(positionedNode: TypeScript.ISyntaxNode) { - var node = positionedNode; - var elementsList: TypeScript.ISyntaxNodeOrToken[]; - var block: TypeScript.BlockSyntax; - - switch (node.kind()) { - case TypeScript.SyntaxKind.ModuleDeclaration: - elementsList = (node).moduleElements; - break; - - case TypeScript.SyntaxKind.ClassDeclaration: - elementsList = (node).classElements; - break; - - case TypeScript.SyntaxKind.FunctionDeclaration: - block = (node).block; - break; - - case TypeScript.SyntaxKind.ConstructorDeclaration: - block = (node).block; - break; - - case TypeScript.SyntaxKind.MemberFunctionDeclaration: - block = (node).block; - break; - - case TypeScript.SyntaxKind.GetAccessor: - block = (node).block; - break; - - case TypeScript.SyntaxKind.SetAccessor: - block = (node).block; - break; - - case TypeScript.SyntaxKind.FunctionExpression: - block = (node).block; - break; - - case TypeScript.SyntaxKind.ParenthesizedArrowFunctionExpression: - block = (node).block; - break; - - case TypeScript.SyntaxKind.SimpleArrowFunctionExpression: - block = (node).block; - break; - - default: - throw TypeScript.Errors.argument('positionNode', 'unknown node kind in getSyntaxListOfDeclarationWithElements'); - } - - var parentElement: TypeScript.ISyntaxElement = positionedNode; - if (block) { - parentElement = block; - elementsList = block.statements; - } - - return elementsList; - } - - private canHaveBreakpointInDeclaration(positionedNode: TypeScript.ISyntaxNode) { - return positionedNode && !TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(positionedNode); - } - - private breakpointSpanOfDeclarationWithElements(positionedNode: TypeScript.ISyntaxNode): TextSpan { - if (!this.canHaveBreakpointInDeclaration(positionedNode)) { - return null; - } - - // If inside another module the whole declaration is debuggable - var node = positionedNode; - var moduleSyntax = positionedNode; - if ((SyntaxUtilities.isModuleElement(node) && Syntax.containingNode(positionedNode).kind() != TypeScript.SyntaxKind.SourceUnit) || - SyntaxUtilities.isClassElement(node) || - (moduleSyntax.kind() == TypeScript.SyntaxKind.ModuleDeclaration && moduleSyntax.name - && moduleSyntax.name.kind() == TypeScript.SyntaxKind.QualifiedName)) { - return createBreakpointSpanInfo(positionedNode); - } - else { - // Try to get the breakpoint in first element declaration - return this.breakpointSpanOfFirstChildOfSyntaxList(this.getSyntaxListOfDeclarationWithElements(positionedNode)); - } - } - - private canHaveBreakpointInVariableDeclarator(varDeclaratorNode: TypeScript.ISyntaxNode) { - if (!varDeclaratorNode || TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(varDeclaratorNode)) { - return false; - } - - var varDeclaratorSyntax = varDeclaratorNode; - return !!varDeclaratorSyntax.equalsValueClause; - } - - private breakpointSpanOfVariableDeclarator(varDeclaratorNode: TypeScript.ISyntaxNode): TextSpan { - if (!this.canHaveBreakpointInVariableDeclarator(varDeclaratorNode)) { - return null; - } - - var container = Syntax.containingNode(varDeclaratorNode); - if (container && container.kind() == TypeScript.SyntaxKind.VariableDeclaration) { - var parentDeclaratorsList = varDeclaratorNode.parent; - // If this is the first declarator in the list use the declaration instead - if (parentDeclaratorsList && childAt(parentDeclaratorsList, 0) == varDeclaratorNode) { - return this.breakpointSpanOfVariableDeclaration(container); - } - - // Create breakpoint on this var declarator - if (this.canHaveBreakpointInVariableDeclarator(varDeclaratorNode)) { - return createBreakpointSpanInfo(varDeclaratorNode); - } - else { - return null; - } - } - else if (container) { - // Member Variable syntax - return this.breakpointSpanOfMemberVariableDeclaration(container); - } - - return null; - } - - private canHaveBreakpointInVariableDeclaration(varDeclarationNode: TypeScript.ISyntaxNode) { - if (!varDeclarationNode || TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(varDeclarationNode)) { - return false; - } - - var varDeclarationSyntax = varDeclarationNode; - var containerChildren = varDeclarationSyntax.variableDeclarators; - if (!containerChildren || childCount(containerChildren) == 0) { - return false; - } - - var child = childAt(containerChildren, 0); - if (isNode(child)) { - return this.canHaveBreakpointInVariableDeclarator(child); - } - - return false; - } - - private breakpointSpanOfVariableDeclaration(varDeclarationNode: TypeScript.ISyntaxNode): TextSpan { - if (!this.canHaveBreakpointInDeclaration(varDeclarationNode)) { - return null; - } - - var container = Syntax.containingNode(varDeclarationNode); - var varDeclarationSyntax = varDeclarationNode; - var varDeclarators = varDeclarationSyntax.variableDeclarators; - - if (container && container.kind() == TypeScript.SyntaxKind.VariableStatement) { - return this.breakpointSpanOfVariableStatement(container); - } - - if (this.canHaveBreakpointInVariableDeclaration(varDeclarationNode)) { - return createBreakpointSpanInfoWithLimChar(varDeclarationNode, end(childAt(varDeclarators, 0))); - } - else { - return null; - } - } - - private canHaveBreakpointInVariableStatement(varStatementNode: TypeScript.ISyntaxNode) { - if (!varStatementNode || TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(varStatementNode)) { - return false; - } - - var variableStatement = varStatementNode; - return this.canHaveBreakpointInVariableDeclaration(variableStatement.variableDeclaration); - } - - private breakpointSpanOfVariableStatement(varStatementNode: TypeScript.ISyntaxNode): TextSpan { - if (!this.canHaveBreakpointInVariableStatement(varStatementNode)) { - return null; - } - - var variableStatement = varStatementNode; - var variableDeclaration = variableStatement.variableDeclaration; - var varDeclarationSyntax = variableDeclaration; - var varDeclarators = varDeclarationSyntax.variableDeclarators; - return createBreakpointSpanInfoWithLimChar(varStatementNode, end(childAt(varDeclarators, 0))); - } - - private breakpointSpanOfParameter(parameterNode: TypeScript.ISyntaxNode): TextSpan { - if (parameterNode.parent.kind() === SyntaxKind.SimpleArrowFunctionExpression) { - return this.breakpointSpanOfNode(parameterNode.parent); - } - - if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(parameterNode)) { - return null; - } - - var parameterSyntax = parameterNode; - if (parameterSyntax.dotDotDotToken || parameterSyntax.equalsValueClause || parameterSyntax.modifiers.length > 0) { - return createBreakpointSpanInfo(parameterNode); - } - else { - return null; - } - } - - private breakpointSpanOfMemberVariableDeclaration(memberVarDeclarationNode: TypeScript.ISyntaxNode): TextSpan { - if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(memberVarDeclarationNode)) { - return null; - } - - var memberVariableDeclaration = memberVarDeclarationNode; - if (this.canHaveBreakpointInVariableDeclarator(memberVariableDeclaration.variableDeclarator)) { - return createBreakpointSpanInfo(memberVarDeclarationNode, memberVariableDeclaration.modifiers, memberVariableDeclaration.variableDeclarator); - } - else { - return null; - } - } - - private breakpointSpanOfImportDeclaration(importDeclarationNode: TypeScript.ISyntaxNode): TextSpan { - if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(importDeclarationNode)) { - return null; - } - - var importSyntax = importDeclarationNode; - return createBreakpointSpanInfo(importDeclarationNode, importSyntax.modifiers, importSyntax.importKeyword, importSyntax.identifier, importSyntax.equalsToken, importSyntax.moduleReference); - } - - private breakpointSpanOfEnumDeclaration(enumDeclarationNode: TypeScript.ISyntaxNode): TextSpan { - if (!this.canHaveBreakpointInDeclaration(enumDeclarationNode)) { - return null; - } - - return createBreakpointSpanInfo(enumDeclarationNode); - } - - private breakpointSpanOfFirstEnumElement(enumDeclarationNode: TypeScript.ISyntaxNode): TextSpan { - var enumDeclarationSyntax = enumDeclarationNode; - var enumElements = enumDeclarationSyntax.enumElements; - if (enumElements && childCount(enumElements)) { - return this.breakpointSpanOf(childAt(enumElements, 0)); - } - - return null; - } - - private breakpointSpanOfEnumElement(enumElementNode: TypeScript.ISyntaxNode): TextSpan { - if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(enumElementNode)) { - return null; - } - - return createBreakpointSpanInfo(enumElementNode); - } - - private breakpointSpanOfIfStatement(ifStatementNode: TypeScript.ISyntaxNode): TextSpan { - var ifStatement = ifStatementNode; - return createBreakpointSpanInfo(ifStatementNode, ifStatement.ifKeyword, ifStatement.openParenToken, ifStatement.condition, ifStatement.closeParenToken); - } - - private breakpointSpanOfElseClause(elseClauseNode: TypeScript.ISyntaxNode): TextSpan { - var elseClause = elseClauseNode; - return this.breakpointSpanOf(elseClause.statement); - } - - private breakpointSpanOfForInStatement(forInStatementNode: TypeScript.ISyntaxNode): TextSpan { - var forInStatement = forInStatementNode; - return createBreakpointSpanInfo(forInStatementNode, forInStatement.forKeyword, forInStatement.openParenToken, forInStatement.variableDeclaration, - forInStatement.left, forInStatement.inKeyword, forInStatement.expression, forInStatement.closeParenToken); - } - - private breakpointSpanOfForStatement(forStatementNode: TypeScript.ISyntaxNode): TextSpan { - var forStatement = forStatementNode; - return this.breakpointSpanOf(forStatement.variableDeclaration - ? forStatement.variableDeclaration - : forStatement.initializer); - } - - private breakpointSpanOfWhileStatement(whileStatementNode: TypeScript.ISyntaxNode): TextSpan { - var whileStatement = whileStatementNode; - return createBreakpointSpanInfo(whileStatementNode, whileStatement.whileKeyword, whileStatement.openParenToken, whileStatement.condition, whileStatement.closeParenToken); - } - - private breakpointSpanOfDoStatement(doStatementNode: TypeScript.ISyntaxNode): TextSpan { - var doStatement = doStatementNode; - return createBreakpointSpanInfo(doStatementNode, doStatement.whileKeyword, doStatement.openParenToken, doStatement.condition, doStatement.closeParenToken); - } - - private breakpointSpanOfSwitchStatement(switchStatementNode: TypeScript.ISyntaxNode): TextSpan { - var switchStatement = switchStatementNode; - return createBreakpointSpanInfo(switchStatementNode, switchStatement.switchKeyword, switchStatement.openParenToken, switchStatement.expression, switchStatement.closeParenToken); - } - - private breakpointSpanOfFirstStatementOfFirstCaseClause(switchStatementNode: TypeScript.ISyntaxNode): TextSpan { - var switchStatement = switchStatementNode; - if (switchStatement.switchClauses && switchStatement.switchClauses.length == 0) { - return null; - } - - var switchClauses = switchStatement.switchClauses; - if (switchClauses.length == 0) { - return null; - } - - var firstCaseClause = switchClauses[0]; - var statements = firstCaseClause.statements; - - return this.breakpointSpanOfFirstChildOfSyntaxList(statements); - } - - private breakpointSpanOfLastStatementOfLastCaseClause(switchStatementNode: TypeScript.ISyntaxNode): TextSpan { - var switchStatement = switchStatementNode; - if (switchStatement.switchClauses && switchStatement.switchClauses.length == 0) { - return null; - } - - var switchClauses = switchStatement.switchClauses; - if (switchClauses.length == 0) { - return null; - } - - var lastClauseNode = switchClauses[switchClauses.length - 1]; - var statements = lastClauseNode.statements; - - return this.breakpointSpanOfLastChildOfSyntaxList(statements); - } - - private breakpointSpanOfCaseSwitchClause(caseClauseNode: TypeScript.ISyntaxNode): TextSpan { - var caseSwitchClause = caseClauseNode; - return this.breakpointSpanOfFirstChildOfSyntaxList(caseSwitchClause.statements); - } - - private breakpointSpanOfDefaultSwitchClause(defaultSwithClauseNode: TypeScript.ISyntaxNode): TextSpan { - var defaultSwitchClause = defaultSwithClauseNode; - return this.breakpointSpanOfFirstChildOfSyntaxList(defaultSwitchClause.statements); - } - - private breakpointSpanOfWithStatement(withStatementNode: TypeScript.ISyntaxNode): TextSpan { - var withStatement = withStatementNode; - return this.breakpointSpanOf(withStatement.statement); - } - - private breakpointSpanOfTryStatement(tryStatementNode: TypeScript.ISyntaxNode): TextSpan { - var tryStatement = tryStatementNode; - return this.breakpointSpanOfFirstStatementInBlock(tryStatement.block); - } - - private breakpointSpanOfCatchClause(catchClauseNode: TypeScript.ISyntaxNode): TextSpan { - var catchClause = catchClauseNode; - return createBreakpointSpanInfo(catchClauseNode, catchClause.catchKeyword, catchClause.openParenToken, catchClause.identifier, catchClause.typeAnnotation, catchClause.closeParenToken); - } - - private breakpointSpanOfFinallyClause(finallyClauseNode: TypeScript.ISyntaxNode): TextSpan { - var finallyClause = finallyClauseNode; - return this.breakpointSpanOfFirstStatementInBlock(finallyClause.block); - } - - private breakpointSpanOfParenthesizedArrowFunctionExpression(arrowFunctionExpression: ParenthesizedArrowFunctionExpressionSyntax): TextSpan { - if (arrowFunctionExpression.block) { - return this.breakpointSpanOfFirstStatementInBlock(arrowFunctionExpression.block); - } - else { - return this.breakpointSpanOf(arrowFunctionExpression.expression); - } - } - - private breakpointSpanOfSimpleArrowFunctionExpression(arrowFunctionExpression: SimpleArrowFunctionExpressionSyntax): TextSpan { - if (arrowFunctionExpression.block) { - return this.breakpointSpanOfFirstStatementInBlock(arrowFunctionExpression.block); - } - else { - return this.breakpointSpanOf(arrowFunctionExpression.expression); - } - } - - private breakpointSpanOfContainingNode(positionedElement: ISyntaxElement): TextSpan { - var current = positionedElement.parent; - while (!isNode(current)) { - current = current.parent; - } - - return this.breakpointSpanOf(current); - } - - private breakpointSpanIfStartsOnSameLine(positionedElement: TypeScript.ISyntaxElement): TextSpan { - if (positionedElement && this.posLine == this.lineMap.getLineNumberFromPosition(start(positionedElement))) { - return this.breakpointSpanOf(positionedElement); - } - - return null; - } - - public breakpointSpanOf(positionedElement: TypeScript.ISyntaxElement): TextSpan { - if (!positionedElement) { - return null; - } - - for (var containingNode = Syntax.containingNode(positionedElement); containingNode != null; containingNode = Syntax.containingNode(containingNode)) { - if (containingNode.kind() == TypeScript.SyntaxKind.TypeAnnotation) { - return this.breakpointSpanIfStartsOnSameLine(containingNode); - } - } - - var element = positionedElement; - - // Syntax node - if (isNode(element)) { - return this.breakpointSpanOfNode(positionedElement); - } - - // Token - if (isToken(element)) { - return this.breakpointSpanOfToken(positionedElement); - } - - // List - // Separated List - return this.breakpointSpanOfContainingNode(positionedElement); - } - } - - export function getBreakpointLocation(syntaxTree: TypeScript.SyntaxTree, askedPos: number): TextSpan { - // Cannot set breakpoint in dts file - if (TypeScript.isDTSFile(syntaxTree.fileName())) { - return null; - } - - var sourceUnit = syntaxTree.sourceUnit(); - var positionedToken = TypeScript.findToken(sourceUnit, askedPos); - - var lineMap = syntaxTree.lineMap(); - var posLine = lineMap.getLineNumberFromPosition(askedPos); - var tokenStartLine = lineMap.getLineNumberFromPosition(start(positionedToken)); - if (posLine < tokenStartLine) { - return null; - } - - var breakpointResolver = new BreakpointResolver(posLine, lineMap); - return breakpointResolver.breakpointSpanOf(positionedToken); - } -} +/// module ts.Breakpoints { /**