internal static async Task <Document> AddAccessModifierAsync( Document document, SyntaxNode declaration, CancellationToken cancellationToken) { SyntaxNode oldRoot = await document.GetSyntaxRootAsync(cancellationToken); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken); SyntaxKind modifierKind = GetModifierKind(declaration, semanticModel, cancellationToken); SyntaxToken modifierToken = SyntaxFactory.Token(modifierKind).WithTrailingSpace(); SyntaxTokenList modifiers = declaration.GetDeclarationModifiers(); SyntaxNode newDeclaration = declaration; if (modifiers.Count > 0) { modifiers = modifiers .Replace(modifiers[0], modifiers[0].WithoutLeadingTrivia()) .Insert(0, modifierToken.WithLeadingTrivia(modifiers[0].LeadingTrivia)); } else { SyntaxNodeOrToken nodeOrToken = GetNodeOrToken(declaration); if ((nodeOrToken.IsNode && nodeOrToken.AsNode() == null) || (nodeOrToken.IsToken && nodeOrToken.AsToken().IsKind(SyntaxKind.None))) { Debug.Assert(false, ""); return(document); } modifiers = SyntaxFactory.TokenList(modifierToken.WithLeadingTrivia(nodeOrToken.GetLeadingTrivia())); if (nodeOrToken.IsNode) { newDeclaration = declaration.ReplaceNode( nodeOrToken.AsNode(), nodeOrToken.AsNode().WithoutLeadingTrivia()); } else { newDeclaration = declaration.ReplaceToken( nodeOrToken.AsToken(), nodeOrToken.AsToken().WithoutLeadingTrivia()); } } newDeclaration = GetNewDeclaration(newDeclaration, modifiers); SyntaxNode newRoot = oldRoot.ReplaceNode(declaration, newDeclaration); return(document.WithSyntaxRoot(newRoot)); }
private void NodeToJson(JsonWriter jw, SyntaxNodeOrToken node, Dictionary <SyntaxNodeOrToken, int> nodeToIdx) { jw.WriteStartObject(); jw.WritePropertyName("id"); jw.WriteValue(nodeToIdx[node]); jw.WritePropertyName("type"); jw.WriteValue(node.Kind().ToString()); if (node.IsKind(SyntaxKind.IdentifierName) || node.IsKind(SyntaxKind.PredefinedType) || RoslynUtils.IsSimpleLiteral(node) || node.IsToken || node.AsNode().ChildNodes().Count() == 0) { jw.WritePropertyName("value"); jw.WriteValue(node.ToString()); } else { jw.WritePropertyName("children"); jw.WriteStartArray(); foreach (var child in node.AsNode().ChildNodesAndTokens()) { if (!nodeToIdx.TryGetValue(child, out int idx)) { idx = int.MaxValue; } jw.WriteValue(idx); } jw.WriteEndArray(); } jw.WriteEndObject(); }
public override Match Run(SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.Kind() != SyntaxKind.Argument) return Match.NoMatch; var argument = (ArgumentSyntax) nodeOrToken.AsNode(); if (_variable.MinOccurrences == 1 && _variable.MaxOccurrences == 1) return Match.Success.WithSyntaxNodeOrToken(argument); var argumentList = argument.Parent as ArgumentListSyntax; if (argumentList == null) return Match.NoMatch; var currentIndex = argumentList.Arguments.IndexOf(argument); var availableCount = argumentList.Arguments.Count - currentIndex - _following; if (availableCount == 0) return Match.NoMatch; var captureCount = _variable.MaxOccurrences == null ? availableCount : Math.Min(availableCount, _variable.MaxOccurrences.Value); if (captureCount < _variable.MinOccurrences) return Match.NoMatch; var endIndex = currentIndex + captureCount - 1; var endArgument = argumentList.Arguments[endIndex]; return Match.Success.AddCapture(_variable, argument, endArgument); }
public Cursor MoveToFirstChild() { Debug.Assert(this.CurrentNodeOrToken.IsNode); // Just try to get the first node directly. This is faster than getting the list of // child nodes and tokens (which forces all children to be enumerated for the sake // of counting. It should always be safe to index the 0th element of a node. But // just to make sure that this is not a problem, we verify that the slotcount of the // node is greater than 0. var node = CurrentNodeOrToken.AsNode(); if (node.SlotCount > 0) { var child = Microsoft.CodeAnalysis.ChildSyntaxList.ItemInternal(node, 0); if (IsNonZeroWidthOrIsEndOfFile(child)) { return(new Cursor(child, 0)); } } // Fallback to enumerating all children. int index = 0; foreach (var child in this.CurrentNodeOrToken.ChildNodesAndTokens()) { if (IsNonZeroWidthOrIsEndOfFile(child)) { return(new Cursor(child, index)); } index++; } return(new Cursor()); }
public static void Dump(this SyntaxNodeOrToken nodeOrToken, TextWriter writer = null, int depth = 0) { const string indentString = " "; if (nodeOrToken.IsMissing) { return; } writer = writer ?? Console.Out; for (int i = 0; i < depth; i++) { writer.Write(indentString); } if (nodeOrToken.IsNode) { var node = nodeOrToken.AsNode(); writer.WriteLine("{0}: {1}", node.GetType().Name, node); foreach (var child in node.ChildNodesAndTokens()) { Dump(child, writer, depth + 1); } } else { var token = nodeOrToken.AsToken(); writer.WriteLine("{0}: {1}", token.Kind(), token); } }
/// <summary> /// Recursive method that "quotes" a SyntaxNode, SyntaxToken, SyntaxTrivia or other objects. /// </summary> /// <returns>A description of Roslyn API calls necessary to recreate the input object.</returns> private ApiCall Quote(object treeElement, string name = null) { if (treeElement is SyntaxTrivia) { return(QuoteTrivia((SyntaxTrivia)treeElement)); } if (treeElement is SyntaxToken) { return(QuoteToken((SyntaxToken)treeElement, name)); } if (treeElement is SyntaxNodeOrToken) { SyntaxNodeOrToken syntaxNodeOrToken = (SyntaxNodeOrToken)treeElement; if (syntaxNodeOrToken.IsNode) { return(QuoteNode(syntaxNodeOrToken.AsNode(), name)); } else { return(QuoteToken(syntaxNodeOrToken.AsToken(), name)); } } return(QuoteNode((SyntaxNode)treeElement, name)); }
private bool MatchesIgnoringAxis(SyntaxNodeOrToken nodeOrToken, SyntaxQuery query) { var node = nodeOrToken.AsNode(); if (node is ExpressionStatementSyntax statement && node.Kind() == ExpressionStatement) { return(MatchesIgnoringAxis(statement.Expression, query)); } if (node is SwitchSectionSyntax switchSection) { foreach (var label in switchSection.Labels) { if (MatchesSyntaxKindAndFilter(switchSection, label.Kind(), query)) { return(true); } } } if (node is PredefinedTypeSyntax predefinedType) { return(MatchesSyntaxKindAndFilter(predefinedType, predefinedType.Keyword.Kind(), query)); } return(MatchesSyntaxKindAndFilter(nodeOrToken, nodeOrToken.Kind(), query)); }
internal static double ComputeDistance(SyntaxNodeOrToken oldNodeOrToken, SyntaxNodeOrToken newNodeOrToken) { Debug.Assert(newNodeOrToken.IsToken == oldNodeOrToken.IsToken); double distance; if (oldNodeOrToken.IsToken) { var leftToken = oldNodeOrToken.AsToken(); var rightToken = newNodeOrToken.AsToken(); distance = ComputeDistance(leftToken, rightToken); Debug.Assert(!SyntaxFactory.AreEquivalent(leftToken, rightToken) || distance == ExactMatchDist); } else { var leftNode = oldNodeOrToken.AsNode(); var rightNode = newNodeOrToken.AsNode(); distance = ComputeDistance(leftNode, rightNode); Debug.Assert(!SyntaxFactory.AreEquivalent(leftNode, rightNode) || distance == ExactMatchDist); } return(distance); }
private static CompletionSyntax GetCompletionSyntax(SyntaxNodeOrToken nodeOrToken) { SyntaxNodeOrToken dot; SyntaxNode prefix = null; if (nodeOrToken.IsNode) { prefix = nodeOrToken.AsNode(); dot = nodeOrToken.GetPreviousSibling(); if (dot.Kind() != SyntaxKind.DotToken) { return(new CompletionSyntax(null, prefix)); } } else { if (nodeOrToken.Kind() != SyntaxKind.DotToken) { return(new CompletionSyntax(null, prefix)); } dot = nodeOrToken; } var previous = dot.GetPreviousSibling(); return(previous.IsNode ? new CompletionSyntax(previous.AsNode(), prefix) : new CompletionSyntax(null, prefix)); }
private static void CheckIfCommasAreAtTheSameLineAsThePreviousParameter(SyntaxNodeAnalysisContext context, SyntaxNodeOrTokenList nodeOrTokenList) { SyntaxNode previousNode = null; // If index is even we expecting parameter syntax node, otherwise we expecting comma token. for (int index = 0, count = nodeOrTokenList.Count; index < count; ++index) { SyntaxNodeOrToken nodeOrToken = nodeOrTokenList[index]; if (index % 2 == 0) { // We expecting node here if (nodeOrToken.IsToken) { return; } previousNode = nodeOrToken.AsNode(); } else { // We expecting token here if (nodeOrToken.IsNode) { return; } if (previousNode.GetEndLine() < nodeOrToken.GetLineSpan().StartLinePosition.Line) { var properties = TokenSpacingProperties.RemovePrecedingPreserveLayout; context.ReportDiagnostic(Diagnostic.Create(Descriptor, nodeOrToken.GetLocation(), properties)); } } } }
private void append(TreeViewItem _rootItem, SyntaxNode _node) { if (__treeView.Items.Count == 0) { __treeView.Items.Add(_rootItem); } ChildSyntaxList _children = _node.ChildNodesAndTokens(); ChildSyntaxList.Enumerator _enumerator = _children.GetEnumerator(); while (_enumerator.MoveNext()) { SyntaxNodeOrToken _syntaxElement = _enumerator.Current; if (_syntaxElement.IsNode) { SyntaxNode _childNode = _syntaxElement.AsNode(); TreeViewItem _childNodeItem = syntaxNodeItem(_childNode); _rootItem.Items.Add(_childNodeItem); append(_childNodeItem, _childNode); } else if (_syntaxElement.IsToken) { SyntaxToken _token = _syntaxElement.AsToken(); _rootItem.Items.Add(syntaxTokenItem(_token)); } } }
public static FileLinePositionSpan GetSpan(SyntaxNodeOrToken nodeOrToken) { var span = nodeOrToken.Span; if (nodeOrToken.IsNode) { var node = nodeOrToken.AsNode(); if (node is ConstructorDeclarationSyntax) { var constructorDeclarationNode = node as ConstructorDeclarationSyntax; span = constructorDeclarationNode.Identifier.Span; } else if (node is MethodDeclarationSyntax) { var methodDeclarationNode = node as MethodDeclarationSyntax; span = methodDeclarationNode.Identifier.Span; } else if (node is AccessorDeclarationSyntax) { var accessprDecl = node as AccessorDeclarationSyntax; span = accessprDecl.Keyword.Span; } else if (node is ObjectCreationExpressionSyntax) { var objectCreationExpression = node as ObjectCreationExpressionSyntax; span = objectCreationExpression.Type.Span; } else if (node is MemberAccessExpressionSyntax) { var memberAccess = node as MemberAccessExpressionSyntax; span = memberAccess.Name.Span; } else if (node is InvocationExpressionSyntax) { var invocationExpression = node as InvocationExpressionSyntax; span = invocationExpression.Expression.Span; if (invocationExpression.Expression is MemberAccessExpressionSyntax) { var memberAccess = invocationExpression.Expression as MemberAccessExpressionSyntax; span = memberAccess.Name.Span; } else { } } else { } } else { } var result = nodeOrToken.SyntaxTree.GetLineSpan(span); return(result); }
void ParseAccessNode(SyntaxNode sn, ParsingState state) { SyntaxNodeOrToken snt = sn.ChildNodesAndTokens().First(); if (snt.Kind().Equals(SyntaxKind.SimpleMemberAccessExpression)) { ParseAccessNode(snt.AsNode(), state); } else if (snt.IsNode) { ParseNode(snt.AsNode(), state); } else if (snt.IsToken) { ParseCommonToken(snt.AsToken(), state); } }
private static bool IsTypeName( SyntaxNodeOrToken nodeOrToken, SemanticModel semanticModel, CancellationToken cancellationToken) { // Syntactically, everything works out. We're in a pretty good spot to show 'when' now. // But let's not do it just yet... Consider these cases: // case SyntaxNode | // case SyntaxNode w| // If what we have here is known to be a type, we don't want to clutter the variable name suggestion list // with 'when' since we know that the resulting code would be semantically invalid. bool isVar; ImmutableArray <ISymbol> symbols; if (nodeOrToken.IsNode) { var node = nodeOrToken.AsNode(); var expression = node as ExpressionSyntax ?? (node as ConstantPatternSyntax)?.Expression; if (!(expression is TypeSyntax typeSyntax)) { return(false); } // We don't pass in the semantic model - let IsPotentialTypeName handle the cases where it's clear // from the syntax, but other than that, we need to do our own logic here. if (typeSyntax.IsPotentialTypeName(semanticModelOpt: null, cancellationToken)) { return(true); } isVar = typeSyntax.IsVar; symbols = semanticModel.LookupName(typeSyntax, namespacesAndTypesOnly: false, cancellationToken); } else { // In a var pattern, the 'var' keyword is not wrapped in a type syntax, so we might just have a naked token. var token = nodeOrToken.AsToken(); isVar = token.Text == SyntaxFacts.GetText(SyntaxKind.VarKeyword); symbols = semanticModel.LookupSymbols(nodeOrToken.AsToken().SpanStart, null, token.Text); } if (symbols.Length == 0) { // For all unknown identifiers except var, we return false (therefore 'when' will be offered), // because the user could later create a type with this name OR a constant. We give them both options. // But with var, when there is no type or constant with this name, we instead make the reasonable // assumption that the user didn't just type 'var' to then create a constant named 'var', but really // is about to declare a variable. Therefore we don't want to interfere with the declaration. // However note that if such a constant already exists, we do the right thing and do offer 'when'. return(isVar); } return(symbols.All(symbol => symbol is IAliasSymbol || symbol is ITypeSymbol)); }
public static SyntaxNodeOrToken WithoutLeadingTrivia(this SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.IsNode) { return(nodeOrToken.AsNode().WithoutLeadingTrivia()); } return(nodeOrToken.AsToken().WithoutLeadingTrivia()); }
private bool CanReuse(SyntaxNodeOrToken nodeOrToken) { // Zero width nodes and tokens always indicate that the parser had to do // something tricky, so don't reuse them. // NOTE: this is slightly different from IsMissing because of omitted type arguments // and array size expressions. if (nodeOrToken.FullWidth == 0) { return(false); } // As of 2013/03/14, the compiler never attempts to incrementally parse a tree containing // annotations. Our goal in instituting this restriction is to prevent API clients from // taking a depedency on the survival of annotations. if (nodeOrToken.ContainsAnnotations) { return(false); } // We can't reuse a node or token if it intersects a changed text range. if (this.IntersectsNextChange(nodeOrToken)) { return(false); } // don't reuse nodes or tokens with skipped text or diagnostics attached to them if (nodeOrToken.ContainsDiagnostics || (nodeOrToken.IsToken && ((CSharpSyntaxNode)nodeOrToken.AsToken().Node).ContainsSkippedText && nodeOrToken.Parent.ContainsDiagnostics)) { return(false); } // fabricated tokens did not come from the lexer (likely from parser) if (IsFabricatedToken(nodeOrToken.CSharpKind())) { return(false); } // don't reuse nodes that are incomplete. this helps cases were an incomplete node // completes differently after a change with far look-ahead. // // NOTE(cyrusn): It is very unfortunate that we even need this check given that we // have already checked for ContainsDiagnostics above. However, there is a case where we // can have a node with a missing token *and* there are no diagnostics. // Specifically, this happens in the REPL when you have the last statement without a // trailing semicolon. We treat this as an ExpressionStatement with a missing // semicolon, but we do not report errors. It would be preferable to fix that so // that the semicolon can be optional rather than abusing the system. if ((nodeOrToken.IsToken && nodeOrToken.AsToken().IsMissing) || (nodeOrToken.IsNode && IsIncomplete((CSharp.CSharpSyntaxNode)nodeOrToken.AsNode()))) { return(false); } return(true); }
public static Edit UpdateBetween( SyntaxNodeOrToken left, SyntaxTriviaList leftTrailingTrivia, SyntaxTriviaList rightLeadingTrivia, SyntaxNodeOrToken right) { var leftLastToken = left.IsToken ? left.AsToken() : left.AsNode().GetLastToken(); var rightFirstToken = right.IsToken ? right.AsToken() : right.AsNode().GetFirstToken(); return(new Edit(leftLastToken, leftTrailingTrivia, rightFirstToken, rightLeadingTrivia)); }
public static SyntaxNode GetNode(this SyntaxNodeOrToken nodeOrToken) { if (!nodeOrToken.IsNode) { throw new ArgumentException("expected node", nameof(nodeOrToken)); } return(nodeOrToken.AsNode()); }
public IEnumerable <OutliningRegionSpan> FindRegions(SyntaxNodeOrToken nodeOrToken) { var node = nodeOrToken.IsNode ? nodeOrToken.AsNode() : null; var typedNode = node as T; return(typedNode == null ? Enumerable.Empty <OutliningRegionSpan>() : FindRegions(typedNode)); }
public TRoot Replace <TRoot>(TRoot root, SyntaxNodeOrToken oldNodeOrToken, SyntaxNodeOrToken newNodeOrToken) where TRoot : SyntaxNode { if (oldNodeOrToken.IsToken) { return(root.ReplaceToken(oldNodeOrToken.AsToken(), newNodeOrToken.AsToken())); } return(root.ReplaceNode(oldNodeOrToken.AsNode(), newNodeOrToken.AsNode())); }
internal Roslyn.Compilers.CSharp.SyntaxToken FindTokenInternal(int position) { SyntaxNodeOrToken syntaxNodeOrToken = (SyntaxNodeOrToken)this; while (syntaxNodeOrToken.AsNode() != null) { syntaxNodeOrToken = Roslyn.Compilers.CSharp.SyntaxNode.GetChildThatContainsPosition(syntaxNodeOrToken.ChildNodesAndTokens(), position); } return(syntaxNodeOrToken.AsToken()); }
private void ClassifyNodeOrToken(SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.IsToken) { ClassifyToken(nodeOrToken.AsToken()); return; } ClassifyNode(nodeOrToken.AsNode()); }
private void TestAnnotation(SyntaxAnnotation annotation, SyntaxNode root, SyntaxNodeOrToken oldNodeOrToken) { // Test for existence of exactly one annotation if (oldNodeOrToken.IsToken) { TestAnnotation(annotation, root, oldNodeOrToken.AsToken()); return; } TestAnnotation(annotation, root, oldNodeOrToken.AsNode()); }
private static int GetEndPosition(SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.IsToken) { return(nodeOrToken.Span.End); } else { return(nodeOrToken.AsNode().GetLastToken().Span.End); } }
public virtual object ExtractValue(SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.IsToken) { return(nodeOrToken.AsToken().Value); } else { return(ExtractValue(nodeOrToken.AsNode().ToString())); } }
// Helpers for populating the treeview. private void AddNodeOrToken(TreeViewItem parentItem, SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.IsNode) { AddNode(parentItem, nodeOrToken.AsNode()); } else { AddToken(parentItem, nodeOrToken.AsToken()); } }
public Cursor MoveToFirstChild() { Debug.Assert(this.CurrentNodeOrToken.IsNode); // Just try to get the first node directly. This is faster than getting the list of // child nodes and tokens (which forces all children to be enumerated for the sake // of counting. It should always be safe to index the 0th element of a node. But // just to make sure that this is not a problem, we verify that the slot count of the // node is greater than 0. var node = CurrentNodeOrToken.AsNode(); // Interpolated strings cannot be scanned or parsed incrementally. Instead they must be // turned into and then reparsed from the single InterpolatedStringToken. We therefore // do not break interpolated string nodes down into their constituent tokens, but // instead replace the whole parsed interpolated string expression with its pre-parsed // interpolated string token. if (node.Kind() == SyntaxKind.InterpolatedStringExpression) { var greenToken = Lexer.RescanInterpolatedString( (InterpolatedStringExpressionSyntax)node.Green ); var redToken = new CodeAnalysis.SyntaxToken( node.Parent, greenToken, node.Position, _indexInParent ); return(new Cursor(redToken, _indexInParent)); } if (node.SlotCount > 0) { var child = Microsoft.CodeAnalysis.ChildSyntaxList.ItemInternal(node, 0); if (IsNonZeroWidthOrIsEndOfFile(child)) { return(new Cursor(child, 0)); } } // Fallback to enumerating all children. int index = 0; foreach (var child in this.CurrentNodeOrToken.ChildNodesAndTokens()) { if (IsNonZeroWidthOrIsEndOfFile(child)) { return(new Cursor(child, index)); } index++; } return(new Cursor()); }
public virtual string ExtractMetadataName(SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.IsToken) { return(nodeOrToken.AsToken().ValueText); } else { return(nodeOrToken.AsNode().ToString()); } }
private void ClassifyNodeOrToken(SyntaxNodeOrToken nodeOrToken) { Debug.Assert(nodeOrToken.IsNode || nodeOrToken.IsToken); if (nodeOrToken.IsToken) { ClassifyToken(nodeOrToken.AsToken()); return; } ClassifyNode(nodeOrToken.AsNode() !); }
public static Result IsTokenwiseEquivalent(SyntaxNodeOrToken nodeOrTokenA, SyntaxNodeOrToken nodeOrTokenB) { if (nodeOrTokenA.IsNode && nodeOrTokenB.IsNode) { return(IsTokenwiseEquivalent(nodeOrTokenA.AsNode(), nodeOrTokenB.AsNode())); } if (nodeOrTokenA.IsToken && nodeOrTokenB.IsToken) { return(IsTokenwiseEquivalent(nodeOrTokenA.AsToken(), nodeOrTokenB.AsToken())); } return(Result.NotEquivalent); }
private void ClassifyNodeOrToken(SyntaxNodeOrToken nodeOrToken) { var node = nodeOrToken.AsNode(); if (node != null) { ClassifyNode(node); } else { ClassifyToken(nodeOrToken.AsToken()); } }
public override Match Run(SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.Kind() != _syntaxKind) return Match.NoMatch; var result = Match.Success; if (nodeOrToken.IsNode) { var node = nodeOrToken.AsNode(); var children = node.ChildNodesAndTokens(); var matcherIndex = 0; var matchedEnd = 0; for (var i = 0; i < children.Count; i++) { if (matcherIndex >= _childMatchers.Length) return Match.NoMatch; while (i < children.Count && children[i].Span.Start < matchedEnd) i++; if (i >= children.Count) break; var child = children[i]; var matcher = _childMatchers[matcherIndex]; var match = matcher.Run(child); if (!match.IsMatch) return Match.NoMatch; // Depending on much was captured, we need to skip some matchers. if (match.Captures.Any()) matchedEnd = match.Captures.Max(c => c.EndNodeOrToken.Span.End); result = result.AddCaptures(match.Captures); matcherIndex++; } var allMatchersUsed = matcherIndex >= _childMatchers.Length; if (!allMatchersUsed) return Match.NoMatch; } return result; }
public static void CheckParents(SyntaxNodeOrToken nodeOrToken, SyntaxTree expectedSyntaxTree) { Assert.Equal(expectedSyntaxTree, nodeOrToken.SyntaxTree); var span = nodeOrToken.Span; if (nodeOrToken.IsToken) { var token = nodeOrToken.AsToken(); foreach (var trivia in token.LeadingTrivia) { var tspan = trivia.Span; var parentToken = trivia.Token; Assert.Equal(parentToken, token); if (trivia.HasStructure) { var parentTrivia = trivia.GetStructure().Parent; Assert.Null(parentTrivia); CheckParents((CSharpSyntaxNode)trivia.GetStructure(), expectedSyntaxTree); } } foreach (var trivia in token.TrailingTrivia) { var tspan = trivia.Span; var parentToken = trivia.Token; Assert.Equal(parentToken, token); if (trivia.HasStructure) { var parentTrivia = trivia.GetStructure().Parent; Assert.Null(parentTrivia); CheckParents(trivia.GetStructure(), expectedSyntaxTree); } } } else { var node = nodeOrToken.AsNode(); foreach (var child in node.ChildNodesAndTokens()) { var parent = child.Parent; Assert.Equal(node, parent); CheckParents(child, expectedSyntaxTree); } } }
private static SyntaxNodeOrToken GetNewSyntaxListItem(SyntaxNodeOrToken item) { if (!item.IsNode) { return item; } var member = (AnonymousObjectMemberDeclaratorSyntax)item.AsNode(); var identifier = member.Expression as IdentifierNameSyntax; if (identifier != null && identifier.Identifier.ValueText == member.NameEquals.Name.Identifier.ValueText) { return SyntaxFactory.AnonymousObjectMemberDeclarator(member.Expression).WithTriviaFrom(member); } return item; }
public override Match Run(SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.Kind() != SyntaxKind.ArgumentList) return Match.NoMatch; var argumentList = (ArgumentListSyntax) nodeOrToken.AsNode(); if (_variable.MinOccurrences > argumentList.Arguments.Count) return Match.NoMatch; if (_variable.MaxOccurrences != null && _variable.MaxOccurrences < argumentList.Arguments.Count) return Match.NoMatch; if (argumentList.Arguments.Count == 0) return Match.Success; var first = argumentList.Arguments.First(); var last = argumentList.Arguments.Last(); return Match.Success.AddCapture(_variable, first, last); }
public bool TryGetVariable(SyntaxNodeOrToken nodeOrToken, out PatternVariable variable) { return nodeOrToken.IsToken ? TryGetVariable(nodeOrToken.AsToken(), out variable) : TryGetVariable(nodeOrToken.AsNode(), out variable); }
private bool ValidateNodeOrToken(SyntaxNodeOrToken nodeOrtoken, SyntaxTree tree, string filename = "", List<Failure> failures = null) { var retVal = true; if (nodeOrtoken.IsNode) { retVal = ValidateNonTerminal(nodeOrtoken.AsNode(), tree, filename, failures); } else { retVal = ValidateToken(nodeOrtoken.AsToken(), tree, filename, failures); } return retVal; }
private static int GetEndPosition(SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.IsToken) { return nodeOrToken.Span.End; } else { return nodeOrToken.AsNode().GetLastToken().Span.End; } }
public SourceLocationWithAssociatedNode(SyntaxTree syntaxTree, SyntaxNodeOrToken nodeOrToken, bool associateInParent = false) : this(syntaxTree, nodeOrToken.Span, nodeOrToken.IsNode ? nodeOrToken.AsNode() : nodeOrToken.AsToken().Parent, associateInParent) { }
private BoundStatement RewriteForStatement( CSharpSyntaxNode syntax, ImmutableArray<LocalSymbol> outerLocals, BoundStatement rewrittenInitializer, ImmutableArray<LocalSymbol> innerLocals, BoundExpression rewrittenCondition, SyntaxNodeOrToken conditionSyntax, BoundStatement rewrittenIncrement, BoundStatement rewrittenBody, GeneratedLabelSymbol breakLabel, GeneratedLabelSymbol continueLabel, bool hasErrors) { Debug.Assert(rewrittenBody != null); // The sequence point behavior exhibited here is different from that of the native compiler. In the native // compiler, if you have something like // // for(int i = 0, j = 0; ; i++, j++) // ^--------------^ ^------^ // // then all the initializers are treated as a single sequence point, as are // all the loop incrementers. // // We now make each one individually a sequence point: // // for(int i = 0, j = 0; ; i++, j++) // ^-------^ ^---^ ^-^ ^-^ // // If we decide that we want to preserve the native compiler stepping behavior // then we'll need to be a bit fancy here. The initializer and increment statements // can contain lambdas whose bodies need to have sequence points inserted, so we // need to make sure we visit the children. But we'll also need to make sure that // we do not generate one sequence point for each statement in the initializers // and the incrementers. var statementBuilder = ArrayBuilder<BoundStatement>.GetInstance(); if (rewrittenInitializer != null) { statementBuilder.Add(rewrittenInitializer); } var startLabel = new GeneratedLabelSymbol("start"); if (!innerLocals.IsDefaultOrEmpty) { var walker = new AnyLocalCapturedInALambdaWalker(innerLocals); if (walker.Analyze(rewrittenCondition) || walker.Analyze(rewrittenIncrement) || walker.Analyze(rewrittenBody)) { // If any inner local is captured within a lambda, we need to enter scope-block // always from the top, that is where an instance of a display class will be created. // The IL will be less optimal, but this shouldn't be a problem, given presence of lambdas. // for (initializer; condition; increment) // body; // // becomes the following (with // block added for locals) // // { // initializer; // start: // { // GotoIfFalse condition break; // body; // continue: // increment; // goto start; // } // break: // } // start: statementBuilder.Add(new BoundLabelStatement(syntax, startLabel)); var blockBuilder = ArrayBuilder<BoundStatement>.GetInstance(); // GotoIfFalse condition break; if (rewrittenCondition != null) { BoundStatement ifNotConditionGotoBreak = new BoundConditionalGoto(rewrittenCondition.Syntax, rewrittenCondition, false, breakLabel); if (this.generateDebugInfo) { if (conditionSyntax.IsToken) { ifNotConditionGotoBreak = new BoundSequencePointWithSpan(syntax, ifNotConditionGotoBreak, conditionSyntax.Span); } else { ifNotConditionGotoBreak = new BoundSequencePoint((CSharpSyntaxNode)conditionSyntax.AsNode(), ifNotConditionGotoBreak); } } blockBuilder.Add(ifNotConditionGotoBreak); } // body; blockBuilder.Add(rewrittenBody); // continue: // increment; blockBuilder.Add(new BoundLabelStatement(syntax, continueLabel)); if (rewrittenIncrement != null) { blockBuilder.Add(rewrittenIncrement); } // goto start; blockBuilder.Add(new BoundGotoStatement(syntax, startLabel)); statementBuilder.Add(new BoundBlock(syntax, innerLocals, blockBuilder.ToImmutableAndFree())); // break: statementBuilder.Add(new BoundLabelStatement(syntax, breakLabel)); return new BoundBlock(syntax, outerLocals, statementBuilder.ToImmutableAndFree(), hasErrors); } } var endLabel = new GeneratedLabelSymbol("end"); // for (initializer; condition; increment) // body; // // becomes the following (with // block added for locals) // // { // initializer; // goto end; // start: // body; // continue: // increment; // end: // GotoIfTrue condition start; // break: // } // initializer; // goto end; //mark the initial jump as hidden. //We do it to tell that this is not a part of previous statement. //This jump may be a target of another jump (for example if loops are nested) and that will make //impression of the previous statement being re-executed var gotoEnd = new BoundSequencePoint(null, new BoundGotoStatement(syntax, endLabel)); statementBuilder.Add(gotoEnd); // start: // body; statementBuilder.Add(new BoundLabelStatement(syntax, startLabel)); ArrayBuilder<BoundStatement> saveBuilder = null; if (!innerLocals.IsDefaultOrEmpty) { saveBuilder = statementBuilder; statementBuilder = ArrayBuilder<BoundStatement>.GetInstance(); } statementBuilder.Add(rewrittenBody); // continue: // increment; statementBuilder.Add(new BoundLabelStatement(syntax, continueLabel)); if (rewrittenIncrement != null) { statementBuilder.Add(rewrittenIncrement); } // end: // GotoIfTrue condition start; statementBuilder.Add(new BoundLabelStatement(syntax, endLabel)); BoundStatement branchBack = null; if (rewrittenCondition != null) { branchBack = new BoundConditionalGoto(rewrittenCondition.Syntax, rewrittenCondition, true, startLabel); } else { branchBack = new BoundGotoStatement(syntax, startLabel); } if (this.generateDebugInfo) { if (conditionSyntax.IsToken) { branchBack = new BoundSequencePointWithSpan(syntax, branchBack, conditionSyntax.Span); } else { //if there is no condition, make this a hidden point so that //it does not count as a part of previous statement branchBack = new BoundSequencePoint((CSharpSyntaxNode)conditionSyntax.AsNode(), branchBack); } } statementBuilder.Add(branchBack); if (!innerLocals.IsDefaultOrEmpty) { var block = new BoundBlock(syntax, innerLocals, statementBuilder.ToImmutableAndFree()); statementBuilder = saveBuilder; statementBuilder.Add(block); } // break: statementBuilder.Add(new BoundLabelStatement(syntax, breakLabel)); var statements = statementBuilder.ToImmutableAndFree(); return new BoundBlock(syntax, outerLocals, statements, hasErrors); }
private SyntaxNodeOrToken VisitNodeOrToken(SyntaxNodeOrToken nodeOrToken) { if (nodeOrToken.IsNode) return Visit(nodeOrToken.AsNode()); return VisitToken(nodeOrToken.AsToken()); }
private BoundStatement RewriteForStatement( CSharpSyntaxNode syntax, ImmutableArray<LocalSymbol> locals, BoundStatement rewrittenInitializer, BoundExpression rewrittenCondition, SyntaxNodeOrToken conditionSyntax, BoundStatement rewrittenIncrement, BoundStatement rewrittenBody, GeneratedLabelSymbol breakLabel, GeneratedLabelSymbol continueLabel, bool hasErrors) { // The sequence point behavior exhibited here is different from that of the native compiler. In the native // compiler, if you have something like // // for(int i = 0, j = 0; ; i++, j++) // ^--------------^ ^------^ // // then all the initializers are treated as a single sequence point, as are // all the loop incrementers. // // We now make each one individually a sequence point: // // for(int i = 0, j = 0; ; i++, j++) // ^-------^ ^---^ ^-^ ^-^ // // If we decide that we want to preserve the native compiler stepping behavior // then we'll need to be a bit fancy here. The initializer and increment statements // can contain lambdas whose bodies need to have sequence points inserted, so we // need to make sure we visit the children. But we'll also need to make sure that // we do not generate one sequence point for each statement in the initializers // and the incrementers. var startLabel = new GeneratedLabelSymbol("start"); var endLabel = new GeneratedLabelSymbol("end"); // for (initializer; condition; increment) // body; // // becomes the following (with // block added for locals) // // { // initializer; // goto end; // start: // body; // continue: // increment; // end: // GotoIfTrue condition start; // break: // } // initializer; // goto end; var statementBuilder = ArrayBuilder<BoundStatement>.GetInstance(); if (rewrittenInitializer != null) { statementBuilder.Add(rewrittenInitializer); } //mark the initial jump as hidden. //We do it to tell that this is not a part of previous statement. //This jump may be a target of another jump (for example if loops are nested) and that will make //impression of the previous statement being re-executed var gotoEnd = new BoundSequencePoint(null, new BoundGotoStatement(syntax, endLabel)); statementBuilder.Add(gotoEnd); // start: // body; statementBuilder.Add(new BoundLabelStatement(syntax, startLabel)); Debug.Assert(rewrittenBody != null); statementBuilder.Add(rewrittenBody); // continue: // increment; statementBuilder.Add(new BoundLabelStatement(syntax, continueLabel)); if (rewrittenIncrement != null) { statementBuilder.Add(rewrittenIncrement); } // end: // GotoIfTrue condition start; statementBuilder.Add(new BoundLabelStatement(syntax, endLabel)); BoundStatement branchBack = null; if (rewrittenCondition != null) { branchBack = new BoundConditionalGoto(rewrittenCondition.Syntax, rewrittenCondition, true, startLabel); } else { branchBack = new BoundGotoStatement(syntax, startLabel); } if (this.generateDebugInfo) { if (conditionSyntax.IsToken) { branchBack = new BoundSequencePointWithSpan(syntax, branchBack, conditionSyntax.Span); } else { //if there is no condition, make this a hidden point so that //it does not count as a part of previous statement branchBack = new BoundSequencePoint((CSharpSyntaxNode)conditionSyntax.AsNode(), branchBack); } } statementBuilder.Add(branchBack); // break: statementBuilder.Add(new BoundLabelStatement(syntax, breakLabel)); var statements = statementBuilder.ToImmutableAndFree(); return new BoundBlock(syntax, locals, statements, hasErrors); }
protected override SyntaxNode GetInnermostNamespaceScope(SyntaxNodeOrToken nodeOrToken) { var node = nodeOrToken.IsNode ? nodeOrToken.AsNode() : nodeOrToken.Parent; return node.GetAncestorOrThis<NamespaceDeclarationSyntax>() ?? (SyntaxNode)node.GetAncestorOrThis<CompilationUnitSyntax>(); }
private BoundStatement RewriteForStatement( SyntaxNode syntax, ReadOnlyArray<LocalSymbol> locals, BoundStatement rewrittenInitializer, BoundExpression rewrittenCondition, SyntaxNodeOrToken conditionSyntax, BoundStatement rewrittenIncrement, BoundStatement rewrittenBody, GeneratedLabelSymbol breakLabel, GeneratedLabelSymbol continueLabel, bool hasErrors) { var startLabel = new GeneratedLabelSymbol("start"); var endLabel = new GeneratedLabelSymbol("end"); // for (initializer; condition; increment) // body; // // becomes the following (with // block added for locals) // // { // initializer; // goto end; // start: // body; // continue: // increment; // end: // GotoIfTrue condition start; // break: // } // initializer; // goto end; var statementBuilder = ArrayBuilder<BoundStatement>.GetInstance(); if (rewrittenInitializer != null) { statementBuilder.Add(rewrittenInitializer); } //mark the initial jump as hidden. //We do it to tell that this is not a part of previous statement. //This jump may be a target of another jump (for example if loops are nested) and that will make //impression of the previous statement being re-executed var gotoEnd = new BoundSequencePoint(null, new BoundGotoStatement(syntax, endLabel)); statementBuilder.Add(gotoEnd); // start: // body; statementBuilder.Add(new BoundLabelStatement(syntax, startLabel)); Debug.Assert(rewrittenBody != null); statementBuilder.Add(rewrittenBody); // continue: // increment; statementBuilder.Add(new BoundLabelStatement(syntax, continueLabel)); if (rewrittenIncrement != null) { statementBuilder.Add(rewrittenIncrement); } // end: // GotoIfTrue condition start; statementBuilder.Add(new BoundLabelStatement(syntax, endLabel)); BoundStatement branchBack = null; if (rewrittenCondition != null) { branchBack = new BoundConditionalGoto(rewrittenCondition.Syntax, rewrittenCondition, true, startLabel); } else { branchBack = new BoundGotoStatement(syntax, startLabel); } if (this.generateDebugInfo) { if (conditionSyntax.IsToken) { branchBack = new BoundSequencePointWithSpan(syntax, branchBack, conditionSyntax.Span); } else { //if there is no condition, make this a hidden point so that //it does not count as a part of previous statement branchBack = new BoundSequencePoint(conditionSyntax.AsNode(), branchBack); } } statementBuilder.Add(branchBack); // break: statementBuilder.Add(new BoundLabelStatement(syntax, breakLabel)); var statements = statementBuilder.ToReadOnlyAndFree(); return new BoundBlock(syntax, locals, statements, hasErrors); }
private void VisitImpl(SyntaxNodeOrToken nodeOrToken) { greatestChildPosition.Add(nodeOrToken, 0); SyntaxNode node = nodeOrToken.AsNode(); IList<string> identity; if (node is CompilationUnitSyntax) { identity = new List<string>(); identity.Add("CompilationUnit"); identities.Add(nodeOrToken, identity); } else { identity = identities[nodeOrToken.Parent].ToList(); } string name = null; if (node is NamespaceDeclarationSyntax) { name = ((NamespaceDeclarationSyntax)node).Name.ToString(); } else if (node is ClassDeclarationSyntax) { name = ((ClassDeclarationSyntax)node).Identifier.ValueText; } else if (node is VariableDeclaratorSyntax) { name = ((VariableDeclaratorSyntax)node).Identifier.ValueText; } else if (node is MethodDeclarationSyntax) { name = ((MethodDeclarationSyntax)node).Identifier.ValueText; } else if (node is PropertyDeclarationSyntax) { name = ((PropertyDeclarationSyntax)node).Identifier.ValueText; } else if (node is UsingDirectiveSyntax) { name = ((UsingDirectiveSyntax)node).Name.ToFullString().Replace(".", string.Empty) ; } else if (nodeOrToken.IsToken) { name = nodeOrToken.AsToken().ValueText; } if (!(node is CompilationUnitSyntax)) { identity.Add( string.Format("{0}{1}", name, (++greatestChildPosition[nodeOrToken.Parent]).ToString())); identities.Add(nodeOrToken, identity); } }
private bool CanReuse(SyntaxNodeOrToken nodeOrToken) { // Zero width nodes and tokens always indicate that the parser had to do // something tricky, so don't reuse them. // NOTE: this is slightly different from IsMissing because of omitted type arguments // and array size expressions. if (nodeOrToken.FullWidth == 0) { return false; } // As of 2013/03/14, the compiler never attempts to incrementally parse a tree containing // annotations. Our goal in instituting this restriction is to prevent API clients from // taking a depedency on the survival of annotations. if (nodeOrToken.ContainsAnnotations) { return false; } // We can't reuse a node or token if it intersects a changed text range. if (this.IntersectsNextChange(nodeOrToken)) { return false; } // don't reuse nodes or tokens with skipped text or diagnostics attached to them if (nodeOrToken.ContainsDiagnostics || (nodeOrToken.IsToken && ((CSharpSyntaxNode)nodeOrToken.AsToken().Node).ContainsSkippedText && nodeOrToken.Parent.ContainsDiagnostics)) { return false; } // fabricated tokens did not come from the lexer (likely from parser) if (IsFabricatedToken(nodeOrToken.CSharpKind())) { return false; } // don't reuse nodes that are incomplete. this helps cases were an incomplete node // completes differently after a change with far look-ahead. // // NOTE(cyrusn): It is very unfortunate that we even need this check given that we // have already checked for ContainsDiagnostics above. However, there is a case where we // can have a node with a missing token *and* there are no diagnostics. // Specifically, this happens in the REPL when you have the last statement without a // trailing semicolon. We treat this as an ExpressionStatement with a missing // semicolon, but we do not report errors. It would be preferable to fix that so // that the semicolon can be optional rather than abusing the system. if ((nodeOrToken.IsToken && nodeOrToken.AsToken().IsMissing) || (nodeOrToken.IsNode && IsIncomplete((CSharp.CSharpSyntaxNode)nodeOrToken.AsNode()))) { return false; } if (!nodeOrToken.ContainsDirectives) { return true; } return this.newDirectives.IncrementallyEquivalent(this.oldDirectives); }