// Implementation based on https://github.com/mauricioaniche/ck private int CountLoops(MemberDeclarationSyntax method) { int count = method.DescendantNodes().OfType <ForEachStatementSyntax>().Count(); count += method.DescendantNodes().OfType <ForStatementSyntax>().Count(); count += method.DescendantNodes().OfType <WhileStatementSyntax>().Count(); count += method.DescendantNodes().OfType <DoStatementSyntax>().Count(); return(count); }
private int CountUnaryExpressions(MemberDeclarationSyntax method) { int count = method.DescendantNodes().OfType <PrefixUnaryExpressionSyntax>() .Count(n => n.IsKind(SyntaxKind.PreIncrementExpression) || n.IsKind(SyntaxKind.PreDecrementExpression) || n.IsKind(SyntaxKind.UnaryPlusExpression) || n.IsKind(SyntaxKind.UnaryMinusExpression)); count += method.DescendantNodes().OfType <PostfixUnaryExpressionSyntax>() .Count(n => n.IsKind(SyntaxKind.PostIncrementExpression) || n.IsKind(SyntaxKind.PostDecrementExpression)); return(count); }
// Implementation based on https://github.com/mauricioaniche/ck private int CountComparisonOperators(MemberDeclarationSyntax method) { int count = method.DescendantNodes().OfType <AssignmentExpressionSyntax>() .Count(n => n.IsKind(SyntaxKind.CoalesceAssignmentExpression)); count += method.DescendantNodes().OfType <BinaryExpressionSyntax>() .Count(n => n.IsKind(SyntaxKind.EqualsExpression) || n.IsKind(SyntaxKind.NotEqualsExpression) || n.IsKind(SyntaxKind.LessThanExpression) || n.IsKind(SyntaxKind.LessThanOrEqualExpression) || n.IsKind(SyntaxKind.GreaterThanExpression) || n.IsKind(SyntaxKind.GreaterThanOrEqualExpression) || n.IsKind(SyntaxKind.CoalesceExpression)); return(count); }
public static TextSpan GetSpanOfAssignmentDependenciesAndDeclarationsInSpan(this MemberDeclarationSyntax containingMethod, TextSpan textSpan, SemanticModel model, CancellationToken cancellationToken = default(CancellationToken)) { var resultSpan = textSpan; List <SyntaxNode> dependentAssignments = new List <SyntaxNode>(); var tokenKeyComparer = Comparer <int> .Default; do { SyntaxNode[] assignments = containingMethod.DescendantNodes(resultSpan) .Where(e => (e is AssignmentExpressionSyntax || e is EqualsValueClauseSyntax) && !dependentAssignments.Contains(e)).ToArray(); if (!assignments.Any()) // no newly found assignments, done { break; } dependentAssignments.AddRange(assignments); IEnumerable <ISymbol> symbolsAssigned = dependentAssignments.Select(e => GetAssignmentSymbol(e, model, cancellationToken)); SortedSet <SyntaxToken> references = new SortedSet <SyntaxToken>(Comparer <SyntaxToken> .Create((token, syntaxToken) => tokenKeyComparer.Compare( token.SpanStart, syntaxToken.SpanStart))); foreach (ISymbol symbol in symbolsAssigned) { var symbolReferences = GetSymbolReferences(containingMethod, symbol); references.UnionWith(symbolReferences); } resultSpan = GetBoundingSpan(references); } while (true); return(resultSpan); }
private static bool HasInstanceReferences(MemberDeclarationSyntax memberDeclaration, SemanticModel semanticModel) { return(memberDeclaration.DescendantNodes() .OfType <ExpressionSyntax>() .Where(IsLeftmostIdentifierName) .Where(n => !SyntaxHelper.IsInNameofCall(n, semanticModel)) .Any(n => IsInstanceMember(n, semanticModel))); }
private int CountBinaryExpressions(MemberDeclarationSyntax method) { return(method.DescendantNodes().OfType <BinaryExpressionSyntax>() .Count(n => n.IsKind(SyntaxKind.AddExpression) || n.IsKind(SyntaxKind.SubtractExpression) || n.IsKind(SyntaxKind.MultiplyExpression) || n.IsKind(SyntaxKind.DivideExpression) || n.IsKind(SyntaxKind.ModuloExpression) || n.IsKind(SyntaxKind.LeftShiftExpression) || n.IsKind(SyntaxKind.RightShiftExpression))); }
private int CalculateCyclomaticComplexity(MemberDeclarationSyntax method) { //Defined based on https://www.ndepend.com/docs/code-metrics#CC int count = method.DescendantNodes().OfType <IfStatementSyntax>().Count(); count += method.DescendantNodes().OfType <WhileStatementSyntax>().Count(); count += method.DescendantNodes().OfType <ForStatementSyntax>().Count(); count += method.DescendantNodes().OfType <ForEachStatementSyntax>().Count(); count += method.DescendantNodes().OfType <CaseSwitchLabelSyntax>().Count(); count += method.DescendantNodes().OfType <DefaultSwitchLabelSyntax>().Count(); count += method.DescendantNodes().OfType <ContinueStatementSyntax>().Count(); count += method.DescendantNodes().OfType <GotoStatementSyntax>().Count(); count += method.DescendantNodes().OfType <ConditionalExpressionSyntax>().Count(); count += method.DescendantNodes().OfType <CatchClauseSyntax>().Count(); count += CountLogicalOperators(method, "&&"); count += CountLogicalOperators(method, "||"); count += CountLogicalOperators(method, "??"); return(count + 1); }
public static bool IsAccessibleProperty(this MemberDeclarationSyntax member) { var isPublicProperty = member.IsKind(SyntaxKind.PropertyDeclaration) && member.Modifiers.Contains(m => m.IsKind(SyntaxKind.PublicKeyword)); var getter = member.DescendantNodes() .Where(a => a.IsKind(SyntaxKind.GetAccessorDeclaration)) .Cast <AccessorDeclarationSyntax>() .Where(g => g.HasModifiers() == false) .SingleOrDefault(); return(isPublicProperty && getter != default); }
private static IEnumerable <ThrowInfo> GetOtherUndocumentedExceptions( MemberDeclarationSyntax declaration, ISymbol declarationSymbol, Func <SyntaxNode, bool> predicate, SemanticModel semanticModel, CancellationToken cancellationToken) { foreach (SyntaxNode node in declaration.DescendantNodes(f => !f.IsKind( SyntaxKind.AnonymousMethodExpression, SyntaxKind.SimpleLambdaExpression, SyntaxKind.ParenthesizedLambdaExpression))) { switch (node.Kind()) { case SyntaxKind.ThrowStatement: { if (predicate(node)) { var throwStatement = (ThrowStatementSyntax)node; ThrowInfo info = GetUndocumentedExceptionInfo(node, throwStatement.Expression, declaration, declarationSymbol, semanticModel, cancellationToken); if (info != null) { yield return(info); } } break; } case SyntaxKind.ThrowExpression: { if (predicate(node)) { var throwExpression = (ThrowExpressionSyntax)node; ThrowInfo info = GetUndocumentedExceptionInfo(node, throwExpression.Expression, declaration, declarationSymbol, semanticModel, cancellationToken); if (info != null) { yield return(info); } } break; } } } }
private static IEnumerable <ThrowInfo> GetOtherUndocumentedExceptions( MemberDeclarationSyntax declaration, ISymbol declarationSymbol, Func <SyntaxNode, bool> predicate, INamedTypeSymbol exceptionSymbol, SemanticModel semanticModel, CancellationToken cancellationToken) { foreach (SyntaxNode node in declaration.DescendantNodes(f => !CSharpFacts.IsAnonymousFunctionExpression(f.Kind()))) { switch (node.Kind()) { case SyntaxKind.ThrowStatement: { if (predicate(node)) { var throwStatement = (ThrowStatementSyntax)node; ThrowInfo info = GetUndocumentedExceptionInfo(node, throwStatement.Expression, declaration, declarationSymbol, exceptionSymbol, semanticModel, cancellationToken); if (info != null) { yield return(info); } } break; } case SyntaxKind.ThrowExpression: { if (predicate(node)) { var throwExpression = (ThrowExpressionSyntax)node; ThrowInfo info = GetUndocumentedExceptionInfo(node, throwExpression.Expression, declaration, declarationSymbol, exceptionSymbol, semanticModel, cancellationToken); if (info != null) { yield return(info); } } break; } } } }
// Implementation based on https://github.com/mauricioaniche/ck private int CountMaxNestedBlocks(MemberDeclarationSyntax method) { var blocks = method.DescendantNodes().OfType <BlockSyntax>().ToList(); List <int> blocksAncestors = new List <int>(); foreach (var block in blocks) { blocksAncestors.Add(block.Ancestors().Count(a => a.IsKind(SyntaxKind.Block))); } if (!blocksAncestors.Any()) { return(0); } return(blocksAncestors.Max()); }
/// <summary> /// Determines if we are before or after the members of this container (or if there are none) /// </summary> /// <param name="currMember">The namespace or class SyntxNode</param> /// <param name="position">The position in the text</param> /// <returns>-1 if position is before all members, 0 if there are none, 1 if it is after all members</returns> private static int getPosInContainer(MemberDeclarationSyntax currMember, int position) { var lastMember = currMember.DescendantNodes().OfType <MemberDeclarationSyntax>().LastOrDefault(); if (lastMember == null) { return(0); } else if (position > lastMember.FullSpan.End) { return(1); } else { return(-1); } }
public static async Task <IEnumerable <DependecyData> > ExtractContextDependencies(Solution solution, MemberDeclarationSyntax member, CancellationToken cancellationToken) { var document = solution.GetDocument(member.SyntaxTree); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var memberSymbol = semanticModel.GetDeclaredSymbol(member); var result = new List <DependecyData>(); var identifierNameSyntaxes = member.DescendantNodes().OfType <IdentifierNameSyntax>().ToList(); foreach (var item in identifierNameSyntaxes) { var symbolInfo = semanticModel.GetSymbolInfo(item); var symbol = symbolInfo.Symbol; if (symbol != null) { if (symbol is ILocalSymbol localSymbol) { continue; } if (!SymbolEqualityComparer.Default.Equals(symbol.ContainingSymbol, memberSymbol.ContainingSymbol)) { continue; } var typeInfo = semanticModel.GetTypeInfo(item); var type = typeInfo.Type; if ((type != null) && (type.IsImplicitlyDeclared == false)) { var dependecyData = new DependecyData() { Name = symbol.Name.ToString(), Type = type.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), Using = type.ContainingNamespace.ToString(), }; result.Add(dependecyData); } } } return(result.Distinct()); }
private static IEnumerable <ThrowInfo> GetOtherUndocumentedExceptions( MemberDeclarationSyntax containingMember, Func <SyntaxNode, bool> predicate, SemanticModel semanticModel, CancellationToken cancellationToken) { foreach (SyntaxNode descendant in containingMember.DescendantNodes()) { switch (descendant.Kind()) { case SyntaxKind.ThrowStatement: { if (predicate(descendant)) { var throwStatement = (ThrowStatementSyntax)descendant; ThrowInfo info = GetUndocumentedExceptionInfo(descendant, throwStatement.Expression, containingMember, semanticModel, cancellationToken); if (info != null) { yield return(info); } } break; } case SyntaxKind.ThrowExpression: { if (predicate(descendant)) { var throwExpression = (ThrowExpressionSyntax)descendant; ThrowInfo info = GetUndocumentedExceptionInfo(descendant, throwExpression.Expression, containingMember, semanticModel, cancellationToken); if (info != null) { yield return(info); } } break; } } } }
private void SearchInsideStructures <T>( MemberDeclarationSyntax memberDeclaration, string namespaceIdentifier) { var insideStructures = memberDeclaration .DescendantNodes().OfType <T>(); if (insideStructures.Any()) { foreach (var insideStructure in insideStructures) { if (insideStructure is MemberDeclarationSyntax insideMember) { FillStructureCollection( insideMember, namespaceIdentifier); } } } }
private List <CaDETVariable> GetMethodVariables() { List <CaDETVariable> methodVariables = new List <CaDETVariable>(); if (_cSharpMember is PropertyDeclarationSyntax) { return(methodVariables); } var variableDeclarations = _cSharpMember.DescendantNodes().OfType <VariableDeclarationSyntax>(); foreach (var variableDeclaration in variableDeclarations) { foreach (var variable in variableDeclaration.Variables) { methodVariables.Add(new CaDETVariable(variable.Identifier.ToString(), new CaDETLinkedType() { FullType = ((ILocalSymbol)_semanticModel.GetDeclaredSymbol(variable)).Type.ToString() })); } } return(methodVariables); }
// Implementation based on https://github.com/mauricioaniche/ck private int CountNumberOfStringLiterals(MemberDeclarationSyntax method) { return(method.DescendantNodes().OfType <LiteralExpressionSyntax>().Count(n => n.IsKind(SyntaxKind.StringLiteralExpression))); }
/// <summary> /// Entry point of the program: generates the 'Ryder.Lightweight.cs' file. /// </summary> public static int Main(string[] args) { string ns = null; string dir = Directory.GetCurrentDirectory(); string output = Path.Combine(Directory.GetCurrentDirectory(), OUTPUT_FILENAME); bool makePublic = false; for (int i = 0; i < args.Length; i++) { switch (args[i]) { case "--public": case "-p": makePublic = true; break; case "--namespace": case "-n": if (args.Length == i + 1) { Console.Error.WriteLine("No namespace given."); return(1); } ns = args[++i]; break; case "--directory": case "-d": if (args.Length == i + 1) { Console.Error.WriteLine("No directory given."); return(1); } dir = args[++i]; break; case "--output": case "-o": if (args.Length == i + 1) { Console.Error.WriteLine("No directory given."); return(1); } output = args[++i]; break; default: Console.Error.WriteLine($"Unknown argument: '{args[i]}'."); return(1); } } string methodRedirectionPath = Path.Combine(dir, "Redirection.Method.cs"); string helpersPath = Path.Combine(dir, "Helpers.cs"); if (!File.Exists(methodRedirectionPath) || !File.Exists(helpersPath)) { Console.Error.WriteLine("Invalid directory given."); return(1); } try { // Read files string methodRedirectionContent = File.ReadAllText(methodRedirectionPath); string helpersContent = File.ReadAllText(helpersPath); // Parse content to trees, and get their root / classes / usings SyntaxTree methodRedirectionTree = SyntaxFactory.ParseSyntaxTree(methodRedirectionContent, path: methodRedirectionPath); SyntaxTree helpersTree = SyntaxFactory.ParseSyntaxTree(helpersContent, path: helpersPath); CompilationUnitSyntax methodRedirection = methodRedirectionTree.GetCompilationUnitRoot(); CompilationUnitSyntax helpers = helpersTree.GetCompilationUnitRoot(); UsingDirectiveSyntax[] usings = methodRedirection.Usings.Select(x => x.Name.ToString()) .Concat(helpers.Usings.Select(x => x.Name.ToString())) .Distinct() .OrderBy(x => x) .Select(x => SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(x))) .ToArray(); ClassDeclarationSyntax methodRedirectionClass = methodRedirection.DescendantNodes() .OfType <ClassDeclarationSyntax>() .First(); ClassDeclarationSyntax helpersClass = helpers.DescendantNodes() .OfType <ClassDeclarationSyntax>() .First(); // Set visibility of main class if (!makePublic) { var modifiers = methodRedirectionClass.Modifiers; var publicModifier = modifiers.First(x => x.Kind() == SyntaxKind.PublicKeyword); methodRedirectionClass = methodRedirectionClass.WithModifiers( modifiers.Replace(publicModifier, SyntaxFactory.Token(SyntaxKind.InternalKeyword)) ); } // Set visibility of helpers class helpersClass = helpersClass.WithModifiers( helpersClass.Modifiers.Replace( helpersClass.Modifiers.First(x => x.Kind() == SyntaxKind.InternalKeyword), SyntaxFactory.Token(SyntaxKind.PrivateKeyword) ) ); // Change helpers class extension methods to normal methods var extMethods = helpersClass.DescendantNodes() .OfType <MethodDeclarationSyntax>() .Where(x => x.ParameterList.DescendantTokens().Any(tok => tok.Kind() == SyntaxKind.ThisKeyword)); var extMethodsNames = extMethods.Select(x => x.Identifier.Text); helpersClass = helpersClass.ReplaceNodes( helpersClass.DescendantNodes().OfType <ParameterSyntax>().Where(x => x.Modifiers.Any(SyntaxKind.ThisKeyword)), (x, _) => x.WithModifiers(x.Modifiers.Remove(x.Modifiers.First(y => y.Kind() == SyntaxKind.ThisKeyword))) ); // Disable overrides var members = methodRedirectionClass.Members; for (int i = 0; i < members.Count; i++) { var member = members[i]; if (!(member is MethodDeclarationSyntax method)) { if (member is ConstructorDeclarationSyntax ctor) { members = members.Replace(ctor, ctor.WithIdentifier(SyntaxFactory.Identifier("Redirection"))); } continue; } var overrideModifier = method.Modifiers.FirstOrDefault(x => x.Kind() == SyntaxKind.OverrideKeyword); if (overrideModifier == default(SyntaxToken)) { continue; } method = method.WithModifiers( method.Modifiers.Remove(overrideModifier) ); members = members.Replace(member, method); } // Add missing field var field = SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration( SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.BoolKeyword)), SyntaxFactory.SeparatedList(new[] { SyntaxFactory.VariableDeclarator("isRedirecting") }) ) ); const string DOCS = @" /// <summary> /// Provides the ability to redirect calls from one method to another. /// </summary> "; var disposableType = SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseTypeName(nameof(IDisposable))); methodRedirectionClass = methodRedirectionClass.WithMembers(members) // Add docs .WithLeadingTrivia(SyntaxFactory.Comment(DOCS)) // Rename to 'Redirection' .WithIdentifier(SyntaxFactory.Identifier("Redirection")) // Disable inheritance, but implement IDisposable .WithBaseList(SyntaxFactory.BaseList().AddTypes(disposableType)) // Embed helpers, missing field .AddMembers(field, helpersClass); // Generate namespace (or member, if no namespace is specified) MemberDeclarationSyntax @namespace = ns == null ? (MemberDeclarationSyntax)methodRedirectionClass : SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(ns)).AddMembers(methodRedirectionClass); var extCalls = @namespace.DescendantNodes() .OfType <InvocationExpressionSyntax>() .Where(x => x.Expression is MemberAccessExpressionSyntax access && extMethodsNames.Contains(access.Name.Identifier.Text)); var helpersAccess = SyntaxFactory.IdentifierName("Helpers"); @namespace = @namespace.ReplaceNodes( extCalls, (x, _) => SyntaxFactory.InvocationExpression(((MemberAccessExpressionSyntax)x.Expression).WithExpression(helpersAccess)).WithArgumentList(x.ArgumentList.WithArguments(x.ArgumentList.Arguments.Insert(0, SyntaxFactory.Argument(((MemberAccessExpressionSyntax)x.Expression).Expression))))); // Generate syntax root CompilationUnitSyntax root = SyntaxFactory.CompilationUnit() .AddUsings(usings) .AddMembers(@namespace); // Print root to file using (FileStream fs = File.OpenWrite(output)) using (TextWriter writer = new StreamWriter(fs)) { fs.SetLength(0); Formatter.Format(root, new AdhocWorkspace()).WriteTo(writer); } } catch (Exception e) { Console.Error.WriteLine("Error encountered:"); Console.Error.WriteLine(e.Message); return(1); } return(0); }
private static bool isContainer(MemberDeclarationSyntax currMember) { return(currMember.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.ClassDeclaration) || currMember.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.NamespaceDeclaration) && currMember.DescendantNodes().OfType <MemberDeclarationSyntax>().Count() > 0); }
/// <summary> /// DOI: 10.1002/smr.2255 /// </summary> private int GetNumberOfLocalVariables(MemberDeclarationSyntax method) { return(method.DescendantNodes().OfType <VariableDeclarationSyntax>().Count()); }
// Implementation based on https://github.com/mauricioaniche/ck private int CountNumberOfLambdaExpressions(MemberDeclarationSyntax method) { return(method.DescendantNodes().OfType <LambdaExpressionSyntax>().Count()); }
// Implementation based on https://github.com/mauricioaniche/ck private int CountNumberOfParenthesizedExpressions(MemberDeclarationSyntax method) { return(method.DescendantNodes().OfType <ExpressionSyntax>() .Count(n => n.IsKind(SyntaxKind.ParenthesizedExpression))); }
private void VisitIndexerOrPropertyDeclarationSyntax(MemberDeclarationSyntax node) { IEnumerable<BlockSyntax> accessorBlocks = node.DescendantNodes() .OfType<AccessorDeclarationSyntax>() .Select(a => a.DescendantNodes().OfType<BlockSyntax>().FirstOrDefault()); Symbol symbol = _semanticModel.GetDeclaredSymbol(node); if (symbol != null) { _members.Add(new MemberInfo(node, symbol, _semanticModel, accessorBlocks)); } }
// Implementation based on https://github.com/mauricioaniche/ck private int CountNumberOfAssignments(MemberDeclarationSyntax method) { return(method.DescendantNodes().OfType <AssignmentExpressionSyntax>().Count()); }
// Implementation based on https://github.com/mauricioaniche/ck private int CountTryCatchBlocks(MemberDeclarationSyntax method) { return(method.DescendantNodes().OfType <TryStatementSyntax>().Count()); }
// Implementation based on https://github.com/mauricioaniche/ck private int CountReturnStatements(MemberDeclarationSyntax method) { return(method.DescendantNodes().OfType <ReturnStatementSyntax>().Count()); }