static string ProcessNode(SyntaxNode node, int depth, StringBuilder prepend) { switch (node.Kind()) { case SyntaxKind.CompilationUnit: return ProcessChildNodes(node, depth, prepend); case SyntaxKind.OptionStatement: case SyntaxKind.ImportsStatement: case SyntaxKind.ClassStatement: case SyntaxKind.EndClassStatement: case SyntaxKind.ImplementsStatement: case SyntaxKind.EnumStatement: case SyntaxKind.EndEnumStatement: // ignore; break; case SyntaxKind.ClassBlock: var className = ((ClassStatementSyntax)node.ChildNodes().First()).Identifier.Text; var classResult = string.Format("class {0} {{\n{1}}}\n", className, ProcessChildNodes(node, depth, prepend)); if (depth == 0) return classResult; prepend.Append(classResult); return null; case SyntaxKind.EnumBlock: var enumName = ((EnumStatementSyntax)node.ChildNodes().First()).Identifier.Text; var values = node.ChildNodes().OfType<EnumMemberDeclarationSyntax>().Select(n => n.Initializer == null ? n.Identifier.Text : n.Identifier.Text + " = " + n.Initializer.Value); prepend.Append(string.Format("enum {0} {{{1}}};\n", enumName, string.Join(", ", values))); return null; case SyntaxKind.EnumMemberDeclaration: return ((EnumMemberDeclarationSyntax)node).Identifier.Text; default: return string.Format("{0}// UNKNOWN {1}\n", Tabs(depth), node.Kind()); } return null; }
private static IEnumerable<CodeAction> GetActions(Document document, SyntaxNode root, SyntaxNode node, CSharpSyntaxNode nullableType, CSharpSyntaxNode objectType) { var returnType = (CSharpSyntaxNode)nullableType ?? objectType; if (returnType == null) yield break; var bodyStatement = node.ChildNodes().OfType<BlockSyntax>().FirstOrDefault(); if (bodyStatement == null) yield break; if (HasReturnContract(bodyStatement, returnType.ToString())) yield break; yield return CreateAction( node.Span ,t2 => { var newBody = bodyStatement.WithStatements(SyntaxFactory.List<StatementSyntax>(new[] { CreateContractEnsuresCall(returnType.ToString()) }.Concat(bodyStatement.Statements))); var newRoot = (CompilationUnitSyntax)root.ReplaceNode((SyntaxNode)bodyStatement, newBody); if (UsingStatementNotPresent(newRoot)) newRoot = AddUsingStatement(node, newRoot); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } ,"Add a Contract to specify the return value must not be null" ); }
public IEnumerable<IHalsteadMetrics> Calculate(SyntaxNode root) { var analyzer = new HalsteadAnalyzer(); var childNodes = root.ChildNodes().AsArray(); var types = childNodes.Where(n => n.IsKind(SyntaxKind.ClassDeclaration) || n.IsKind(SyntaxKind.StructDeclaration)) .AsArray(); var methods = types.SelectMany(n => n.ChildNodes().Where(_isMethod)); var getProperties = types.SelectMany(n => n.ChildNodes().Where(IsGetProperty)); var setProperties = types.SelectMany(n => n.ChildNodes().Where(IsSetProperty)); var looseMethods = childNodes.Where(_isMethod); var looseGetProperties = childNodes.Where(IsGetProperty); var looseSetProperties = childNodes.Where(IsSetProperty); var members = methods.Concat(getProperties) .Concat(setProperties) .Concat(looseMethods) .Concat(looseGetProperties) .Concat(looseSetProperties) .AsArray(); if (members.Any()) { return members.Select(analyzer.Calculate); } var statements = childNodes.Length == 0 ? root.DescendantNodesAndTokens().Select(x => SyntaxFactory.ParseStatement(x.ToFullString(), 0, new CSharpParseOptions(kind: SourceCodeKind.Script, preprocessorSymbols: new string[0]))) : childNodes.Select(x => SyntaxFactory.ParseStatement(x.ToFullString(), 0, new CSharpParseOptions(kind: SourceCodeKind.Script, preprocessorSymbols: new string[0]))); var fakeMethod = SyntaxFactory.MethodDeclaration(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)), "fake") .WithBody(SyntaxFactory.Block(statements)); return new[] { analyzer.Calculate(fakeMethod) }; }
public bool SyntaxNodeMatchesDeclaration(SyntaxNode syntaxNode) { if (string.IsNullOrWhiteSpace(_declarationFilter)) { return true; } // The semantics of CSharp and Visual Basic appear to be different (I.e., VB puts everything inside a "Block") if (syntaxNode.SyntaxTree is Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree) { if (SyntaxNodeWrapper.Get(syntaxNode).GetKind().EndsWith("Declaration")) { return InternalsHelper.GetIdentifierTokenValueText(syntaxNode) == _declarationFilter; } } else if (syntaxNode.SyntaxTree is Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree) { if (SyntaxNodeWrapper.Get(syntaxNode).GetKind().EndsWith("Block")) { SyntaxNode firstChild = syntaxNode.ChildNodes().FirstOrDefault(); if (firstChild != null && SyntaxNodeWrapper.Get(firstChild).GetKind().EndsWith("Statement")) { return InternalsHelper.GetIdentifierTokenValueText(firstChild) == _declarationFilter; } } } return false; }
static string ProcessChildNodes(SyntaxNode node, int depth, StringBuilder prepend) { var sb = new StringBuilder(); foreach (var childNode in node.ChildNodes()) { sb.Append(ProcessNode(childNode, depth + 1, prepend)); } return sb.ToString(); }
public static InvocationExpressionSyntax FindExpressionForConfigureAwait(SyntaxNode node) { foreach (var item in node.ChildNodes()) { if (item is InvocationExpressionSyntax) return (InvocationExpressionSyntax)item; return FindExpressionForConfigureAwait(item); } return null; }
static int CountNesting(SyntaxNode node) { int nesting = 0; foreach (var child in node.ChildNodes()) { if(!(child is BlockSyntax) && child is StatementSyntax) nesting = Math.Max(CountNesting(child) + 1, nesting); else nesting = Math.Max(CountNesting(child), nesting); } return nesting; }
protected override SyntaxNode GetTargetNode(SyntaxNode node) { if (node.IsKind(SyntaxKind.MemberBindingExpression)) { var nameNode = node.ChildNodes().FirstOrDefault(n => n.IsKind(SyntaxKind.IdentifierName)); if (nameNode != null) { return nameNode; } } return base.GetTargetNode(node); }
private void Recurse(SyntaxNode node, bool isInSwitch) { if (node is ContinueStatementSyntax) HasContinue = true; else if (node is BreakStatementSyntax && !isInSwitch) //ignore break statements in a switch, since they apply to breaking the switch and not the loop HasBreak = true; else { foreach (var child in node.ChildNodes()) { if (!IsLoopSyntax(child)) //any breaks or continues in child loops will belong to that loop, so we can skip recusing into them. Recurse(child, isInSwitch || child is SwitchStatementSyntax); } } }
protected override void ParseSyntaxNode(ITextSnapshot snapshot, SyntaxNode parentSyntaxNode, CodeBlock parentCodeBlockNode, CancellationToken token, int level) { if (token.IsCancellationRequested) { throw new TaskCanceledException(); } else { foreach (var childnode in parentSyntaxNode.ChildNodes()) { BlockType type = BlockType.Unknown; int startPosition = 0; int endPosition = 0; if (TryAsNamespace(childnode, ref type, ref startPosition, ref endPosition) || TryAsType(childnode, ref type, ref startPosition, ref endPosition) || TryAsEnum(childnode, ref type, ref startPosition, ref endPosition) || TryAsSwitch(childnode, ref type, ref startPosition, ref endPosition) || TryAsSwitchSection(childnode, snapshot, ref type, ref startPosition, ref endPosition) || TryAsProperty(childnode, ref type, ref startPosition, ref endPosition)) { var statementStart = childnode.SpanStart; string statement = StatementFromSpan(snapshot, statementStart, startPosition); CodeBlock child = new CodeBlock(parentCodeBlockNode, type, statement, new SnapshotSpan(snapshot, Span.FromBounds(startPosition, endPosition)), statementStart, level + 1); ParseSyntaxNode(snapshot, childnode, child, token, level + 1); } else if (TryAsBlock(childnode, parentSyntaxNode, ref type, ref startPosition, ref endPosition)) { int statementStart = type == BlockType.Unknown ? startPosition : parentSyntaxNode.SpanStart; string statement = StatementFromSpan(snapshot, statementStart, startPosition); CodeBlock child = new CodeBlock(parentCodeBlockNode, type, statement, new SnapshotSpan(snapshot, Span.FromBounds(startPosition, endPosition)), statementStart, level + 1); ParseSyntaxNode(snapshot, childnode, child, token, level + 1); } else { ParseSyntaxNode(snapshot, childnode, parentCodeBlockNode, token, level); } } } }
static int SearchUsingInsertionPoint (SyntaxNode parent) { var result = 0; foreach (SyntaxNode node in parent.ChildNodes ()) { if (node.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.UsingDirective)) { result = node.FullSpan.End; continue; } SyntaxTrivia last = new SyntaxTrivia (); foreach (var trivia in node.GetLeadingTrivia ()) { if (last.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.SingleLineCommentTrivia)|| last.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.DefineDirectiveTrivia) || last.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.MultiLineCommentTrivia) || last.IsKind (Microsoft.CodeAnalysis.CSharp.SyntaxKind.SingleLineDocumentationCommentTrivia)) result = trivia.Span.End; last = trivia; } break; } return result; }
private static SyntaxNode CastResursiveMethod(SyntaxNode tree, SemanticModel semanticModel, GenRef genRef, Dictionary<SyntaxNode, SyntaxNode> castChanges) { var change = new Dictionary<SyntaxNode, SyntaxNode>(); foreach (var node in tree.ChildNodes()) { ITypeSymbol ts = null; // if invocation -> ITypeSymbol // ------------------------- if (node is InvocationExpressionSyntax) { ISymbol invokedSymbol = semanticModel.GetSymbolInfo(node).Symbol; // if is generic method if (genRef.Methods.Contains(invokedSymbol.OriginalDefinition)) { ts = ((IMethodSymbol)invokedSymbol).ReturnType; } } else if ((node is MemberAccessExpressionSyntax) && !(node.Parent is AssignmentExpressionSyntax)) { ISymbol invokedSymbol = semanticModel.GetSymbolInfo(node).Symbol; // if is generic property if (genRef.Properties.Contains(invokedSymbol.OriginalDefinition)) { ts = ((IPropertySymbol)invokedSymbol).Type; } } // recurse for changed node var casted = CastResursiveMethod(node, semanticModel, genRef, castChanges); if (ts != null) { // do cast casted = Helpers.CastTo((ExpressionSyntax)casted, ts); if (node.Parent is MemberAccessExpressionSyntax) casted = ((ExpressionSyntax)casted).Parenthesize(); castChanges.Add(node, casted); } // add for replace if (node != casted) change.Add(node, casted); } if (change.Any()) tree = tree.ReplaceNodes(change.Keys, (x, y) => change[x]); return tree; }
public override void Visit(SyntaxNode node) { var padding = node.Ancestors().Count(); var prepend = node.ChildNodes().Any() ? "[-]" : "[.]"; var nodetype = node.GetType().FullName; if (nodetype.StartsWith(prefix)) nodetype = nodetype.Substring(prefix.Length); var line = new string(' ', padding) + prepend + " " + nodetype; Console.WriteLine(line); //var decl = node as ClassDeclarationSyntax; //if (decl != null && decl.BaseList != null) //{ // Console.Write(new string(' ', padding + 4) + decl.Identifier); // foreach (var n in decl.BaseList.Types.OfType<IdentifierNameSyntax>()) // { // Console.Write(" " + n.Identifier); // } // Console.WriteLine(); //} var attr = node as AttributeSyntax; if (attr != null) { Console.WriteLine(new string(' ', padding + 4) + "> " + attr.Name); foreach (var arg in attr.ArgumentList.Arguments) { var expr = arg.Expression as LiteralExpressionSyntax; //Console.WriteLine(new string(' ', padding + 4) + "> " + arg.NameColon + " " + arg.NameEquals); Console.WriteLine(new string(' ', padding + 4) + "> " + (expr == null ? null : expr.Token.Value)); } } var attr2 = node as IdentifierNameSyntax; if (attr2 != null) { Console.WriteLine(new string(' ', padding + 4) + "T " + attr2.Identifier.GetType()); Console.WriteLine(new string(' ', padding + 4) + "V " + attr2.Identifier); } var x = node as TypeSyntax; if (x != null) { var xtype = x.GetType().FullName; if (xtype.StartsWith(prefix)) xtype = nodetype.Substring(prefix.Length); Console.WriteLine(new string(' ', padding + 4) + "> " + xtype); } base.Visit(node); }
public override bool DefaultVisit(SyntaxNode node) { foreach (var child in node.ChildNodes()) { if (Visit(child)) return true; } return false; }
void AddUsings (SyntaxNode parent) { SyntaxNode firstChild = null, lastChild = null; foreach (var child in parent.ChildNodes ()) { if (child is UsingDirectiveSyntax) { if (firstChild == null) { firstChild = child; } lastChild = child; continue; } if (firstChild != null) break; } if (firstChild != null && firstChild != lastChild) { var first = firstChild.GetLocation ().GetLineSpan (); var last = lastChild.GetLocation ().GetLineSpan (); Foldings.Add (new FoldingRegion (new DocumentRegion (first.StartLinePosition, last.EndLinePosition), FoldType.Undefined)); } }
private static MethodDeclarationSyntax FindMethodDeclaration(SyntaxNode node, string name) { if (node.Kind() == SyntaxKind.MethodDeclaration) { var methodNode = node as MethodDeclarationSyntax; if (methodNode.Identifier.ValueText == name) { return methodNode; } } foreach (var childNode in node.ChildNodes()) { var childMethodNode = IMethodSymbolExtensionsTests.FindMethodDeclaration(childNode, name); if (childMethodNode != null) { return childMethodNode; } } return null; }
internal IfStatementSyntax GetFirstIfStatementInUsingBlock(SyntaxNode block) { if (reportedIssue) { return null; } IfStatementSyntax firstIfStatement = block.ChildNodes().FirstOrDefault() as IfStatementSyntax; if (firstIfStatement == null) { // first should check on Applied var diagnostic = Diagnostic.Create(rule, usingStatement.GetLocation(), "not checked whether lock was succcessful"); analysisContext.ReportDiagnostic(diagnostic); reportedIssue = true; } return firstIfStatement; }
internal void CheckReturnOrThrow(SyntaxNode ifAppliedNode) { if (reportedIssue) { return; } var returnStatement = ifAppliedNode.ChildNodes().Where(node => node as ReturnStatementSyntax != null).LastOrDefault(); var throwStatement = ifAppliedNode.ChildNodes().Where(node => node as ThrowStatementSyntax != null).LastOrDefault(); if (returnStatement == null && throwStatement == null) { ReportIssue( "no return/throw statement"); } }
private async Task<MethodDeclarationSyntax> GetMethodDeclaration( SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) { var invocationExpression = node.ChildNodes().FirstOrDefault(n => n.IsKind(SyntaxKind.InvocationExpression)); var methodSymbol = semanticModel.GetSymbolInfo(invocationExpression, cancellationToken).Symbol as IMethodSymbol; if (methodSymbol == null) { return null; } var methodReference = methodSymbol.DeclaringSyntaxReferences.FirstOrDefault(); if (methodReference == null) { return null; } var methodDeclaration = (await methodReference.GetSyntaxAsync(cancellationToken).ConfigureAwait(false)) as MethodDeclarationSyntax; if (methodDeclaration == null) { return null; } if (!methodDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.AsyncKeyword))) { return null; } return methodDeclaration; }
public override void Visit(SyntaxNode node) { List<MemberDeclarationSyntax> members = new List<MemberDeclarationSyntax>(); var newRoot = node.ReplaceNodes(node.ChildNodes().OfType<MemberDeclarationSyntax>(), (oldNode, newNode) => { members.Add(newNode); return null; }); if (node is CompilationUnitSyntax) { base.Visit(node); return; } all_++; if (node is MemberDeclarationSyntax) { members_.Add((MemberDeclarationSyntax)node); } }
private SyntaxNode TraverseSyntaxTree(SyntaxNode node) { node = node.ReplaceNodes(node.ChildNodes(), (child, dummy) => TraverseSyntaxTree(child)); return Visit(node); }
private IEnumerable<BlockSyntax> GetBlocks(SyntaxNode node) { var childBlocks = node.ChildNodes().Where(x => x.IsKind(SyntaxKind.Block)).Cast<BlockSyntax>(); var others = node.ChildNodes() .Where(x => !x.IsKind(SyntaxKind.Block)) .SelectMany(GetBlocks); return childBlocks.Concat(others); }
private void CheckStatementSyntax(SyntaxNode node) { var syntaxNodes = node.ChildNodes().AsArray(); var statements = syntaxNodes .Where(x => !(x is TypeDeclarationSyntax)) .Where(x => x is BaseFieldDeclarationSyntax || x is StatementSyntax) .AsArray(); foreach (var statement in statements) { _statements.Add(statement); } }
public SyntaxNode TraverseAndConvert(SyntaxNode node, SyntaxNode newNode) { // Step 1: Handle current node // Find out if this node is a documentable API declaration // If not, skip to go to the child nodes. string docCommentId = GetAPIForNode(node); if (docCommentId != null) { // Look up the comment text string docCommentText = GetDocCommentForId(docCommentId); // Get the SyntaxTrivia for the comment SyntaxTree newTree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText(docCommentText); var newTrivia = newTree.GetRoot().GetLeadingTrivia(); // Read a doc comment from a syntax tree. //var classNode = (ClassDeclarationSyntax)newTree.GetRoot().ChildNodes().First(); //var newTrivia = classNode.GetLeadingTrivia(); //var docCommentTrivia = newTrivia.Single(t => t.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia || // t.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia); // Find out if there is an existing comment or doc comment if (node.HasLeadingTrivia) { SyntaxTriviaList triviaList = node.GetLeadingTrivia(); SyntaxTrivia firstComment = triviaList.Last(); foreach (var trivia in triviaList.Reverse()) { SyntaxKind kind = trivia.Kind(); switch (kind) { case SyntaxKind.SingleLineCommentTrivia: case SyntaxKind.MultiLineCommentTrivia: // Found existing comment firstComment = trivia; break; case SyntaxKind.MultiLineDocumentationCommentTrivia: case SyntaxKind.SingleLineDocumentationCommentTrivia: // Found existing XML doc comment firstComment = trivia; break; default: break; } } // Append the doc comment newNode = node.InsertTriviaBefore(firstComment, newTrivia); } else // no leading trivia { newNode = node.WithLeadingTrivia(newTrivia); } } else // not an API node { newNode = node; } if (node.ChildNodes().Count() > 0) { newNode = newNode.ReplaceNodes(newNode.ChildNodes(), TraverseAndConvert); } return newNode; }
private static ClassDeclarationSyntax FindClassDeclaration(SyntaxNode node, string name) { if (node.Kind() == SyntaxKind.ClassDeclaration) { var classNode = node as ClassDeclarationSyntax; if (classNode.Identifier.ValueText == name) { return classNode; } } foreach (var childNode in node.ChildNodes()) { var childClassNode = ITypeSymbolExtensionsTests.FindClassDeclaration(childNode, name); if (childClassNode != null) { return childClassNode; } } return null; }
private static SyntaxNode CastResursiveMethod(SyntaxNode tree, SemanticModel semanticModel, GenRef genRef, Dictionary<SyntaxNode, SyntaxNode> castChanges) { var change = new Dictionary<SyntaxNode, SyntaxNode>(); foreach (var node in tree.ChildNodes()) { // recurse for changed node var casted = CastResursiveMethod(node, semanticModel, genRef, castChanges); var ts = GetGenericType(node, genRef, semanticModel); if (ts != null) { casted = Helpers.CastTo((ExpressionSyntax)casted, ts); if (node.Parent is MemberAccessExpressionSyntax) casted = ((ExpressionSyntax)casted).Parenthesize(); castChanges.Add(node, casted); } if (node != casted) change.Add(node, casted); } if (change.Any()) tree = tree.ReplaceNodes(change.Keys, (x, y) => change[x]); return tree; }
private static bool IsFunctionAndHasBlock(SyntaxNode n) { return IsFunction(n) && n.ChildNodes().Any(c => c.IsKind(SyntaxKind.Block)); }
private static void FindReturnStatements(SyntaxNode node, List<ReturnStatementSyntax> ret) { if (node is ParenthesizedLambdaExpressionSyntax || node is SimpleLambdaExpressionSyntax) return; //any returns in a sub-lambda will be for that lambda. Ignore them. if (node is ReturnStatementSyntax) ret.Add(node.As<ReturnStatementSyntax>()); foreach (var child in node.ChildNodes()) FindReturnStatements(child, ret); }
private SyntaxNode AddLambdaThis(SyntaxNode node) { //SyntaxTreeHelper.PrintTree(node); if (!node.GetAnnotations("haslambdas").Any()) { return node; } /*if (!node.DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().Any()) { return node; }*/ var stmt = CreateLambdaThis(); var stmtlist = new SyntaxList<StatementSyntax>(); stmtlist = stmtlist.Add(stmt); stmtlist = stmtlist.AddRange(node.ChildNodes().OfType<StatementSyntax>()); node = SyntaxFactory.Block(stmtlist); return node; }
private static Dictionary<string, SyntaxTriviaList> GetSimplifiedCommentLookupImpl(SyntaxNode node, SemanticModel model, Dictionary<string, SyntaxTriviaList> lookup) { Func<SyntaxNode, bool> isCorrectSyntaxType = n => { return n is ClassDeclarationSyntax || n is MethodDeclarationSyntax || n is ConstructorDeclarationSyntax || n is DelegateDeclarationSyntax || n is ConversionOperatorDeclarationSyntax || n is DestructorDeclarationSyntax || n is EnumDeclarationSyntax || n is EventDeclarationSyntax || n is EventFieldDeclarationSyntax || n is FieldDeclarationSyntax || n is IndexerDeclarationSyntax || n is InterfaceDeclarationSyntax || n is OperatorDeclarationSyntax || n is PropertyDeclarationSyntax || n is StructDeclarationSyntax || n is EnumMemberDeclarationSyntax; }; foreach (var child in node.ChildNodes()) { if (child.HasLeadingTrivia || child is NamespaceDeclarationSyntax) { lookup = GetSimplifiedCommentLookupImpl(child, model, lookup); if (!isCorrectSyntaxType(child)) { continue; } // A pattern matching expression would be nice here. ISymbol symbol = null; if (child is EventFieldDeclarationSyntax) { var c = child as EventFieldDeclarationSyntax; symbol = model.GetDeclaredSymbol(c.Declaration.Variables.First()); } else if (child is FieldDeclarationSyntax) { var c = child as FieldDeclarationSyntax; symbol = model.GetDeclaredSymbol(c.Declaration.Variables.First()); } else { symbol = model.GetDeclaredSymbol(child); } var commentId = symbol.GetDocumentationCommentId(); lookup.Add(commentId, child.GetLeadingTrivia()); } } return lookup; }