/// <summary> /// Initializes the contents of the statement. /// </summary> private void Initialize() { this.body.Value = this.FindFirstChild <BlockStatement>(); if (this.body.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } // Look for the try-statement that this finally-statement is attached to. this.tryStatement.Value = null; for (CodeUnit c = this.FindPreviousSibling(); c != null; c = c.FindNext()) { if (c.Is(StatementType.Try)) { this.tryStatement.Value = (TryStatement)c; } else if (!c.Is(StatementType.Catch) && (!c.Is(CodeUnitType.LexicalElement) || c.Is(LexicalElementType.Token))) { break; } } if (this.tryStatement.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } }
/// <summary> /// Initializes the contents of the statement. /// </summary> private void Initialize() { this.body.Value = this.FindFirstChild <BlockStatement>(); if (this.body.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } List <CatchStatement> catchList = new List <CatchStatement>(); for (CodeUnit c = this.FindNextSibling(); c != null; c = c.FindNextSibling()) { if (c.Is(StatementType.Catch)) { catchList.Add((CatchStatement)c); } else if (c.Is(StatementType.Finally)) { this.finallyStatement.Value = (FinallyStatement)c; break; } else if (!c.Is(CodeUnitType.LexicalElement) || c.Is(LexicalElementType.Token)) { break; } } this.catchStatements.Value = catchList.AsReadOnly(); }
/// <summary> /// Walks through the children of the given code unit. /// </summary> /// <param name="codeUnit">The code unit to walk.</param> /// <param name="callback">Callback executed when a code unit is visited.</param> /// <param name="parentElement">The parent element of the code unit, if any.</param> /// <param name="parentStatement">The parent statement of the code unit, if any.</param> /// <param name="parentExpression">The parent expression of the code unit, if any.</param> /// <param name="parentQueryClause">The parent query clause of the code unit, if any.</param> /// <param name="parentToken">The parent token of the code unit, if any.</param> /// <param name="context">Optional context.</param> /// <param name="codeUnitTypes">The types of code units to visit.</param> /// <returns>Returns true to continue walking, false otherwise.</returns> private static bool WalkCodeUnitChildren( CodeUnit codeUnit, CodeUnitVisitor <T> callback, Element parentElement, Statement parentStatement, Expression parentExpression, QueryClause parentQueryClause, Token parentToken, T context, CodeUnitType[] codeUnitTypes) { Param.AssertNotNull(codeUnit, "codeUnit"); Param.Ignore(codeUnitTypes); Param.AssertNotNull(callback, "callback"); Param.Ignore(parentElement); Param.Ignore(parentStatement); Param.Ignore(parentExpression); Param.Ignore(parentQueryClause); Param.Ignore(parentToken); Param.Ignore(context); if (codeUnit.Children != null && codeUnit.Children.Count > 0) { for (CodeUnit child = codeUnit.FindFirstChild(); child != null; child = child.FindNextSibling()) { if (!WalkCodeUnit(child, callback, parentElement, parentStatement, parentExpression, parentQueryClause, parentToken, context, codeUnitTypes)) { return(false); } } } return(true); }
/// <summary> /// Attaches this proxy to its code unit. /// </summary> /// <param name="codeUnit">The code unit to attach to.</param> public void Attach(CodeUnit codeUnit) { Param.AssertNotNull(codeUnit, "codeUnit"); this.target = codeUnit; CsLanguageService.Debug.Assert(this.document != null || codeUnit.Is(ElementType.Document), "Only a document element can have a proxy with a null document property."); }
/// <summary> /// Gets the name of the element. /// </summary> /// <returns>The name of the element.</returns> protected override string GetElementName() { CodeUnit start = this.Children.First; if (!this.ContainsModifier(TokenType.Implicit, TokenType.Explicit)) { // Get the return type. start = this.FindFirstChild <TypeToken>(); } if (start != null) { Token next = start.FindNextSiblingToken(); if (next != null) { if (next.Is(TokenType.Operator)) { // The next token is the operator name. Token operatorName = next.FindNextSiblingToken(); if (operatorName != null) { return("operator " + operatorName.Text); } } else { // This is a regular method. return(next.Text); } } } throw new SyntaxException(this.Document, this.LineNumber); }
/// <summary> /// Initializes the contents of the expression. /// </summary> private void Initialize() { this.value.Value = null; for (CodeUnit c = this.FindFirstChild(); c != null; c = c.FindNextSibling()) { if (c.Is(OperatorType.Increment)) { this.value.Value = c.FindNextSiblingExpression(); if (this.value.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } break; } else if (c.Is(CodeUnitType.Expression)) { this.value.Value = (Expression)c; var operatorSymbol = c.FindNextSibling <IncrementOperator>(); if (operatorSymbol == null) { throw new SyntaxException(this.Document, this.LineNumber); } break; } } if (this.value.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } }
/// <summary> /// Extracts a variable from the clause. /// </summary> /// <param name="firstToken">The first token of the variable.</param> /// <param name="allowTypelessVariable">Indicates whether to allow a variable with no type defined.</param> /// <param name="onlyTypelessVariable">Indicates whether to only get a typeless variable.</param> /// <returns>Returns the variable.</returns> protected static QueryClauseVariable ExtractQueryVariable(Token firstToken, bool allowTypelessVariable, bool onlyTypelessVariable) { Param.RequireNotNull(firstToken, "firstToken"); Param.Ignore(allowTypelessVariable); Param.Ignore(onlyTypelessVariable); if (onlyTypelessVariable || !firstToken.Is(TokenType.Type)) { // In this case there is no type, only an identifier. return(new QueryClauseVariable(null, firstToken.Text, firstToken.Location, firstToken.Generated)); } else { TypeToken type = (TypeToken)firstToken; // Attempt to get the identifier token coming after the type token. Token identifier = firstToken.FindNextSiblingToken(); if (identifier == null || identifier.TokenType != TokenType.Literal) { CsLanguageService.Debug.Assert(allowTypelessVariable, "The clause does not allow typeless variables. The parser should have thrown syntax exception already."); return(new QueryClauseVariable(null, type.Text, type.Location, type.Generated)); } else { // There is a type and an identifier. return(new QueryClauseVariable(type, identifier.Text, CodeUnit.JoinLocations(type, identifier), type.Generated || identifier.Generated)); } } }
/// <summary> /// Creates and starts a code walker. /// </summary> /// <param name="root">The root code unit to walk through.</param> /// <param name="callback">Callback executed when a code unit is visited.</param> /// <param name="context">The optional visitor context data.</param> /// <param name="codeUnitTypes">The types of code units to visit.</param> public static void Start(CodeUnit root, CodeUnitVisitor <T> callback, T context, params CodeUnitType[] codeUnitTypes) { Param.AssertNotNull(root, "root"); Param.AssertNotNull(callback, "callback"); Param.Ignore(context); Param.Ignore(codeUnitTypes); WalkCodeUnit(root, callback, context, codeUnitTypes); }
/// <summary> /// Initializes the contents of the statement. /// </summary> private void Initialize() { OpenParenthesisToken openParen = this.FindFirstChild <OpenParenthesisToken>(); if (openParen == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.switchExpression.Value = openParen.FindNextSiblingExpression(); if (this.switchExpression.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } CloseParenthesisToken closeParen = this.switchExpression.Value.FindNextSibling <CloseParenthesisToken>(); if (closeParen == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.defaultStatement.Value = null; List <SwitchCaseStatement> caseList = new List <SwitchCaseStatement>(); for (CodeUnit c = closeParen.FindNextSibling(); c != null; c = c.FindNext()) { if (c.Is(StatementType.SwitchCase)) { caseList.Add((SwitchCaseStatement)c); } else if (c.Is(StatementType.SwitchDefault)) { if (this.defaultStatement.Value != null) { throw new SyntaxException(this.Document, this.LineNumber); } this.defaultStatement.Value = (SwitchDefaultStatement)c; break; } else if (c.Is(TokenType.OpenCurlyBracket)) { if (caseList.Count > 0 || this.defaultStatement.Value != null) { throw new SyntaxException(this.Document, this.LineNumber); } } else if (!c.Is(CodeUnitType.LexicalElement) || c.Is(LexicalElementType.Token)) { break; } } this.caseStatements.Value = caseList.AsReadOnly(); }
/// <summary> /// Initializes a new instance of the CodeUnitLocationMarker class. /// </summary> /// <param name="codeUnit">The code unit.</param> internal CodeUnitLocationMarker(CodeUnit codeUnit) { Param.AssertNotNull(codeUnit, "codeUnit"); this.Parent = codeUnit.Parent; this.NextSibling = codeUnit.LinkNode.Next; this.PreviousSibling = codeUnit.LinkNode.Previous; if (this.Parent == null && this.NextSibling == null && this.PreviousSibling == null) { throw new ArgumentException("codeUnit"); } }
/// <summary> /// Moves to the next matching item in the collection. /// </summary> private void MoveToNextItem() { for (CodeUnit item = this.currentItem == null ? this.collection.First : this.currentItem.LinkNode.Next; item != null; item = item.LinkNode.Next) { T convertedItem = item as T; if (convertedItem != null) { this.currentItem = convertedItem; return; } } this.currentItem = null; }
/// <summary> /// Finds the last token in the element's declaration. /// </summary> /// <returns>Returns the last token or null.</returns> private Token FindLastDeclarationToken() { CodeUnit previousToken = this.FirstDeclarationToken; for (CodeUnit item = previousToken; item != null; item = item.FindNextDescendentOf(this)) { if (item.Is(CodeUnitType.Attribute)) { // Move to the end of the attribute. item = item.FindLastDescendent(); } else { // These types indicate that we've gone past the end of the declaration. if (item.Is(TokenType.OpenCurlyBracket) || item.Is(TokenType.Semicolon) || item.Is(OperatorType.Equals)) { break; } // If we find an opening parenthesis, square bracket, etc., jump to its corresponding closing bracket. if (item.Is(TokenType.OpenParenthesis) || item.Is(TokenType.OpenGenericBracket) || item.Is(TokenType.OpenSquareBracket)) { item = ((OpenBracketToken)item).MatchingBracket; } if (item.Is(LexicalElementType.Token)) { previousToken = item; } } } if (previousToken != null) { while (previousToken.Parent != null && previousToken.Parent.Is(LexicalElementType.Token)) { previousToken = previousToken.Parent; } } return((Token)previousToken); }
/// <summary> /// Finds the first token in the element's declaration. /// </summary> /// <returns>Returns the first token or null.</returns> private Token FindFirstDeclarationToken() { for (CodeUnit item = this.FindFirstDescendent(); item != null; item = item.FindNextDescendentOf(this)) { if (item.Is(CodeUnitType.Attribute)) { // Move to the end of the attribute. item = item.FindLastDescendent(); } else if (item.Is(LexicalElementType.Token)) { return((Token)item); } } return(null); }
/// <summary> /// Initializes the contents of the statement. /// </summary> private void Initialize() { OpenParenthesisToken openParen = this.FindFirstChild <OpenParenthesisToken>(); if (openParen == null) { this.condition.Value = null; this.body.Value = this.FindFirstChildStatement(); } else { this.condition.Value = openParen.FindNextSiblingExpression(); if (this.condition.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } CloseParenthesisToken closeParen = this.condition.Value.FindNextSibling <CloseParenthesisToken>(); if (closeParen == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.body.Value = closeParen.FindNextSiblingStatement(); } if (this.body.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } // Look for another attached else statement. this.elseStatement.Value = null; for (CodeUnit c = this.FindNextSibling(); c != null; c = c.FindNext()) { if (c.Is(StatementType.Else)) { this.elseStatement.Value = (ElseStatement)c; } else if (!c.Is(CodeUnitType.LexicalElement) || c.Is(LexicalElementType.Token)) { break; } } }
/// <summary> /// Finds and gathers the initializer expressions for the for statement. /// </summary> /// <param name="start">The code unit in front of the initializers.</param> /// <returns>Returns the collection of initializers.</returns> private ICollection <Expression> FindIterators(CodeUnit start) { Param.AssertNotNull(start, "start"); List <Expression> expressions = new List <Expression>(); bool comma = true; for (CodeUnit c = start.FindNextSibling(); c != null; c = c.FindNextSibling()) { if (!c.Is(CodeUnitType.LexicalElement) || c.Is(LexicalElementType.Token)) { if (c.Is(TokenType.CloseParenthesis)) { return(expressions.AsReadOnly()); } else if (comma) { comma = false; if (c.Is(CodeUnitType.Expression)) { expressions.Add((Expression)c); } else { throw new SyntaxException(this.Document, this.LineNumber); } } else { if (c.Is(TokenType.Comma)) { comma = true; } else { throw new SyntaxException(this.Document, this.LineNumber); } } } } throw new SyntaxException(this.Document, this.LineNumber); }
/// <summary> /// Finds the condition expression if there is one. /// </summary> /// <param name="start">The code unit in front of the expression.</param> /// <returns>Returns the condition expression or null.</returns> private Expression FindCondition(CodeUnit start) { Param.AssertNotNull(start, "start"); for (CodeUnit c = start.FindNextSibling(); c != null; c = c.FindNextSibling()) { if (!c.Is(CodeUnitType.LexicalElement) || c.Is(LexicalElementType.Token)) { if (c.Is(TokenType.Semicolon)) { return(null); } if (c.Is(CodeUnitType.Expression)) { return((Expression)c); } break; } } throw new SyntaxException(this.Document, this.LineNumber); }
/// <summary> /// Visits the given code unit and walks through its children. /// </summary> /// <param name="codeUnit">The code unit to walk.</param> /// <param name="callback">Callback executed when a code unit is visited.</param> /// <param name="context">Optional context.</param> /// <param name="codeUnitTypes">The types of code units to visit.</param> /// <returns>Returns true to continue walking, false otherwise.</returns> private static bool WalkCodeUnit(CodeUnit codeUnit, CodeUnitVisitor <T> callback, T context, CodeUnitType[] codeUnitTypes) { Param.AssertNotNull(codeUnit, "codeUnit"); Param.AssertNotNull(callback, "callback"); Param.Ignore(context); Param.Ignore(codeUnitTypes); // Gather up the various parent types for this code unit. Element parentElement = null; Statement parentStatement = null; Expression parentExpression = null; QueryClause parentQueryClause = null; Token parentToken = null; CodeUnit parent = codeUnit.Parent; while (parent != null) { switch (parent.CodeUnitType) { case CodeUnitType.Element: if (parentElement != null) { parentElement = (Element)parent; // Elements are the top-level code units, so we can stop now. parent = null; } break; case CodeUnitType.Statement: if (parentStatement != null) { parentStatement = (Statement)parent; } break; case CodeUnitType.Expression: if (parentExpression != null) { parentExpression = (Expression)parent; } break; case CodeUnitType.QueryClause: if (parentQueryClause != null) { parentQueryClause = (QueryClause)parent; } break; case CodeUnitType.LexicalElement: if (parentToken != null) { parentToken = (Token)parent; } break; } parent = parent == null ? null : parent.Parent; } return(WalkCodeUnit(codeUnit, callback, parentElement, parentStatement, parentExpression, parentQueryClause, parentToken, context, codeUnitTypes)); }
/// <summary> /// Reads the next expression from a conditional preprocessor directive. /// </summary> /// <param name="document">The parent document.</param> /// <param name="parentProxy">Represents the parent item.</param> /// <param name="previousPrecedence">The precedence of the expression just before this one.</param> /// <returns>Returns the expression.</returns> private Expression GetNextConditionalPreprocessorExpression(CsDocument document, CodeUnitProxy parentProxy, ExpressionPrecedence previousPrecedence) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parentProxy, "parentProxy"); Param.Ignore(previousPrecedence); // Move past comments and whitepace. this.AdvanceToNextConditionalDirectiveCodeSymbol(parentProxy); // Saves the next expression. Expression expression = null; CodeUnitProxy expressionExtensionProxy = new CodeUnitProxy(this.document); // Get the next symbol. Symbol symbol = this.symbols.Peek(1); if (symbol != null) { switch (symbol.SymbolType) { case SymbolType.Other: expression = this.GetConditionalPreprocessorConstantExpression(expressionExtensionProxy); break; case SymbolType.Not: expression = this.GetConditionalPreprocessorNotExpression(expressionExtensionProxy); break; case SymbolType.OpenParenthesis: expression = this.GetConditionalPreprocessorParenthesizedExpression(expressionExtensionProxy); break; case SymbolType.False: expression = this.CreateLiteralExpression(expressionExtensionProxy, symbol.SymbolType, TokenType.False); break; case SymbolType.True: expression = this.CreateLiteralExpression(expressionExtensionProxy, symbol.SymbolType, TokenType.True); break; default: throw new SyntaxException(this.document, symbol.LineNumber); } } // Gather up all extensions to this expression. Expression topLevelExpression = expression; // Gather up all extensions to this expression. while (expression != null) { // Check if there is an extension to this expression. Expression extension = this.GetConditionalPreprocessorExpressionExtension(expressionExtensionProxy, expression, previousPrecedence); if (extension != null) { // Save the expression extension proxy and create a new one for the next expression extension. expressionExtensionProxy = new CodeUnitProxy(this.document); expressionExtensionProxy.Children.Add(expression); topLevelExpression = expression; } else { // There are no more extensions. break; } } // There are no more extensions. The children of the current top-level expression extension proxy // should actually be children of the parent proxy, since there are no more extensions. CodeUnit unit = expressionExtensionProxy.Children.First; while (unit != null) { CodeUnit next = unit.LinkNode.Next; unit.Detach(); unit.LinkNode.ContainingList = null; parentProxy.Children.Add(unit); unit = next; } // Return the expression. return(topLevelExpression); }
/// <summary> /// Initializes the contents of the statement. /// </summary> private void Initialize() { CodeUnit start = this.FindFirstChild <OpenParenthesisToken>(); if (start == null) { throw new SyntaxException(this.Document, this.LineNumber); } Expression expression = start.FindNextSiblingExpression(); if (expression != null) { this.catchExpression.Value = expression; if (expression.ExpressionType == ExpressionType.Literal) { this.exceptionType.Value = CodeParser.ExtractTypeTokenFromLiteralExpression((LiteralExpression)expression); } else if (expression.ExpressionType == ExpressionType.VariableDeclaration) { VariableDeclarationExpression variableDeclaration = (VariableDeclarationExpression)expression; this.exceptionType.Value = variableDeclaration.Type; foreach (VariableDeclaratorExpression declarator in variableDeclaration.Declarators) { this.identifier.Value = declarator.Identifier.Text; break; } } start = expression; } CloseParenthesisToken closeParen = start.FindNextSibling <CloseParenthesisToken>(); if (closeParen == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.body.Value = closeParen.FindNextSibling <BlockStatement>(); if (this.body.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } // Look for the try-statement that this catch-statement is attached to. this.tryStatement.Value = null; for (CodeUnit c = this.FindPreviousSibling(); c != null; c = c.FindNext()) { if (c.Is(StatementType.Try)) { this.tryStatement.Value = (TryStatement)c; } else if (!c.Is(StatementType.Catch) && (!c.Is(CodeUnitType.LexicalElement) || c.Is(LexicalElementType.Token))) { break; } } if (this.tryStatement.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } }
/// <summary> /// Initializes the contents of the class. /// </summary> private void Initialize() { JoinToken @join = this.FindFirstChild <JoinToken>(); if (@join == null) { throw new SyntaxException(this.Document, this.LineNumber); } Token token = @join.FindNextSiblingToken(); if (token == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.rangeVariable.Value = ExtractQueryVariable(token, true, false); if (this.rangeVariable.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } InToken @in = token.FindNextSibling <InToken>(); if (@in == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.inExpression.Value = @in.FindNextSiblingExpression(); if (this.inExpression.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } OnToken @on = this.inExpression.Value.FindNextSibling <OnToken>(); if (@on == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.onKeyExpression.Value = @on.FindNextSiblingExpression(); if (this.onKeyExpression.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } EqualsToken equals = this.onKeyExpression.Value.FindNextSibling <EqualsToken>(); if (equals == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.equalsKeyExpression.Value = equals.FindNextSiblingExpression(); if (this.equalsKeyExpression.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.intoVariable.Value = null; for (CodeUnit c = this.equalsKeyExpression.Value.FindNextSibling(); c != null; c = c.FindNextSibling()) { if (c.Is(TokenType.Into)) { token = c.FindNextSiblingToken(); if (token == null) { throw new SyntaxException(this.Document, this.LineNumber); } this.intoVariable.Value = ExtractQueryVariable(token, true, false); if (this.intoVariable.Value == null) { throw new SyntaxException(this.Document, this.LineNumber); } break; } else if (!c.Is(CodeUnitType.LexicalElement) || c.Is(LexicalElementType.Token)) { break; } } }
/// <summary> /// Visits the given code unit and walks through its children. /// </summary> /// <param name="codeUnit">The code unit to walk.</param> /// <param name="callback">Callback executed when a code unit is visited.</param> /// <param name="parentElement">The parent element of the code unit, if any.</param> /// <param name="parentStatement">The parent statement of the code unit, if any.</param> /// <param name="parentExpression">The parent expression of the code unit, if any.</param> /// <param name="parentQueryClause">The parent query clause of the code unit, if any.</param> /// <param name="parentToken">The parent token of the code unit, if any.</param> /// <param name="context">Optional context.</param> /// <param name="codeUnitTypes">The types of code units to visit.</param> /// <returns>Returns true to continue walking, false otherwise.</returns> private static bool WalkCodeUnit( CodeUnit codeUnit, CodeUnitVisitor <T> callback, Element parentElement, Statement parentStatement, Expression parentExpression, QueryClause parentQueryClause, Token parentToken, T context, CodeUnitType[] codeUnitTypes) { Param.AssertNotNull(codeUnit, "codeUnit"); Param.AssertNotNull(callback, "callback"); Param.Ignore(parentElement); Param.Ignore(parentStatement); Param.Ignore(parentExpression); Param.Ignore(parentQueryClause); Param.Ignore(parentToken); Param.Ignore(context); Param.Ignore(codeUnitTypes); if (CompareCodeUnitType(codeUnitTypes, codeUnit.CodeUnitType)) { if (!callback(codeUnit, parentElement, parentStatement, parentExpression, parentQueryClause, parentToken, context)) { return(false); } } if (codeUnit.Children != null && codeUnit.Children.Count > 0) { switch (codeUnit.CodeUnitType) { case CodeUnitType.Element: parentElement = (Element)codeUnit; break; case CodeUnitType.Statement: parentStatement = (Statement)codeUnit; break; case CodeUnitType.Expression: parentExpression = (Expression)codeUnit; break; case CodeUnitType.QueryClause: parentQueryClause = (QueryClause)codeUnit; break; case CodeUnitType.LexicalElement: if (codeUnit.Is(LexicalElementType.Token)) { parentToken = (Token)codeUnit; } break; } return(WalkCodeUnitChildren(codeUnit, callback, parentElement, parentStatement, parentExpression, parentQueryClause, parentToken, context, codeUnitTypes)); } return(true); }