private int ProcessMethodCallsInMethod(MethodDeclarationSyntax node, int n) { int sum = 0; var hashcode = node.Identifier.ToString() + node.ParameterList.ToString(); if (!AnalyzedMethods.ContainsKey(hashcode)) { var newMethods = new List<MethodDeclarationSyntax>(); AnalyzedMethods.Add(hashcode, sum); try { foreach (var methodCall in node.DescendantNodes().OfType<InvocationExpressionSyntax>()) { var semanticModelForThisMethodCall = Document.Project.Solution.GetDocument(methodCall.SyntaxTree).GetSemanticModelAsync().Result; var methodCallSymbol = (IMethodSymbol)semanticModelForThisMethodCall.GetSymbolInfo(methodCall).Symbol; if (methodCallSymbol != null) { if (methodCallSymbol.IsDispatcherBeginInvoke() || methodCallSymbol.IsDispatcherInvoke()) AnalyzedMethods[hashcode]++; var methodDeclarationNode = methodCallSymbol.FindMethodDeclarationNode(); if (methodDeclarationNode != null) newMethods.Add(methodDeclarationNode); } } if (n < 3) { foreach (var newMethod in newMethods) AnalyzedMethods[hashcode] += ProcessMethodCallsInMethod(newMethod, n + 1); } } catch (Exception ex) { Logs.Console.Warn("Caught exception while processing method call node: {0} @ {1}", node, ex.Message); if (!(ex is InvalidProjectFileException || ex is FormatException || ex is ArgumentException || ex is PathTooLongException)) throw; } } else return AnalyzedMethods[hashcode]; return sum; }
public TaskDeclaration(string path, MethodDeclarationSyntax declaration, bool step) { Debug.Assert(path != null); Debug.Assert(declaration != null); this.path = path; this.declaration = declaration; this.step = step; var documentation = declaration .DescendantNodes(descendIntoTrivia: true) .OfType<DocumentationCommentTriviaSyntax>() .FirstOrDefault(); if (documentation != null) comments = documentation.Content.ToString() .Replace("///", "").Trim(' ').TrimEnd('\n').TrimEnd('\r'); }
/// <summary> /// Computes the summary for the given method. /// </summary> /// <param name="method">Method</param> /// <param name="machine">Machine</param> /// <param name="state">State</param> private void ComputeSummaryForMethod(MethodDeclarationSyntax method, ClassDeclarationSyntax machine, ClassDeclarationSyntax state) { List<InvocationExpressionSyntax> givesUpSources = new List<InvocationExpressionSyntax>(); foreach (var call in method.DescendantNodes().OfType<InvocationExpressionSyntax>()) { var model = this.AnalysisContext.Compilation.GetSemanticModel(call.SyntaxTree); var callSymbol = model.GetSymbolInfo(call).Symbol; if (callSymbol == null) { continue; } var definition = SymbolFinder.FindSourceDefinitionAsync(callSymbol, this.AnalysisContext.Solution).Result; if (definition == null) { continue; } var callee = this.AnalysisContext.GetCallee(call); var calleeMethod = definition.DeclaringSyntaxReferences.First().GetSyntax() as BaseMethodDeclarationSyntax; if (this.AnalysisContext.IsSourceOfGivingUpOwnership(call, model, callee) || this.AnalysisContext.Summaries.ContainsKey(calleeMethod)) { givesUpSources.Add(call); } else if (machine.ChildNodes().OfType<BaseMethodDeclarationSyntax>().Contains(calleeMethod) && !this.AnalysisContext.Summaries.ContainsKey(calleeMethod) && !calleeMethod.Modifiers.Any(SyntaxKind.AbstractKeyword)) { return; } } MethodSummary summary = MethodSummary.Factory.Summarize(this.AnalysisContext, method, machine, state); foreach (var givesUpNode in summary.GivesUpNodes) { this.TryComputeGivesUpSetForSendControlFlowGraphNode(givesUpNode, summary); this.TryComputeGivesUpSetForCreateControlFlowGraphNode(givesUpNode, summary); this.TryComputeGivesUpSetForGenericControlFlowGraphNode(givesUpNode, summary); } }
private SyntaxNode rewriteFunction(MethodDeclarationSyntax node, bool asPublic) { //since no return type has been spacified we need to know if it returns something bool returns = node.DescendantNodes().OfType<ReturnStatementSyntax>().Any(); TypeSyntax rtype = returns ? SyntaxFactory.IdentifierName("object") : SyntaxFactory.IdentifierName("void"); List<SyntaxToken> modifiers = new List<SyntaxToken>(); bool found = false; foreach (var mod in node.Modifiers) { switch(mod.CSharpKind()) { case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.ProtectedKeyword: case SyntaxKind.InternalKeyword: { found = true; break; } } modifiers.Add(mod); } if (!found) { if (asPublic) modifiers.AddRange(Compiler.Public); else modifiers.AddRange(Compiler.Private); } SyntaxNode result = SyntaxFactory.MethodDeclaration(rtype, node.Identifier) .WithModifiers(SyntaxFactory.TokenList(modifiers)) .WithParameterList(rewriteParamList(node.ParameterList)) .WithBody(rewriteBody(node.Body)) .WithAdditionalAnnotations( new SyntaxAnnotation("ExcessFunction")); return returns? ctx_.AddLinker(result, (ctx, linkNode, newNode, model) => { MethodDeclarationSyntax mthod = (MethodDeclarationSyntax)linkNode; ControlFlowAnalysis cfa = model.AnalyzeControlFlow(mthod.Body); ITypeSymbol rt = null; foreach (var rs in cfa.ReturnStatements) { ReturnStatementSyntax rss = (ReturnStatementSyntax)rs; ITypeSymbol type = model.GetSpeculativeTypeInfo(rss.Expression.SpanStart, rss.Expression, SpeculativeBindingOption.BindAsExpression).Type; if (type == null) continue; if (type.TypeKind == TypeKind.Error) return newNode; if (rt == null) rt = type; else if (rt != type) return newNode; } if (rt == null) return newNode; MethodDeclarationSyntax res = (MethodDeclarationSyntax)newNode; return res.WithReturnType(SyntaxFactory.ParseTypeName(rt.Name)); }) : result; }
private static string CreateSafeLocalVariableName(MethodDeclarationSyntax methodNode, IMethodSymbol methodSymbol) { var localDeclarations = methodNode.DescendantNodes(_ => true).OfType<VariableDeclaratorSyntax>(); var returnValueName = $"{methodSymbol.Name.Substring(0, 1).ToLower()}{methodSymbol.Name.Substring(1)}Result"; var returnValueSafeName = returnValueName; var returnValueCount = 0; // Create a "safe" local variable name. while (localDeclarations.Any(_ => _.Identifier.Text == returnValueSafeName)) { returnValueSafeName = $"{returnValueName}{returnValueCount}"; returnValueCount++; } return returnValueSafeName; }
private static bool IsUnnecessaryAsyncAwait(MethodDeclarationSyntax node) { if(node.AttributeLists.Any(a => a.ToFullString().Contains("TestMethod"))) { return false; } int numAwaits = Regex.Matches(node.Body.ToString(), "await").Count; int numReturnAwaits = Regex.Matches(node.Body.ToString(), "return await").Count; if (!node.ReturnType.ToString().Equals("void") && !node.DescendantNodes().OfType<StatementSyntax>().Where(a => a.ToString().Contains("await")).Any(a => a.Ancestors().OfType<TryStatementSyntax>().Any())) { if (numAwaits == numReturnAwaits) return true; else if (numAwaits == 1 && node.Body.Statements.Count > 0 && node.Body.Statements.Last().ToString().StartsWith("await")) return true; } return false; }
private bool IsUnnecessarilyCaptureContext(MethodDeclarationSyntax node, int n) { if (CheckUIElementAccess(node)) return false; else { bool result = true; { var newMethods = new List<MethodDeclarationSyntax>(); try { var semanticModel = SourceFile.Project.Solution.GetDocument(node.SyntaxTree).GetSemanticModelAsync().Result; if (semanticModel != null) { foreach (var methodCall in node.DescendantNodes().OfType<InvocationExpressionSyntax>()) { var methodCallSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(methodCall).Symbol; if (methodCallSymbol != null) { var methodDeclarationNode = methodCallSymbol.FindMethodDeclarationNode(); if (methodDeclarationNode != null && n < 10) newMethods.Add(methodDeclarationNode); } } } foreach (var newMethod in newMethods) result = result && IsUnnecessarilyCaptureContext(newMethod, n + 1); } catch (Exception ex) { } } return result; } }
private bool IsThereLongRunning(MethodDeclarationSyntax node, out string replacement) { replacement = string.Empty; foreach (var blocking in node.DescendantNodes().OfType<MemberAccessExpressionSyntax>().Where(a => BlockingMethodCalls.Any(b => b.Equals(a.Name.ToString())))) { replacement = "Blocking Method Calls"; return true; } foreach (var methodCall in node.DescendantNodes().OfType<InvocationExpressionSyntax>()) { var methodCallSymbol = (IMethodSymbol)SemanticModel.GetSymbolInfo(methodCall).Symbol; if (methodCallSymbol != null) { replacement = DetectSynchronousUsages((IMethodSymbol)methodCallSymbol.OriginalDefinition, SemanticModel); if (!string.IsNullOrEmpty(replacement)) { if (!methodCallSymbol.Name.ToString().Equals("Invoke")) { return true; } } } } return false; }
private void ProcessMethodCallsInMethod(MethodDeclarationSyntax node, int n, string topAncestor) { var hashcode = node.Identifier.ToString() + node.ParameterList.ToString(); bool asyncFlag = false; if (node.HasAsyncModifier()) asyncFlag = true; if (!AnalyzedMethods.Contains(hashcode)) { AnalyzedMethods.Add(hashcode); var newMethods = new List<MethodDeclarationSyntax>(); try { var semanticModel = Document.Project.Solution.GetDocument(node.SyntaxTree).GetSemanticModelAsync().Result; foreach (var blocking in node.DescendantNodes().OfType<MemberAccessExpressionSyntax>().Where(a => BlockingMethodCalls.Any(b => b.Equals(a.Name.ToString())))) { Logs.TempLog2.Info("BLOCKING {0} {1} {2}\r\n{3} \r\n{4}\r\n{5}\r\n--------------------------", asyncFlag, n, blocking, Document.FilePath, topAncestor, node); } foreach (var blocking in node.DescendantNodes().OfType<MemberAccessExpressionSyntax>().Where(a => a.Name.ToString().Equals("Result"))) { var s = semanticModel.GetSymbolInfo(blocking).Symbol; if (s != null && s.ToString().Contains("System.Threading.Tasks")) Logs.TempLog2.Info("BLOCKING {0} {1} {2}\r\n{3} \r\n{4}\r\n{5}\r\n--------------------------", asyncFlag, n, blocking, Document.FilePath, topAncestor, node); } foreach (var methodCall in node.DescendantNodes().OfType<InvocationExpressionSyntax>()) { var methodCallSymbol = (IMethodSymbol)semanticModel.GetSymbolInfo(methodCall).Symbol; if (methodCallSymbol != null) { var replacement = ((IMethodSymbol)methodCallSymbol.OriginalDefinition).DetectSynchronousUsages(SemanticModel); if (replacement != "None") { if (!methodCallSymbol.Name.ToString().Equals("Invoke")) Logs.TempLog2.Info("LONGRUNNING {0} {1} {2} {3}\r\n{4} {5}\r\n{6}\r\n--------------------------", asyncFlag, n, methodCallSymbol, Document.FilePath, replacement, topAncestor, node); Logs.TempLog3.Info("{0} {1}", methodCallSymbol.ContainingType, methodCallSymbol, replacement); } var methodDeclarationNode = methodCallSymbol.FindMethodDeclarationNode(); if (methodDeclarationNode != null) newMethods.Add(methodDeclarationNode); } } foreach (var newMethod in newMethods) ProcessMethodCallsInMethod(newMethod, n + 1, topAncestor); } catch (Exception ex) { Logs.Console.Warn("Caught exception while processing method call node: {0} @ {1}", node, ex.Message); if (!( ex is FormatException || ex is ArgumentException || ex is PathTooLongException)) throw; } } }
private static IEnumerable<string> DeclaredIdentifiers(MethodDeclarationSyntax syntax) { var methodParameterNames = syntax.ParameterList.Parameters .Select(p => p.Identifier.ValueText); var methodLocalVars = syntax .DescendantNodes() .OfType<LocalDeclarationStatementSyntax>() .SelectMany(d => d.Declaration.Variables) .Select(v => v.Identifier.ValueText); var classFieldIds = syntax.ContainingClass() .DescendantNodes() .OfType<FieldDeclarationSyntax>() .SelectMany(f => f.Declaration.Variables) .Select(v => v.Identifier.ValueText); var classPropertyIds = syntax.ContainingClass() .DescendantNodes() .OfType<PropertyDeclarationSyntax>() .Select(p => p.Identifier.ValueText); var classMethodIds = syntax.ContainingClass() .DescendantNodes() .OfType<MethodDeclarationSyntax>() .Select(m => m.Identifier.ValueText); var classDelegateIds = syntax.ContainingClass() .DescendantNodes() .OfType<DelegateDeclarationSyntax>() .Select(d => d.Identifier.ValueText); return methodParameterNames .Concat(methodLocalVars) .Concat(classFieldIds) .Concat(classPropertyIds) .Concat(classMethodIds) .Concat(classDelegateIds); }
private void ExtractMethodTests(TestFixtureDetails testFixture, MethodDeclarationSyntax methodNode, ISemanticModel semanticModel) { var allMethodTestCases = new List<TestCase>(); foreach (AttributeSyntax attribute in methodNode.DescendantNodes().OfType<AttributeSyntax>()) { var methodTestCases=ExtractMethodsFromAttributes(testFixture, semanticModel, attribute); allMethodTestCases.AddRange(methodTestCases); } if (allMethodTestCases.Count > 0) { int maxPars = allMethodTestCases.Max(x => x.Arguments.Length); testFixture.Cases.AddRange(allMethodTestCases.Where(x => x.Arguments.Length == maxPars)); } }