mirror of https://github.com/icsharpcode/ILSpy.git
9 changed files with 1027 additions and 38 deletions
@ -0,0 +1,821 @@
@@ -0,0 +1,821 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
using Microsoft.CodeAnalysis.CSharp.Syntax; |
||||
using Microsoft.CodeAnalysis.Shared.Extensions; |
||||
using Microsoft.CodeAnalysis.Text; |
||||
using Roslyn.Utilities; |
||||
using Microsoft.CodeAnalysis; |
||||
using Microsoft.CodeAnalysis.CSharp; |
||||
using System.Threading.Tasks; |
||||
|
||||
namespace ICSharpCode.ILSpy.AddIn |
||||
{ |
||||
static class SyntaxNodeExtensions |
||||
{ |
||||
public static IEnumerable<SyntaxNode> GetAncestors(this SyntaxNode node) |
||||
{ |
||||
var current = node.Parent; |
||||
|
||||
while (current != null) |
||||
{ |
||||
yield return current; |
||||
|
||||
current = current is IStructuredTriviaSyntax |
||||
? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent |
||||
: current.Parent; |
||||
} |
||||
} |
||||
|
||||
public static IEnumerable<TNode> GetAncestors<TNode>(this SyntaxNode node) |
||||
where TNode : SyntaxNode |
||||
{ |
||||
var current = node.Parent; |
||||
while (current != null) |
||||
{ |
||||
if (current is TNode) |
||||
{ |
||||
yield return (TNode)current; |
||||
} |
||||
|
||||
current = current is IStructuredTriviaSyntax |
||||
? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent |
||||
: current.Parent; |
||||
} |
||||
} |
||||
|
||||
public static TNode GetAncestor<TNode>(this SyntaxNode node) |
||||
where TNode : SyntaxNode |
||||
{ |
||||
if (node == null) |
||||
{ |
||||
return default(TNode); |
||||
} |
||||
|
||||
return node.GetAncestors<TNode>().FirstOrDefault(); |
||||
} |
||||
|
||||
public static TNode GetAncestorOrThis<TNode>(this SyntaxNode node) |
||||
where TNode : SyntaxNode |
||||
{ |
||||
if (node == null) |
||||
{ |
||||
return default(TNode); |
||||
} |
||||
|
||||
return node.GetAncestorsOrThis<TNode>().FirstOrDefault(); |
||||
} |
||||
|
||||
public static IEnumerable<TNode> GetAncestorsOrThis<TNode>(this SyntaxNode node) |
||||
where TNode : SyntaxNode |
||||
{ |
||||
var current = node; |
||||
while (current != null) |
||||
{ |
||||
if (current is TNode) |
||||
{ |
||||
yield return (TNode)current; |
||||
} |
||||
|
||||
current = current is IStructuredTriviaSyntax |
||||
? ((IStructuredTriviaSyntax)current).ParentTrivia.Token.Parent |
||||
: current.Parent; |
||||
} |
||||
} |
||||
|
||||
public static bool HasAncestor<TNode>(this SyntaxNode node) |
||||
where TNode : SyntaxNode |
||||
{ |
||||
return node.GetAncestors<TNode>().Any(); |
||||
} |
||||
|
||||
public static bool CheckParent<T>(this SyntaxNode node, Func<T, bool> valueChecker) where T : SyntaxNode |
||||
{ |
||||
if (node == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
var parentNode = node.Parent as T; |
||||
if (parentNode == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
return valueChecker(parentNode); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns true if is a given token is a child token of of a certain type of parent node.
|
||||
/// </summary>
|
||||
/// <typeparam name="TParent">The type of the parent node.</typeparam>
|
||||
/// <param name="node">The node that we are testing.</param>
|
||||
/// <param name="childGetter">A function that, when given the parent node, returns the child token we are interested in.</param>
|
||||
public static bool IsChildNode<TParent>(this SyntaxNode node, Func<TParent, SyntaxNode> childGetter) |
||||
where TParent : SyntaxNode |
||||
{ |
||||
var ancestor = node.GetAncestor<TParent>(); |
||||
if (ancestor == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
var ancestorNode = childGetter(ancestor); |
||||
|
||||
return node == ancestorNode; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns true if this node is found underneath the specified child in the given parent.
|
||||
/// </summary>
|
||||
public static bool IsFoundUnder<TParent>(this SyntaxNode node, Func<TParent, SyntaxNode> childGetter) |
||||
where TParent : SyntaxNode |
||||
{ |
||||
var ancestor = node.GetAncestor<TParent>(); |
||||
if (ancestor == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
var child = childGetter(ancestor); |
||||
|
||||
// See if node passes through child on the way up to ancestor.
|
||||
return node.GetAncestorsOrThis<SyntaxNode>().Contains(child); |
||||
} |
||||
|
||||
public static SyntaxNode GetCommonRoot(this SyntaxNode node1, SyntaxNode node2) |
||||
{ |
||||
//Contract.ThrowIfTrue(node1.RawKind == 0 || node2.RawKind == 0);
|
||||
|
||||
// find common starting node from two nodes.
|
||||
// as long as two nodes belong to same tree, there must be at least one common root (Ex, compilation unit)
|
||||
var ancestors = node1.GetAncestorsOrThis<SyntaxNode>(); |
||||
var set = new HashSet<SyntaxNode>(node2.GetAncestorsOrThis<SyntaxNode>()); |
||||
|
||||
return ancestors.First(set.Contains); |
||||
} |
||||
|
||||
public static int Width(this SyntaxNode node) |
||||
{ |
||||
return node.Span.Length; |
||||
} |
||||
|
||||
public static int FullWidth(this SyntaxNode node) |
||||
{ |
||||
return node.FullSpan.Length; |
||||
} |
||||
|
||||
public static SyntaxNode FindInnermostCommonNode( |
||||
this IEnumerable<SyntaxNode> nodes, |
||||
Func<SyntaxNode, bool> predicate) |
||||
{ |
||||
IEnumerable<SyntaxNode> blocks = null; |
||||
foreach (var node in nodes) |
||||
{ |
||||
blocks = blocks == null |
||||
? node.AncestorsAndSelf().Where(predicate) |
||||
: blocks.Intersect(node.AncestorsAndSelf().Where(predicate)); |
||||
} |
||||
|
||||
return blocks == null ? null : blocks.First(); |
||||
} |
||||
|
||||
public static TSyntaxNode FindInnermostCommonNode<TSyntaxNode>(this IEnumerable<SyntaxNode> nodes) |
||||
where TSyntaxNode : SyntaxNode |
||||
{ |
||||
return (TSyntaxNode)nodes.FindInnermostCommonNode(n => n is TSyntaxNode); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// create a new root node from the given root after adding annotations to the tokens
|
||||
///
|
||||
/// tokens should belong to the given root
|
||||
/// </summary>
|
||||
public static SyntaxNode AddAnnotations(this SyntaxNode root, IEnumerable<Tuple<SyntaxToken, SyntaxAnnotation>> pairs) |
||||
{ |
||||
// Contract.ThrowIfNull(root);
|
||||
// Contract.ThrowIfNull(pairs);
|
||||
|
||||
var tokenMap = pairs.GroupBy(p => p.Item1, p => p.Item2).ToDictionary(g => g.Key, g => g.ToArray()); |
||||
return root.ReplaceTokens(tokenMap.Keys, (o, n) => o.WithAdditionalAnnotations(tokenMap[o])); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// create a new root node from the given root after adding annotations to the nodes
|
||||
///
|
||||
/// nodes should belong to the given root
|
||||
/// </summary>
|
||||
public static SyntaxNode AddAnnotations(this SyntaxNode root, IEnumerable<Tuple<SyntaxNode, SyntaxAnnotation>> pairs) |
||||
{ |
||||
// Contract.ThrowIfNull(root);
|
||||
// Contract.ThrowIfNull(pairs);
|
||||
|
||||
var tokenMap = pairs.GroupBy(p => p.Item1, p => p.Item2).ToDictionary(g => g.Key, g => g.ToArray()); |
||||
return root.ReplaceNodes(tokenMap.Keys, (o, n) => o.WithAdditionalAnnotations(tokenMap[o])); |
||||
} |
||||
|
||||
public static TextSpan GetContainedSpan(this IEnumerable<SyntaxNode> nodes) |
||||
{ |
||||
// Contract.ThrowIfNull(nodes);
|
||||
// Contract.ThrowIfFalse(nodes.Any());
|
||||
|
||||
TextSpan fullSpan = nodes.First().Span; |
||||
foreach (var node in nodes) |
||||
{ |
||||
fullSpan = TextSpan.FromBounds( |
||||
Math.Min(fullSpan.Start, node.SpanStart), |
||||
Math.Max(fullSpan.End, node.Span.End)); |
||||
} |
||||
|
||||
return fullSpan; |
||||
} |
||||
|
||||
public static IEnumerable<TextSpan> GetContiguousSpans( |
||||
this IEnumerable<SyntaxNode> nodes, Func<SyntaxNode, SyntaxToken> getLastToken = null) |
||||
{ |
||||
SyntaxNode lastNode = null; |
||||
TextSpan? textSpan = null; |
||||
foreach (var node in nodes) |
||||
{ |
||||
if (lastNode == null) |
||||
{ |
||||
textSpan = node.Span; |
||||
} |
||||
else |
||||
{ |
||||
var lastToken = getLastToken == null |
||||
? lastNode.GetLastToken() |
||||
: getLastToken(lastNode); |
||||
if (lastToken.GetNextToken(includeDirectives: true) == node.GetFirstToken()) |
||||
{ |
||||
// Expand the span
|
||||
textSpan = TextSpan.FromBounds(textSpan.Value.Start, node.Span.End); |
||||
} |
||||
else |
||||
{ |
||||
// Return the last span, and start a new one
|
||||
yield return textSpan.Value; |
||||
textSpan = node.Span; |
||||
} |
||||
} |
||||
|
||||
lastNode = node; |
||||
} |
||||
|
||||
if (textSpan.HasValue) |
||||
{ |
||||
yield return textSpan.Value; |
||||
} |
||||
} |
||||
|
||||
//public static bool OverlapsHiddenPosition(this SyntaxNode node, CancellationToken cancellationToken)
|
||||
//{
|
||||
// return node.OverlapsHiddenPosition(node.Span, cancellationToken);
|
||||
//}
|
||||
|
||||
//public static bool OverlapsHiddenPosition(this SyntaxNode node, TextSpan span, CancellationToken cancellationToken)
|
||||
//{
|
||||
// return node.SyntaxTree.OverlapsHiddenPosition(span, cancellationToken);
|
||||
//}
|
||||
|
||||
//public static bool OverlapsHiddenPosition(this SyntaxNode declaration, SyntaxNode startNode, SyntaxNode endNode, CancellationToken cancellationToken)
|
||||
//{
|
||||
// var start = startNode.Span.End;
|
||||
// var end = endNode.SpanStart;
|
||||
|
||||
// var textSpan = TextSpan.FromBounds(start, end);
|
||||
// return declaration.OverlapsHiddenPosition(textSpan, cancellationToken);
|
||||
//}
|
||||
|
||||
public static IEnumerable<T> GetAnnotatedNodes<T>(this SyntaxNode node, SyntaxAnnotation syntaxAnnotation) where T : SyntaxNode |
||||
{ |
||||
return node.GetAnnotatedNodesAndTokens(syntaxAnnotation).Select(n => n.AsNode()).OfType<T>(); |
||||
} |
||||
|
||||
public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2) |
||||
{ |
||||
if (node == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
var csharpKind = node.Kind(); |
||||
return csharpKind == kind1 || csharpKind == kind2; |
||||
} |
||||
|
||||
public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3) |
||||
{ |
||||
if (node == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
var csharpKind = node.Kind(); |
||||
return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3; |
||||
} |
||||
|
||||
public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3, SyntaxKind kind4) |
||||
{ |
||||
if (node == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
var csharpKind = node.Kind(); |
||||
return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3 || csharpKind == kind4; |
||||
} |
||||
|
||||
public static bool IsKind(this SyntaxNode node, SyntaxKind kind1, SyntaxKind kind2, SyntaxKind kind3, SyntaxKind kind4, SyntaxKind kind5) |
||||
{ |
||||
if (node == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
var csharpKind = node.Kind(); |
||||
return csharpKind == kind1 || csharpKind == kind2 || csharpKind == kind3 || csharpKind == kind4 || csharpKind == kind5; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns the list of using directives that affect <paramref name="node"/>. The list will be returned in
|
||||
/// top down order.
|
||||
/// </summary>
|
||||
public static IEnumerable<UsingDirectiveSyntax> GetEnclosingUsingDirectives(this SyntaxNode node) |
||||
{ |
||||
return node.GetAncestorOrThis<CompilationUnitSyntax>().Usings |
||||
.Concat(node.GetAncestorsOrThis<NamespaceDeclarationSyntax>() |
||||
.Reverse() |
||||
.SelectMany(n => n.Usings)); |
||||
} |
||||
|
||||
public static bool IsUnsafeContext(this SyntaxNode node) |
||||
{ |
||||
if (node.GetAncestor<UnsafeStatementSyntax>() != null) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
return node.GetAncestors<MemberDeclarationSyntax>().Any( |
||||
m => m.GetModifiers().Any(SyntaxKind.UnsafeKeyword)); |
||||
} |
||||
|
||||
public static bool IsInStaticContext(this SyntaxNode node) |
||||
{ |
||||
// this/base calls are always static.
|
||||
if (node.FirstAncestorOrSelf<ConstructorInitializerSyntax>() != null) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
var memberDeclaration = node.FirstAncestorOrSelf<MemberDeclarationSyntax>(); |
||||
if (memberDeclaration == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
switch (memberDeclaration.Kind()) |
||||
{ |
||||
case SyntaxKind.MethodDeclaration: |
||||
case SyntaxKind.ConstructorDeclaration: |
||||
case SyntaxKind.PropertyDeclaration: |
||||
case SyntaxKind.EventDeclaration: |
||||
case SyntaxKind.IndexerDeclaration: |
||||
return memberDeclaration.GetModifiers().Any(SyntaxKind.StaticKeyword); |
||||
|
||||
case SyntaxKind.FieldDeclaration: |
||||
// Inside a field one can only access static members of a type.
|
||||
return true; |
||||
|
||||
case SyntaxKind.DestructorDeclaration: |
||||
return false; |
||||
} |
||||
|
||||
// Global statements are not a static context.
|
||||
if (node.FirstAncestorOrSelf<GlobalStatementSyntax>() != null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
// any other location is considered static
|
||||
return true; |
||||
} |
||||
|
||||
public static NamespaceDeclarationSyntax GetInnermostNamespaceDeclarationWithUsings(this SyntaxNode contextNode) |
||||
{ |
||||
var usingDirectiveAncsestor = contextNode.GetAncestor<UsingDirectiveSyntax>(); |
||||
if (usingDirectiveAncsestor == null) |
||||
{ |
||||
return contextNode.GetAncestorsOrThis<NamespaceDeclarationSyntax>().FirstOrDefault(n => n.Usings.Count > 0); |
||||
} |
||||
else |
||||
{ |
||||
// We are inside a using directive. In this case, we should find and return the first 'parent' namespace with usings.
|
||||
var containingNamespace = usingDirectiveAncsestor.GetAncestor<NamespaceDeclarationSyntax>(); |
||||
if (containingNamespace == null) |
||||
{ |
||||
// We are inside a top level using directive (i.e. one that's directly in the compilation unit).
|
||||
return null; |
||||
} |
||||
else |
||||
{ |
||||
return containingNamespace.GetAncestors<NamespaceDeclarationSyntax>().FirstOrDefault(n => n.Usings.Count > 0); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns all of the trivia to the left of this token up to the previous token (concatenates
|
||||
/// the previous token's trailing trivia and this token's leading trivia).
|
||||
/// </summary>
|
||||
public static IEnumerable<SyntaxTrivia> GetAllPrecedingTriviaToPreviousToken(this SyntaxToken token) |
||||
{ |
||||
var prevToken = token.GetPreviousToken(includeSkipped: true); |
||||
if (prevToken.Kind() == SyntaxKind.None) |
||||
{ |
||||
return token.LeadingTrivia; |
||||
} |
||||
|
||||
return prevToken.TrailingTrivia.Concat(token.LeadingTrivia); |
||||
} |
||||
|
||||
public static bool IsBreakableConstruct(this SyntaxNode node) |
||||
{ |
||||
switch (node.Kind()) |
||||
{ |
||||
case SyntaxKind.DoStatement: |
||||
case SyntaxKind.WhileStatement: |
||||
case SyntaxKind.SwitchStatement: |
||||
case SyntaxKind.ForStatement: |
||||
case SyntaxKind.ForEachStatement: |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public static bool IsContinuableConstruct(this SyntaxNode node) |
||||
{ |
||||
switch (node.Kind()) |
||||
{ |
||||
case SyntaxKind.DoStatement: |
||||
case SyntaxKind.WhileStatement: |
||||
case SyntaxKind.ForStatement: |
||||
case SyntaxKind.ForEachStatement: |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public static bool IsReturnableConstruct(this SyntaxNode node) |
||||
{ |
||||
switch (node.Kind()) |
||||
{ |
||||
case SyntaxKind.AnonymousMethodExpression: |
||||
case SyntaxKind.SimpleLambdaExpression: |
||||
case SyntaxKind.ParenthesizedLambdaExpression: |
||||
case SyntaxKind.MethodDeclaration: |
||||
case SyntaxKind.ConstructorDeclaration: |
||||
case SyntaxKind.DestructorDeclaration: |
||||
case SyntaxKind.GetAccessorDeclaration: |
||||
case SyntaxKind.SetAccessorDeclaration: |
||||
case SyntaxKind.OperatorDeclaration: |
||||
case SyntaxKind.AddAccessorDeclaration: |
||||
case SyntaxKind.RemoveAccessorDeclaration: |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public static bool IsAnyArgumentList(this SyntaxNode node) |
||||
{ |
||||
return node.IsKind(SyntaxKind.ArgumentList) || |
||||
node.IsKind(SyntaxKind.AttributeArgumentList) || |
||||
node.IsKind(SyntaxKind.BracketedArgumentList) || |
||||
node.IsKind(SyntaxKind.TypeArgumentList); |
||||
} |
||||
|
||||
public static bool IsAnyLambda(this SyntaxNode node) |
||||
{ |
||||
return |
||||
node.IsKind(SyntaxKind.ParenthesizedLambdaExpression) || |
||||
node.IsKind(SyntaxKind.SimpleLambdaExpression); |
||||
} |
||||
|
||||
public static bool IsAnyLambdaOrAnonymousMethod(this SyntaxNode node) |
||||
{ |
||||
return node.IsAnyLambda() || node.IsKind(SyntaxKind.AnonymousMethodExpression); |
||||
} |
||||
|
||||
public static bool IsAnyAssignExpression(this SyntaxNode node) |
||||
{ |
||||
return SyntaxFacts.IsAssignmentExpression(node.Kind()); |
||||
} |
||||
|
||||
public static bool IsParentKind(this SyntaxNode node, SyntaxKind kind) |
||||
{ |
||||
return node != null && node.Parent.IsKind(kind); |
||||
} |
||||
|
||||
public static bool IsParentKind(this SyntaxToken node, SyntaxKind kind) |
||||
{ |
||||
return node.Parent != null && node.Parent.IsKind(kind); |
||||
} |
||||
|
||||
public static bool IsCompoundAssignExpression(this SyntaxNode node) |
||||
{ |
||||
switch (node.Kind()) |
||||
{ |
||||
case SyntaxKind.AddAssignmentExpression: |
||||
case SyntaxKind.SubtractAssignmentExpression: |
||||
case SyntaxKind.MultiplyAssignmentExpression: |
||||
case SyntaxKind.DivideAssignmentExpression: |
||||
case SyntaxKind.ModuloAssignmentExpression: |
||||
case SyntaxKind.AndAssignmentExpression: |
||||
case SyntaxKind.ExclusiveOrAssignmentExpression: |
||||
case SyntaxKind.OrAssignmentExpression: |
||||
case SyntaxKind.LeftShiftAssignmentExpression: |
||||
case SyntaxKind.RightShiftAssignmentExpression: |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public static bool IsLeftSideOfAssignExpression(this SyntaxNode node) |
||||
{ |
||||
return node.IsParentKind(SyntaxKind.SimpleAssignmentExpression) && |
||||
((AssignmentExpressionSyntax)node.Parent).Left == node; |
||||
} |
||||
|
||||
public static bool IsLeftSideOfAnyAssignExpression(this SyntaxNode node) |
||||
{ |
||||
return node.Parent.IsAnyAssignExpression() && |
||||
((AssignmentExpressionSyntax)node.Parent).Left == node; |
||||
} |
||||
|
||||
public static bool IsRightSideOfAnyAssignExpression(this SyntaxNode node) |
||||
{ |
||||
return node.Parent.IsAnyAssignExpression() && |
||||
((AssignmentExpressionSyntax)node.Parent).Right == node; |
||||
} |
||||
|
||||
public static bool IsVariableDeclaratorValue(this SyntaxNode node) |
||||
{ |
||||
return |
||||
node.IsParentKind(SyntaxKind.EqualsValueClause) && |
||||
node.Parent.IsParentKind(SyntaxKind.VariableDeclarator) && |
||||
((EqualsValueClauseSyntax)node.Parent).Value == node; |
||||
} |
||||
|
||||
public static BlockSyntax FindInnermostCommonBlock(this IEnumerable<SyntaxNode> nodes) |
||||
{ |
||||
return nodes.FindInnermostCommonNode<BlockSyntax>(); |
||||
} |
||||
|
||||
public static IEnumerable<SyntaxNode> GetAncestorsOrThis(this SyntaxNode node, Func<SyntaxNode, bool> predicate) |
||||
{ |
||||
var current = node; |
||||
while (current != null) |
||||
{ |
||||
if (predicate(current)) |
||||
{ |
||||
yield return current; |
||||
} |
||||
|
||||
current = current.Parent; |
||||
} |
||||
} |
||||
|
||||
public static SyntaxNode GetParent(this SyntaxNode node) |
||||
{ |
||||
return node != null ? node.Parent : null; |
||||
} |
||||
|
||||
public static ValueTuple<SyntaxToken, SyntaxToken> GetBraces(this SyntaxNode node) |
||||
{ |
||||
var namespaceNode = node as NamespaceDeclarationSyntax; |
||||
if (namespaceNode != null) |
||||
{ |
||||
return ValueTuple.Create(namespaceNode.OpenBraceToken, namespaceNode.CloseBraceToken); |
||||
} |
||||
|
||||
var baseTypeNode = node as BaseTypeDeclarationSyntax; |
||||
if (baseTypeNode != null) |
||||
{ |
||||
return ValueTuple.Create(baseTypeNode.OpenBraceToken, baseTypeNode.CloseBraceToken); |
||||
} |
||||
|
||||
var accessorListNode = node as AccessorListSyntax; |
||||
if (accessorListNode != null) |
||||
{ |
||||
return ValueTuple.Create(accessorListNode.OpenBraceToken, accessorListNode.CloseBraceToken); |
||||
} |
||||
|
||||
var blockNode = node as BlockSyntax; |
||||
if (blockNode != null) |
||||
{ |
||||
return ValueTuple.Create(blockNode.OpenBraceToken, blockNode.CloseBraceToken); |
||||
} |
||||
|
||||
var switchStatementNode = node as SwitchStatementSyntax; |
||||
if (switchStatementNode != null) |
||||
{ |
||||
return ValueTuple.Create(switchStatementNode.OpenBraceToken, switchStatementNode.CloseBraceToken); |
||||
} |
||||
|
||||
var anonymousObjectCreationExpression = node as AnonymousObjectCreationExpressionSyntax; |
||||
if (anonymousObjectCreationExpression != null) |
||||
{ |
||||
return ValueTuple.Create(anonymousObjectCreationExpression.OpenBraceToken, anonymousObjectCreationExpression.CloseBraceToken); |
||||
} |
||||
|
||||
var initializeExpressionNode = node as InitializerExpressionSyntax; |
||||
if (initializeExpressionNode != null) |
||||
{ |
||||
return ValueTuple.Create(initializeExpressionNode.OpenBraceToken, initializeExpressionNode.CloseBraceToken); |
||||
} |
||||
|
||||
return new ValueTuple<SyntaxToken, SyntaxToken>(); |
||||
} |
||||
|
||||
public static SyntaxTokenList GetModifiers(this SyntaxNode member) |
||||
{ |
||||
if (member != null) |
||||
{ |
||||
switch (member.Kind()) |
||||
{ |
||||
case SyntaxKind.EnumDeclaration: |
||||
return ((EnumDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.ClassDeclaration: |
||||
case SyntaxKind.InterfaceDeclaration: |
||||
case SyntaxKind.StructDeclaration: |
||||
return ((TypeDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.DelegateDeclaration: |
||||
return ((DelegateDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.FieldDeclaration: |
||||
return ((FieldDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.EventFieldDeclaration: |
||||
return ((EventFieldDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.ConstructorDeclaration: |
||||
return ((ConstructorDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.DestructorDeclaration: |
||||
return ((DestructorDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.PropertyDeclaration: |
||||
return ((PropertyDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.EventDeclaration: |
||||
return ((EventDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.IndexerDeclaration: |
||||
return ((IndexerDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.OperatorDeclaration: |
||||
return ((OperatorDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.ConversionOperatorDeclaration: |
||||
return ((ConversionOperatorDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.MethodDeclaration: |
||||
return ((MethodDeclarationSyntax)member).Modifiers; |
||||
case SyntaxKind.GetAccessorDeclaration: |
||||
case SyntaxKind.SetAccessorDeclaration: |
||||
case SyntaxKind.AddAccessorDeclaration: |
||||
case SyntaxKind.RemoveAccessorDeclaration: |
||||
return ((AccessorDeclarationSyntax)member).Modifiers; |
||||
} |
||||
} |
||||
|
||||
return default(SyntaxTokenList); |
||||
} |
||||
|
||||
public static SyntaxNode WithModifiers(this SyntaxNode member, SyntaxTokenList modifiers) |
||||
{ |
||||
if (member != null) |
||||
{ |
||||
switch (member.Kind()) |
||||
{ |
||||
case SyntaxKind.EnumDeclaration: |
||||
return ((EnumDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.ClassDeclaration: |
||||
case SyntaxKind.InterfaceDeclaration: |
||||
case SyntaxKind.StructDeclaration: |
||||
return ((TypeDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.DelegateDeclaration: |
||||
return ((DelegateDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.FieldDeclaration: |
||||
return ((FieldDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.EventFieldDeclaration: |
||||
return ((EventFieldDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.ConstructorDeclaration: |
||||
return ((ConstructorDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.DestructorDeclaration: |
||||
return ((DestructorDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.PropertyDeclaration: |
||||
return ((PropertyDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.EventDeclaration: |
||||
return ((EventDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.IndexerDeclaration: |
||||
return ((IndexerDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.OperatorDeclaration: |
||||
return ((OperatorDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.ConversionOperatorDeclaration: |
||||
return ((ConversionOperatorDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.MethodDeclaration: |
||||
return ((MethodDeclarationSyntax)member).WithModifiers(modifiers); |
||||
case SyntaxKind.GetAccessorDeclaration: |
||||
case SyntaxKind.SetAccessorDeclaration: |
||||
case SyntaxKind.AddAccessorDeclaration: |
||||
case SyntaxKind.RemoveAccessorDeclaration: |
||||
return ((AccessorDeclarationSyntax)member).WithModifiers(modifiers); |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public static TypeDeclarationSyntax WithModifiers( |
||||
this TypeDeclarationSyntax node, SyntaxTokenList modifiers) |
||||
{ |
||||
switch (node.Kind()) |
||||
{ |
||||
case SyntaxKind.ClassDeclaration: |
||||
return ((ClassDeclarationSyntax)node).WithModifiers(modifiers); |
||||
case SyntaxKind.InterfaceDeclaration: |
||||
return ((InterfaceDeclarationSyntax)node).WithModifiers(modifiers); |
||||
case SyntaxKind.StructDeclaration: |
||||
return ((StructDeclarationSyntax)node).WithModifiers(modifiers); |
||||
} |
||||
|
||||
throw new InvalidOperationException(); |
||||
} |
||||
|
||||
public static bool CheckTopLevel(this SyntaxNode node, TextSpan span) |
||||
{ |
||||
var block = node as BlockSyntax; |
||||
if (block != null) |
||||
{ |
||||
return block.ContainsInBlockBody(span); |
||||
} |
||||
|
||||
var field = node as FieldDeclarationSyntax; |
||||
if (field != null) |
||||
{ |
||||
foreach (var variable in field.Declaration.Variables) |
||||
{ |
||||
if (variable.Initializer != null && variable.Initializer.Span.Contains(span)) |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
var global = node as GlobalStatementSyntax; |
||||
if (global != null) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
var constructorInitializer = node as ConstructorInitializerSyntax; |
||||
if (constructorInitializer != null) |
||||
{ |
||||
return constructorInitializer.ContainsInArgument(span); |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public static bool ContainsInArgument(this ConstructorInitializerSyntax initializer, TextSpan textSpan) |
||||
{ |
||||
if (initializer == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
return initializer.ArgumentList.Arguments.Any(a => a.Span.Contains(textSpan)); |
||||
} |
||||
|
||||
public static bool ContainsInBlockBody(this BlockSyntax block, TextSpan textSpan) |
||||
{ |
||||
if (block == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
var blockSpan = TextSpan.FromBounds(block.OpenBraceToken.Span.End, block.CloseBraceToken.SpanStart); |
||||
return blockSpan.Contains(textSpan); |
||||
} |
||||
|
||||
public static bool IsDelegateOrConstructorOrMethodParameterList(this SyntaxNode node) |
||||
{ |
||||
if (!node.IsKind(SyntaxKind.ParameterList)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
return |
||||
node.IsParentKind(SyntaxKind.MethodDeclaration) || |
||||
node.IsParentKind(SyntaxKind.ConstructorDeclaration) || |
||||
node.IsParentKind(SyntaxKind.DelegateDeclaration); |
||||
} |
||||
|
||||
} |
||||
} |
Loading…
Reference in new issue