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;
        }
Ejemplo n.º 2
0
        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');
        }
Ejemplo n.º 3
0
        /// <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);
            }
        }
Ejemplo n.º 4
0
        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));
            }
        }