private string?GetAnsiConsoleParameterDeclaration() { return(_originalInvocation .Ancestors().OfType <MethodDeclarationSyntax>() .First() .ParameterList.Parameters .FirstOrDefault(i => i.Type.NormalizeWhitespace().ToString() == "IAnsiConsole") ?.Identifier.Text); }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { var symbol = (IMethodSymbol)SemanticModel.GetSymbolInfo(node).Symbol; if (symbol != null) { if(symbol.ToString().Contains("System.Threading.Tasks.Task.WaitAll")) { var block = node.Ancestors().OfType<BlockSyntax>().First(); if (block.DescendantNodes().OfType<ForEachStatementSyntax>().Any() || block.DescendantNodes().OfType<ForStatementSyntax>().Any()) return; foreach (var invocation in block.DescendantNodes().OfType<InvocationExpressionSyntax>()) { var symbol2 = (IMethodSymbol)SemanticModel.GetSymbolInfo(invocation).Symbol; if (symbol2!=null && symbol2.IsTaskCreationMethod()) { Logs.TempLog3.Info("{0}{1}--------------------------", Document.FilePath, block.ToLog()); break; } } } } base.VisitInvocationExpression(node); }
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) { // Replace the module method name with a qualified one if this is a module ctor bool nodeChanged = IsInvocationAModuleCtor(node); ExpressionSyntax nodeExpression = nodeChanged ? ((IdentifierNameSyntax)node.Expression).WithIdentifier( SyntaxFactory.Identifier("ConfigScript." + ((IdentifierNameSyntax)node.Expression).Identifier.Text) .WithTriviaFrom(((IdentifierNameSyntax)node.Expression).Identifier)) : node.Expression; // Get a hash of all the previous @doc and @ctx lambda parameters and don't replace the same HashSet<string> currentScopeLambdaParameters = new HashSet<string>( node.Ancestors().OfType<LambdaExpressionSyntax>().SelectMany( x => x.DescendantNodes().OfType<ParameterSyntax>()).Select(x => x.Identifier.Text)); // Only do the replacement if this is a module ctor or a module fluent method ArgumentListSyntax argumentList = node.ArgumentList; if(nodeChanged || IsInvocationAFluentMethod(node)) { // Replace @doc and @ctx argument expressions with the appropriate lambda expressions, and stop descending if we hit another module ctor foreach (ArgumentSyntax argument in node.ArgumentList.Arguments) { // Don't replace existing lambda expressions if (!(argument.Expression is LambdaExpressionSyntax)) { List<IdentifierNameSyntax> identifierNames = argument .DescendantNodes(x => !(x is InvocationExpressionSyntax) || !IsInvocationAModuleCtorOrFluentMethod((InvocationExpressionSyntax)x)) .OfType<IdentifierNameSyntax>() .Where(x => x != null && !currentScopeLambdaParameters.Contains(x.Identifier.Text)) .ToList(); IdentifierNameSyntax docReplacementName = identifierNames.FirstOrDefault(x => x.Identifier.Text.StartsWith("@doc")); IdentifierNameSyntax ctxReplacementName = identifierNames.FirstOrDefault(x => x.Identifier.Text.StartsWith("@ctx")); if (docReplacementName != null) { argumentList = argumentList.ReplaceNode(argument, SyntaxFactory.Argument( SyntaxFactory.ParenthesizedLambdaExpression( SyntaxFactory.ParameterList( new SeparatedSyntaxList<ParameterSyntax>() .Add(SyntaxFactory.Parameter(SyntaxFactory.Identifier(docReplacementName.Identifier.Text))) .Add(SyntaxFactory.Parameter(SyntaxFactory.Identifier(ctxReplacementName == null ? "_" : ctxReplacementName.Identifier.Text)))), argument.Expression)) .WithTriviaFrom(argument)); nodeChanged = true; } else if (ctxReplacementName != null) { argumentList = argumentList.ReplaceNode(argument, SyntaxFactory.Argument( SyntaxFactory.SimpleLambdaExpression( SyntaxFactory.Parameter(SyntaxFactory.Identifier(ctxReplacementName.Identifier.Text)), argument.Expression)) .WithTriviaFrom(argument)); nodeChanged = true; } } } } // Build and return the result node (or just return the original node) return base.VisitInvocationExpression(nodeChanged ? node.WithExpression(nodeExpression).WithArgumentList(argumentList) : node); }
private static bool IsInsideANullCheck(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) { var ifs = invocation.Ancestors().OfType <IfStatementSyntax>(); foreach (IfStatementSyntax @if in ifs) { if ([email protected]?.IsKind(SyntaxKind.NotEqualsExpression) ?? true) { continue; } var equals = (BinaryExpressionSyntax)@if.Condition; if (equals.Left == null || equals.Right == null) { continue; } ISymbol identifierSymbol; if (equals.Right.IsKind(SyntaxKind.NullLiteralExpression) && equals.Left.IsKind(SyntaxKind.IdentifierName)) { identifierSymbol = semanticModel.GetSymbolInfo(equals.Left).Symbol; } else if (equals.Left.IsKind(SyntaxKind.NullLiteralExpression) && equals.Right.IsKind(SyntaxKind.IdentifierName)) { identifierSymbol = semanticModel.GetSymbolInfo(equals.Right).Symbol; } else { continue; } if (symbol.Equals(identifierSymbol)) { return(true); } } return(false); }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { try { var target = _semanticModel.GetSymbolInfo(node.Expression); if (target.Symbol.Name == "SetCommandType") { var commandTypeParameter = node.ArgumentList.Arguments[1].Expression as MemberAccessExpressionSyntax; if (commandTypeParameter != null && commandTypeParameter.Name.Identifier.ValueText == "StoredProcedure") { var storedProcedureName = _semanticModel.GetConstantValue(node.ArgumentList.Arguments[2].Expression).Value.ToString(); var parent = node.Ancestors().First(x => x is MethodDeclarationSyntax); var source = _semanticModel.GetDeclaredSymbol(parent); CreateMethodInvokesStoredProcedureRelationship(source, storedProcedureName); } } } catch (Exception ex) { Console.WriteLine("Exception: " + ex); } base.VisitInvocationExpression(node); }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { IEnumerable <IdentifierNameSyntax> objectAndMethod = node.Expression.DescendantNodes() .OfType <IdentifierNameSyntax>() .TakeLast(2); if (objectAndMethod.Count() == 2) { // Assumption: for this analyser, assuming that variables are declared with a type (not var/base class/interface) IdentifierNameSyntax classIdentifier = objectAndMethod.First(); SyntaxNode declaration = IdentifierDeclarationFinder.Find(classIdentifier); string className = declaration != null ? declaration.ChildNodes().OfType <VariableDeclarationSyntax>().FirstOrDefault()?.Type.ToString() // no declaration was found, assume static method : classIdentifier.Identifier.Text; MethodCalls.Add(new MethodCallHolder(className, node)); } else { string className = node.Ancestors() .OfType <ClassDeclarationSyntax>() .FirstOrDefault()? .Identifier .Text; MethodCalls.Add(new MethodCallHolder(className, node)); } base.VisitInvocationExpression(node); }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { var invokedSymbol = semanticModel.GetSymbolInfo(node).Symbol as IMethodSymbol; if (invokedSymbol == null) { return; } if (!invokedSymbol.IsArrayClone() && !invokedSymbol.IsEnumerableToList() && !invokedSymbol.IsEnumerableToArray()) { return; } var returnOrAssignment = node .Ancestors() .FirstOrDefault(IsReturnOrAssignment); if (IsReturn(returnOrAssignment)) { locations.Add(node.Expression.GetLocation()); } }
protected virtual async Task <bool> IsRegistrableAsync(CodeFixContext context, InvocationExpressionSyntax invocation) { // for now we do not offer codefixes for mixed types var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); if (!(invocation.Expression is MemberAccessExpressionSyntax maes)) { return(true); } if (!(model.GetTypeInfo(maes.ChildNodes().FirstOrDefault()).Type is INamedTypeSymbol typeInvocationContext)) { return(false); } var mdec = invocation .Ancestors() .OfType <MethodDeclarationSyntax>() .FirstOrDefault(); if (mdec == null) { return(false); } var symbol = model.GetDeclaredSymbol(mdec); var typeContext = symbol?.ContainingType; return(typeContext != null && SymbolEqualityComparer.Default.Equals(typeContext, typeInvocationContext)); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, InvocationExpressionSyntax invocation) { if (CheckSpan(invocation, context.Span)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); IMethodSymbol methodSymbol = GetMethodSymbol(invocation, semanticModel, context.CancellationToken); if (methodSymbol != null) { MethodDeclarationSyntax method = await GetMethodAsync(methodSymbol, context.CancellationToken).ConfigureAwait(false); if (method != null && !invocation.Ancestors().Any(f => f == method)) { ExpressionSyntax expression = GetMethodExpression(method); if (expression != null) { List <ParameterInfo> parameterInfos = GetParameterInfos(invocation, methodSymbol, semanticModel, context.CancellationToken); if (parameterInfos != null) { context.RegisterRefactoring( "Inline method", c => InlineMethodAsync(context.Document, invocation, expression, parameterInfos.ToArray(), c)); context.RegisterRefactoring( "Inline and remove method", c => InlineAndRemoveMethodAsync(context.Document, invocation, method, expression, parameterInfos.ToArray(), c)); } } else if (methodSymbol.ReturnsVoid && invocation.IsParentKind(SyntaxKind.ExpressionStatement)) { StatementSyntax[] statements = method.Body?.Statements.ToArray(); if (statements?.Length > 0) { List <ParameterInfo> parameterInfos = GetParameterInfos(invocation, methodSymbol, semanticModel, context.CancellationToken); if (parameterInfos != null) { var expressionStatement = (ExpressionStatementSyntax)invocation.Parent; context.RegisterRefactoring( "Inline method", c => InlineMethodAsync(context.Document, expressionStatement, statements, parameterInfos.ToArray(), c)); context.RegisterRefactoring( "Inline and remove method", c => InlineAndRemoveMethodAsync(context.Document, expressionStatement, method, statements, parameterInfos.ToArray(), c)); } } } } } } }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { var symbol = (IMethodSymbol)SemanticModel.GetSymbolInfo(node).Symbol; if (symbol != null) { var synctype = DetectSynchronousUsages((IMethodSymbol)symbol.OriginalDefinition); Result.StoreDetectedSyncUsage(synctype); Result.WriteDetectedSyncUsage(synctype, Document.FilePath, (IMethodSymbol)symbol.OriginalDefinition); if (synctype != Utilities.Enums.SyncDetected.None && node.Ancestors().OfType<MethodDeclarationSyntax>().Any(method => method.HasAsyncModifier())) { Result.syncUsageResults.NumGUIBlockingSyncUsages++; Logs.TempLog.Info(@"GUIBLOCKING {0}", node.Ancestors().OfType<MethodDeclarationSyntax>().First().ToString()); } } }
protected override bool IsInValidContext(InvocationExpressionSyntax invocationSyntax, SemanticModel semanticModel) => // Do not report if call is inside Main. !invocationSyntax .Ancestors() .OfType <BaseMethodDeclarationSyntax>() .Select(m => semanticModel.GetDeclaredSymbol(m)) .Select(s => s.IsMainMethod()) .FirstOrDefault();
private static async Task <Document> AddCancellationTokenAsync(Document document, InvocationExpressionSyntax invocation, CancellationToken cancellationToken) { SyntaxNode?root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (root is null) { return(document); } if (invocation.Ancestors().OfType <MethodDeclarationSyntax>().FirstOrDefault() is { ParameterList : { Parameters : { } callerParameters } } &&
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) { // Get a hash of all the previous @doc and @ctx lambda parameters and don't replace the same HashSet <string> currentScopeLambdaParameters = new HashSet <string>( node.Ancestors().OfType <LambdaExpressionSyntax>().SelectMany( x => x.DescendantNodes().OfType <ParameterSyntax>()).Select(x => x.Identifier.Text)); // Only do the replacement if this is a module ctor or a module fluent method ArgumentListSyntax argumentList = node.ArgumentList; bool nodeChanged = false; if (IsInvocationAModuleCtorOrFluentMethod(node)) { // Replace @doc and @ctx argument expressions with the appropriate lambda expressions, and stop descending if we hit another module ctor foreach (ArgumentSyntax argument in node.ArgumentList.Arguments) { // Don't replace existing lambda expressions if (!(argument.Expression is LambdaExpressionSyntax)) { List <IdentifierNameSyntax> identifierNames = argument .DescendantNodes(x => !(x is InvocationExpressionSyntax) || !IsInvocationAModuleCtorOrFluentMethod((InvocationExpressionSyntax)x)) .OfType <IdentifierNameSyntax>() .Where(x => x != null && !currentScopeLambdaParameters.Contains(x.Identifier.Text)) .ToList(); IdentifierNameSyntax docReplacementName = identifierNames.FirstOrDefault(x => x.Identifier.Text.StartsWith("@doc")); IdentifierNameSyntax ctxReplacementName = identifierNames.FirstOrDefault(x => x.Identifier.Text.StartsWith("@ctx")); if (docReplacementName != null) { argumentList = argumentList.ReplaceNode(argument, SyntaxFactory.Argument( SyntaxFactory.ParenthesizedLambdaExpression( SyntaxFactory.ParameterList( default(SeparatedSyntaxList <ParameterSyntax>) .Add(SyntaxFactory.Parameter(SyntaxFactory.Identifier(docReplacementName.Identifier.Text))) .Add(SyntaxFactory.Parameter(SyntaxFactory.Identifier(ctxReplacementName == null ? "_" : ctxReplacementName.Identifier.Text)))), argument.Expression)) .WithTriviaFrom(argument)); nodeChanged = true; } else if (ctxReplacementName != null) { argumentList = argumentList.ReplaceNode(argument, SyntaxFactory.Argument( SyntaxFactory.SimpleLambdaExpression( SyntaxFactory.Parameter(SyntaxFactory.Identifier(ctxReplacementName.Identifier.Text)), argument.Expression)) .WithTriviaFrom(argument)); nodeChanged = true; } } } } // Build and return the result node (or just return the original node) return(base.VisitInvocationExpression(nodeChanged ? node.WithArgumentList(argumentList) : node)); }
public static object ResolveFunctionInvocation(string functionName, InvocationExpressionSyntax node, SemanticModel semanticModel) { var returnType = "void"; var varDeclaration = node.Ancestors().OfType <VariableDeclarationSyntax>().FirstOrDefault(); if (varDeclaration != null) { var predefinedType = varDeclaration.ChildNodes().OfType <PredefinedTypeSyntax>().FirstOrDefault(); returnType = predefinedType?.Keyword.Value.ToString() ?? "object"; } var arguments = GetArgumentTypes(node.ArgumentList.Arguments, semanticModel); return(new FunctionDescription(functionName, returnType, arguments)); }
private void Initialize(int depth, InvocationExpressionSyntax invocationExpressionSyntax, IMethodSymbol methodSymbol, SemanticModel semanticModel) { Depth = depth; IsMethod = true; InvocationString = invocationExpressionSyntax.ToString(); var containingNode = invocationExpressionSyntax.Ancestors().OfType <StatementSyntax>().FirstOrDefault(); OwnerStatementString = containingNode?.ToString(); MemberName = methodSymbol.Name; ReturnType = new TypeDescriptor(methodSymbol.ReturnType); var containingTypeSymbol = methodSymbol.ContainingType; ContainingType = new TypeDescriptor(containingTypeSymbol); ParameterTypes = invocationExpressionSyntax.ArgumentList.Arguments .Select(a => new TypeDescriptor(semanticModel.GetTypeInfo(a.Expression).Type)) .ToList(); GenericTypesForMethod = methodSymbol.IsGenericMethod ? methodSymbol.TypeArguments .Select(t => new TypeDescriptor(t)) .ToList() : null; GenericTypesForContainedType = containingTypeSymbol.IsGenericType ? containingTypeSymbol.TypeArguments .Select(t => new TypeDescriptor(t)) .ToList() : null; MethodDeclarationSyntax = SymbolHelper.GetSyntaxReferences(invocationExpressionSyntax, semanticModel) .FirstOrDefault() ?.GetSyntax() as MethodDeclarationSyntax; if (invocationExpressionSyntax.Expression is MemberAccessExpressionSyntax memberAccessExpressionSyntax) { var memberAccessSymbolInfo = semanticModel.GetSymbolInfo(memberAccessExpressionSyntax); // info on the variable being accessed var objectAccessedSyntax = memberAccessExpressionSyntax.Expression; var objectAccessedSymbol = semanticModel.GetSymbolInfo(objectAccessedSyntax).Symbol; var objectAccessedTypeSymbol = semanticModel.GetTypeInfo(objectAccessedSyntax).Type; MemberOwnerType = new TypeDescriptor(objectAccessedTypeSymbol); } else { // a method that is part of the current class (containingType) MemberOwnerType = ContainingType; } }
private void AnalyzeCodeBlock(SyntaxNodeAnalysisContext context) { InvocationExpressionSyntax call = context.Node as InvocationExpressionSyntax; if (call == null) { return; } // If we are not calling the DefineSwitchDefault methods on LocalAppContext then we can safely ignore this. if (!IsCallToDefineSwitchDefault(call, context.SemanticModel)) { return; } // Validate that the second argument is true. ArgumentSyntax args = call.ArgumentList.Arguments[1]; if (args.Expression.Kind() != SyntaxKind.TrueLiteralExpression) { context.ReportDiagnostic(Diagnostic.Create(s_appContextDefaultNotInitializedToTrueDiagnostic, args.GetLocation(), call)); } // check that we are doing this inside an if statement var containingIfStatement = call.Ancestors().FirstOrDefault(n => n.Kind() == SyntaxKind.IfStatement) as IfStatementSyntax; if (containingIfStatement == null) { context.ReportDiagnostic(Diagnostic.Create(s_appContextDefaultValueDefinedOutsideIfConditionDiagnostic, args.GetLocation(), call)); } else { // are we inside the switch? either as a block or as a switchcase? if (!(containingIfStatement.Parent.Kind() == SyntaxKind.SwitchSection || containingIfStatement.Parent.Parent.Kind() == SyntaxKind.SwitchSection)) { context.ReportDiagnostic(Diagnostic.Create(s_appContextDefaultValueDefinedOutsideIfConditionDiagnostic, args.GetLocation(), call)); } } // Validate that the if statement is using the appropriate expression if (containingIfStatement.Condition.Kind() != SyntaxKind.LessThanOrEqualExpression) { context.ReportDiagnostic(Diagnostic.Create(s_appContextDefaultUsedUnexpectedIfStatementDiagnostic, containingIfStatement.GetLocation())); } }
private bool isFunctionalCall(InvocationExpressionSyntax invocation, out StatementSyntax functional) { functional = null; var containingClass = invocation .Ancestors() .OfType <ClassDeclarationSyntax>() .FirstOrDefault(); if (containingClass == null) { return(false); } var parentContainer = containingClass.Parent as ClassDeclarationSyntax; if (parentContainer == null || parentContainer.Identifier.ToString() != "Functions") { return(false); } var concurrentClassName = invocation.Expression.ToString() + "__concurrent"; var concurrentClass = parentContainer .Members .OfType <ClassDeclarationSyntax>() .SingleOrDefault(@class => @class.Identifier.ToString() == concurrentClassName); var newInvocation = default(InvocationExpressionSyntax); if (concurrentClass != null) { newInvocation = Templates.ConcurrentFunctionStatement .Get <InvocationExpressionSyntax>( concurrentClass.Identifier, (invocation.Expression as IdentifierNameSyntax) .Identifier); } else { newInvocation = Templates.FunctionStatement .Get <InvocationExpressionSyntax>(invocation.Expression); } functional = CSharp.ExpressionStatement(newInvocation); return(true); }
private ITypeSymbol GetClassOrStructContainingExpression( InvocationExpressionSyntax expr, SemanticModel semanticModel ) { foreach (var ancestor in expr.Ancestors()) { if (ancestor is StructDeclarationSyntax) { return(semanticModel.GetDeclaredSymbol(ancestor as StructDeclarationSyntax)); } else if (ancestor is ClassDeclarationSyntax) { return(semanticModel.GetDeclaredSymbol(ancestor as ClassDeclarationSyntax)); } } return(null); }
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) { var expression = node.Expression.ToString(); if (expression.EndsWith("OrderBy") == false) { return(base.VisitInvocationExpression(node)); } var parent = node.Ancestors().FirstOrDefault(x => x.IsKind(SyntaxKind.InvocationExpression) || x.IsKind(SyntaxKind.QueryExpression)); if (parent != _root) { return(base.VisitInvocationExpression(node)); } ThrowOrderByException(node.ToString()); return(node); }
static bool ValidateInvocation(InvocationExpressionSyntax expr) { bool allAncestorsIsParenthes = true; foreach (var x in expr.Ancestors()) { // scope is in lambda, method if (x.IsKind(SyntaxKind.SimpleLambdaExpression) || x.IsKind(SyntaxKind.ParenthesizedLambdaExpression) || x.IsKind(SyntaxKind.ArrowExpressionClause)) { // () => M() if (allAncestorsIsParenthes) return true; break; } if (x.IsKind(SyntaxKind.MethodDeclaration)) break; if (x.IsKind(SyntaxKind.PropertyDeclaration)) break; if (x.IsKind(SyntaxKind.ConstructorDeclaration)) break; // x = M() if (x.IsKind(SyntaxKind.SimpleAssignmentExpression)) return true; // var x = M() if (x.IsKind(SyntaxKind.VariableDeclarator)) return true; // return M() if (x.IsKind(SyntaxKind.ReturnStatement)) return true; // from x in M() if (x.IsKind(SyntaxKind.FromClause)) return true; // (bool) ? M() : M() if (x.IsKind(SyntaxKind.ConditionalExpression)) return true; // M(M()) if (x.IsKind(SyntaxKind.InvocationExpression)) return true; // new C(M()) if (x.IsKind(SyntaxKind.ObjectCreationExpression)) return true; // (((((M())))) if (!x.IsKind(SyntaxKind.ParenthesizedExpression)) { allAncestorsIsParenthes = false; } } // Okay => M().M() if (expr.DescendantNodes().OfType<InvocationExpressionSyntax>().Any()) return true; return false; }
public (EarlyReleaseReason?Reason, IMethodSymbol EnclosingMethodSymbol, Location InvocationLocation, Location EnclosingMethodLocation) GetEarlyReleaseJustification([NotNull] Compilation comp, [NotNull] InvocationExpressionSyntax ies, CancellationToken token) { if (comp == null) { throw new ArgumentNullException(nameof(comp)); } if (ies == null) { throw new ArgumentNullException(nameof(ies)); } EarlyReleaseReason?ret = null; IMethodSymbol enclosingMethodSym = null; Location invocationLocation = ies.GetLocation(); Location enclosingMethodLocation = null; var semanticModel = comp.GetSemanticModel(ies.SyntaxTree, true); if (semanticModel != null) { INamedTypeSymbol earlyReleaseJustificationAttrib = FindEarlyReleaseJustificationAttribute(comp); var enclosingMethod = ies.Ancestors().OfType <MethodDeclarationSyntax>().FirstOrDefault(); if (enclosingMethod != null && earlyReleaseJustificationAttrib != null) { var symbolInfo = semanticModel.GetDeclaredSymbol(enclosingMethod, token); if (symbolInfo is IMethodSymbol enclosingMethodSymbol) { enclosingMethodSym = enclosingMethodSymbol; enclosingMethodLocation = enclosingMethodSym.Locations.FirstOrDefault(); var justRes = ExtractJustification(enclosingMethodSymbol, earlyReleaseJustificationAttrib, comp); LogWhetherHasJustificationAttribute(justRes.HasAttribute, enclosingMethodSymbol.Name ?? "UNKNOWN"); ret = justRes.PropertyValue; } } } Debug.Assert(!ret.HasValue || ret.Value.IsDefined()); Debug.Assert(!ret.HasValue || (enclosingMethodSym != null && invocationLocation != null && enclosingMethodLocation != null)); return(ret, enclosingMethodSym, invocationLocation, enclosingMethodLocation); }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { try { var target = _semanticModel.GetSymbolInfo(node.Expression); var parent = node.Ancestors().First(x => x is ClassDeclarationSyntax || x is MethodDeclarationSyntax); if (parent is ClassDeclarationSyntax) { //_semanticModel.GetDeclaredSymbol(parent); } else { var source = _semanticModel.GetDeclaredSymbol(parent); CreateMethodInvokesMethodRelationship(source, target.Symbol); } } catch (Exception ex) { Console.WriteLine("Exception: " + ex); } base.VisitInvocationExpression(node); }
static bool ValidateInvocation(InvocationExpressionSyntax expr) { bool allAncestorsIsParenthes = true; foreach (var x in expr.Ancestors()) { // scope is in lambda, method if (x.IsKind(SyntaxKind.SimpleLambdaExpression) || x.IsKind(SyntaxKind.ParenthesizedLambdaExpression) || x.IsKind(SyntaxKind.ArrowExpressionClause)) { // () => M() if (allAncestorsIsParenthes) { return(true); } break; } if (x.IsKind(SyntaxKind.MethodDeclaration)) { break; } if (x.IsKind(SyntaxKind.PropertyDeclaration)) { break; } if (x.IsKind(SyntaxKind.ConstructorDeclaration)) { break; } // x = M() if (x.IsKind(SyntaxKind.SimpleAssignmentExpression)) { return(true); } // var x = M() if (x.IsKind(SyntaxKind.VariableDeclarator)) { return(true); } // return M() if (x.IsKind(SyntaxKind.ReturnStatement)) { return(true); } // from x in M() if (x.IsKind(SyntaxKind.FromClause)) { return(true); } // (bool) ? M() : M() if (x.IsKind(SyntaxKind.ConditionalExpression)) { return(true); } // M(M()) if (x.IsKind(SyntaxKind.InvocationExpression)) { return(true); } // new C(M()) if (x.IsKind(SyntaxKind.ObjectCreationExpression)) { return(true); } // (((((M())))) if (!x.IsKind(SyntaxKind.ParenthesizedExpression)) { allAncestorsIsParenthes = false; } } // Okay => M().M() if (expr.DescendantNodes().OfType <InvocationExpressionSyntax>().Any()) { return(true); } return(false); }
private void APMDiagnosisDetection(IMethodSymbol symbol, InvocationExpressionSyntax node) { int c = GetIndexCallbackArgument(symbol); var callbackArg = node.ArgumentList.Arguments.ElementAt(c); if (callbackArg.Expression.CSharpKind().ToString().Contains("IdentifierName")) Logs.TempLog.Info("{0} {1}", callbackArg.Expression.CSharpKind(), SemanticModel.GetSymbolInfo(callbackArg.Expression).Symbol.Kind); else Logs.TempLog.Info("{0}", callbackArg.Expression.CSharpKind()); //PRINT ALL APM BEGIN METHODS Logs.APMDiagnosisLog.Info(@"Document: {0}", Document.FilePath); Logs.APMDiagnosisLog.Info(@"Symbol: {0}", symbol); Logs.APMDiagnosisLog.Info(@"Invocation: {0}", node); Logs.APMDiagnosisLog.Info(@"CallbackType: {0}", callbackArg.Expression.CSharpKind()); if (callbackArg.Expression.CSharpKind().ToString().Contains("IdentifierName")) Logs.APMDiagnosisLog.Info("{0}", SemanticModel.GetSymbolInfo(callbackArg.Expression).Symbol.Kind); Logs.APMDiagnosisLog.Info("---------------------------------------------------"); Result.apmDiagnosisResults.NumAPMBeginMethods++; if (node.Ancestors().Where(a => (a is BinaryExpressionSyntax) || (a is VariableDeclaratorSyntax) || (a is VariableDeclarationSyntax) || (a is ReturnStatementSyntax)).Any() ) { Logs.TempLog2.Info("UnderStatement {0}\r\n{1}\r\n--------------------", Document.FilePath, node.Ancestors().OfType<BlockSyntax>().First()); } //var statement = node.Ancestors().OfType<StatementSyntax>().First(); //var ancestors = node.Ancestors().OfType<MethodDeclarationSyntax>(); //if (ancestors.Any()) //{ // var method = ancestors.First(); // bool isFound = false; // bool isAPMFollowed = false; // foreach (var tmp in method.Body.ChildNodes()) // { // if (isFound) // isAPMFollowed = true; // if (statement == tmp) // isFound = true; // } // if (isAPMFollowed) // { // Result.apmDiagnosisResults.NumAPMBeginFollowed++; // Logs.TempLog2.Info("APMFOLLOWED:\r\n{0}\r\n---------------------------------------------------", method); // } //} //SyntaxNode callbackBody = null; //if (callbackArg.Expression.Kind.ToString().Contains("IdentifierName")) //{ // var methodSymbol = SemanticModel.GetSymbolInfo(callbackArg.Expression).Symbol; // if (methodSymbol.Kind.ToString().Equals("Method")) // callbackBody = (MethodDeclarationSyntax)methodSymbol.DeclaringSyntaxReferences.First().GetSyntax(); //} //else if (callbackArg.Expression.Kind.ToString().Contains("LambdaExpression")) // callbackBody = node; //if (callbackBody != null) //{ // if (callbackBody.DescendantNodes().OfType<MemberAccessExpressionSyntax>().Any(a => a.Name.ToString().StartsWith("End"))) // Logs.TempLog3.Info("APMEND in Callback:\r\n{0}\r\nCaller: {1}\r\nDeclaringSyntaxNodes:\r\n{2}\r\n--------------------------------------------------", Document.FilePath, node, callbackBody); // else // Logs.TempLog3.Info("NO APMEND in Callback:\r\n{0}\r\nCaller: {1}\r\nDeclaringSyntaxNodes:\r\n{2}\r\n--------------------------------------------------", Document.FilePath, node, callbackBody); //} }
private static bool IsInsideANullCheck(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) => invocation.Ancestors().OfType<IfStatementSyntax>().Any(@if => IsConditionThatChecksForNotEqualsNull(@if.Condition, semanticModel, symbol));
private void AnalyzeInvocationExpression(DocumentData documentData, InvocationExpressionSyntax node, InvokeFunctionReferenceData functionReferenceData) { var functionData = functionReferenceData.FunctionData; var methodSymbol = functionReferenceData.ReferenceSymbol; var functionNode = functionData.GetNode(); var functionBodyNode = functionData.GetBodyNode(); var queryExpression = node.Ancestors() .TakeWhile(o => o != functionNode) .OfType <QueryExpressionSyntax>() .FirstOrDefault(); if (queryExpression != null) // Await is not supported in a linq query { functionReferenceData.Ignore = true; Logger.Warn($"Cannot await async method in a query expression:\r\n{queryExpression}\r\n"); return; } var searchOptions = AsyncCounterpartsSearchOptions.Default; if (_configuration.UseCancellationTokenOverload) { searchOptions |= AsyncCounterpartsSearchOptions.HasCancellationToken; } functionReferenceData.ReferenceAsyncSymbols = new HashSet <IMethodSymbol>(GetAsyncCounterparts(methodSymbol.OriginalDefinition, searchOptions)); if (functionReferenceData.ReferenceAsyncSymbols.Any()) { if (functionReferenceData.ReferenceAsyncSymbols.All(o => o.ReturnsVoid || !o.ReturnType.IsTaskType())) { functionReferenceData.AwaitInvocation = false; Logger.Info($"Cannot await method that is either void or do not return a Task:\r\n{methodSymbol}\r\n"); } var nameGroups = functionReferenceData.ReferenceAsyncSymbols.GroupBy(o => o.Name).ToList(); if (nameGroups.Count == 1) { functionReferenceData.AsyncCounterpartName = nameGroups[0].Key; } } else if (!ProjectData.Contains(functionReferenceData.ReferenceSymbol)) { // If we are dealing with an external method and there are no async counterparts for it, we cannot convert it to async functionReferenceData.Ignore = true; Logger.Info($"Method {methodSymbol} can not be async as there is no async counterparts for it"); return; } else if (functionReferenceData.ReferenceFunctionData != null) { functionReferenceData.AsyncCounterpartName = functionReferenceData.ReferenceSymbol.Name + "Async"; } // If the invocation returns a Task then we need to analyze it further to see how the Task is handled if (methodSymbol.ReturnType.IsTaskType()) { var retrunType = (INamedTypeSymbol)methodSymbol.ReturnType; var canBeAwaited = false; var currNode = node.Parent; while (true) { var memberExpression = currNode as MemberAccessExpressionSyntax; if (memberExpression == null) { break; } var memberName = memberExpression.Name.ToString(); if (retrunType.IsGenericType && memberName == "Result") { canBeAwaited = true; break; } if (memberName == "ConfigureAwait") { var invocationNode = currNode.Parent as InvocationExpressionSyntax; if (invocationNode != null) { functionReferenceData.ConfigureAwaitParameter = invocationNode.ArgumentList.Arguments.First().Expression; currNode = invocationNode.Parent; continue; } break; } if (memberName == "GetAwaiter") { var invocationNode = currNode.Parent as InvocationExpressionSyntax; if (invocationNode != null) { currNode = invocationNode.Parent; continue; } break; } if (_taskResultMethods.Contains(memberName)) { var invocationNode = currNode.Parent as InvocationExpressionSyntax; if (invocationNode != null) { canBeAwaited = true; } } break; } if (!canBeAwaited) { functionReferenceData.AwaitInvocation = false; Logger.Info( $"Cannot await invocation of a method that returns a Task without be synchronously awaited:\r\n{methodSymbol}\r\n"); } else { functionReferenceData.SynchronouslyAwaited = true; } } if (node.Parent.IsKind(SyntaxKind.ReturnStatement)) { functionReferenceData.UseAsReturnValue = true; } // Calculate if node is the last statement if (node.Parent.Equals(functionBodyNode) || //eg. bool ExpressionReturn() => SimpleFile.Write(); node.Equals(functionBodyNode) // eg. Func<bool> fn = () => SimpleFile.Write(); ) { functionReferenceData.LastInvocation = true; functionReferenceData.UseAsReturnValue = !methodSymbol.ReturnsVoid; } var bodyBlock = functionBodyNode as BlockSyntax; if (bodyBlock?.Statements.Last() == node.Parent) { functionReferenceData.LastInvocation = true; } // Set CancellationTokenRequired if we detect that one of the async counterparts has a cancellation token as a parameter if (_configuration.UseCancellationTokenOverload && functionReferenceData.ReferenceAsyncSymbols.Any(o => o.Parameters.Length > methodSymbol.Parameters.Length)) { functionReferenceData.CancellationTokenRequired = true; } foreach (var analyzer in _configuration.InvocationExpressionAnalyzers) { analyzer.Analyze(node, functionReferenceData, documentData.SemanticModel); } // Propagate CancellationTokenRequired to the method data only if the invocation can be async if (functionReferenceData.CancellationTokenRequired && functionReferenceData.GetConversion() == ReferenceConversion.ToAsync) { // We need to set CancellationTokenRequired to true for the method that contains this invocation var methodData = functionReferenceData.FunctionData.GetMethodData(); methodData.CancellationTokenRequired = true; } }
private T TransformFunctionReference <T>(T node, IFunctionAnalyzationResult funcResult, FunctionReferenceTransformationResult transfromReference, ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata) where T : SyntaxNode { var nameNode = node.GetAnnotatedNodes(transfromReference.Annotation).OfType <SimpleNameSyntax>().First(); var funReferenceResult = transfromReference.AnalyzationResult; var bodyFuncReferenceResult = funReferenceResult as IBodyFunctionReferenceAnalyzationResult; var newNameNode = nameNode .WithIdentifier(Identifier(funReferenceResult.AsyncCounterpartName)) .WithTriviaFrom(nameNode); transfromReference.Transformed = newNameNode; var cancellationTokenParamName = funcResult.GetMethodOrAccessor().CancellationTokenRequired ? "cancellationToken" : null; // TODO: remove // If we have a cref change the name to the async counterpart and add/update arguments if (bodyFuncReferenceResult == null) { if (funReferenceResult.IsCref) { var crefNode = (NameMemberCrefSyntax)nameNode.Parent; var paramList = new List <CrefParameterSyntax>(); // If the cref has already the parameters set then use them if (crefNode.Parameters != null) { paramList.AddRange(crefNode.Parameters.Parameters); // If the external async counterpart has a cancellation token, add it if (funReferenceResult.AsyncCounterpartFunction == null && funReferenceResult.ReferenceSymbol.Parameters.Length < funReferenceResult.AsyncCounterpartSymbol.Parameters.Length) { paramList.Add(CrefParameter(IdentifierName(nameof(CancellationToken)))); } } else { // We have to add the parameters to avoid ambiguity var asyncSymbol = funReferenceResult.AsyncCounterpartSymbol; paramList.AddRange(asyncSymbol.Parameters .Select(o => CrefParameter(o.Type .CreateTypeSyntax(true, namespaceMetadata.AnalyzationResult.IsIncluded(o.Type.ContainingNamespace?.ToString()))))); } // If the async counterpart is internal and a token is required add a token parameter if (funReferenceResult.AsyncCounterpartFunction?.GetMethodOrAccessor()?.CancellationTokenRequired == true) { paramList.Add(CrefParameter(IdentifierName(nameof(CancellationToken)))); } node = node.ReplaceNestedNodes( crefNode.Parent as QualifiedCrefSyntax, crefNode, crefNode .ReplaceNode(nameNode, newNameNode) .WithParameters(CrefParameterList(SeparatedList(paramList))), rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithContainer(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(rootNode.Container))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ); } else if (funReferenceResult.IsNameOf) { node = node.ReplaceNestedNodes( nameNode.Parent as MemberAccessExpressionSyntax, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName).WithTriviaFrom(rootNode.Expression))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ); } return(node); } // If we have a method passed as an argument we need to check if we have to wrap it inside a function if (bodyFuncReferenceResult.AsyncDelegateArgument != null) { if (bodyFuncReferenceResult.WrapInsideFunction) { // TODO: move to analyze step var argumentNode = nameNode.Ancestors().OfType <ArgumentSyntax>().First(); var delReturnType = (INamedTypeSymbol)bodyFuncReferenceResult.AsyncDelegateArgument.ReturnType; var returnType = bodyFuncReferenceResult.AsyncCounterpartSymbol.ReturnType; bool returnTypeMismatch; if (bodyFuncReferenceResult.ReferenceFunction != null) { var refMethod = bodyFuncReferenceResult.ReferenceFunction as IMethodAnalyzationResult; if (refMethod != null && refMethod.PreserveReturnType) { returnTypeMismatch = !delReturnType.Equals(returnType); // TODO Generics } else if (delReturnType.IsGenericType) // Generic Task { returnTypeMismatch = delReturnType.TypeArguments.First().IsAwaitRequired(returnType); } else { returnTypeMismatch = delReturnType.IsAwaitRequired(returnType); } } else { returnTypeMismatch = !delReturnType.Equals(returnType); // TODO Generics } var newArgumentExpression = argumentNode.Expression .ReplaceNestedNodes( nameNode.Parent as MemberAccessExpressionSyntax, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ) .WrapInsideFunction(bodyFuncReferenceResult.AsyncDelegateArgument, returnTypeMismatch, namespaceMetadata.TaskConflict, invocation => invocation.AddCancellationTokenArgumentIf(cancellationTokenParamName, bodyFuncReferenceResult)); node = node .ReplaceNode(argumentNode.Expression, newArgumentExpression); } else { node = node.ReplaceNestedNodes( nameNode.Parent as MemberAccessExpressionSyntax, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ); } return(node); } InvocationExpressionSyntax invokeNode = null; var isAccessor = bodyFuncReferenceResult.ReferenceSymbol.IsAccessor(); if (!isAccessor && funReferenceResult.ReferenceNode.IsKind(SyntaxKind.InvocationExpression)) { invokeNode = nameNode.Ancestors().OfType <InvocationExpressionSyntax>().First(); } if (!bodyFuncReferenceResult.AwaitInvocation) { // An arrow method does not have a statement var statement = nameNode.Ancestors().OfType <StatementSyntax>().FirstOrDefault(); var newNode = (SyntaxNode)statement ?? node; if (invokeNode != null) { newNode = newNode.ReplaceNestedNodes( invokeNode, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode .AddCancellationTokenArgumentIf(cancellationTokenParamName, bodyFuncReferenceResult), funcResult, funReferenceResult, namespaceMetadata, (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression))) ); } else if (isAccessor) { newNode = ConvertAccessor(newNode, nameNode, newNameNode, cancellationTokenParamName, bodyFuncReferenceResult, invNode => UpdateTypeAndRunReferenceTransformers(invNode, funcResult, funReferenceResult, namespaceMetadata, (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression)))); } else { newNode = newNode.ReplaceNestedNodes( nameNode.Parent as MemberAccessExpressionSyntax, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName).WithTriviaFrom(rootNode.Expression))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ); } if (statement != null && !statement.IsKind(SyntaxKind.LocalFunctionStatement)) { if (bodyFuncReferenceResult.UseAsReturnValue) { newNode = ((StatementSyntax)newNode).ToReturnStatement(); } node = node .ReplaceNode(statement, newNode); } else { node = (T)newNode; } } else { // We need to annotate the invocation node because of the AddAwait method as it needs the parent node var invokeAnnotation = Guid.NewGuid().ToString(); if (isAccessor) { node = ConvertAccessor(node, nameNode, newNameNode, cancellationTokenParamName, bodyFuncReferenceResult, invNode => UpdateTypeAndRunReferenceTransformers(invNode, funcResult, funReferenceResult, namespaceMetadata, (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression))) .WithAdditionalAnnotations(new SyntaxAnnotation(invokeAnnotation)) ); } else { node = node.ReplaceNestedNodes( invokeNode, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode .AddCancellationTokenArgumentIf(cancellationTokenParamName, bodyFuncReferenceResult), funcResult, funReferenceResult, namespaceMetadata, (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression))) .WithAdditionalAnnotations(new SyntaxAnnotation(invokeAnnotation)) ); } invokeNode = node.GetAnnotatedNodes(invokeAnnotation).OfType <InvocationExpressionSyntax>().First(); var conditionalAccessNode = invokeNode.Ancestors() .TakeWhile(o => !(o is StatementSyntax)) .OfType <ConditionalAccessExpressionSyntax>() .FirstOrDefault(); if (conditionalAccessNode != null) // ?. syntax { var statement = (StatementSyntax)invokeNode.Ancestors().FirstOrDefault(o => o is StatementSyntax); var block = statement?.Parent as BlockSyntax; if (statement == null || block == null) { // TODO: convert arrow method/property/function to a normal one // TODO: convert to block if there is no block node = node.ReplaceNode(conditionalAccessNode, conditionalAccessNode.AddAwait(_configuration.ConfigureAwaitArgument)); } else { var fnName = nameNode.Identifier.ValueText; // TODO: handle name collisions var variableName = $"{char.ToLowerInvariant(fnName[0])}{fnName.Substring(1)}Task"; var leadingTrivia = statement.GetLeadingTrivia(); var newConditionalAccessNode = ConditionalAccessExpression( conditionalAccessNode.Expression, invokeNode) .WithTriviaFrom(conditionalAccessNode); var localVar = LocalDeclarationStatement( VariableDeclaration( IdentifierName(Identifier(leadingTrivia, "var", TriviaList(Space))), SingletonSeparatedList( VariableDeclarator( Identifier(TriviaList(), variableName, TriviaList(Space))) .WithInitializer( EqualsValueClause(newConditionalAccessNode.WithoutTrivia()) .WithEqualsToken(Token(TriviaList(), SyntaxKind.EqualsToken, TriviaList(Space))) ) ))) .WithSemicolonToken(Token(TriviaList(), SyntaxKind.SemicolonToken, TriviaList(typeMetadata.EndOfLineTrivia))); var index = block.Statements.IndexOf(statement); var lastReturnNode = block.DescendantNodes() .Where(o => o.SpanStart >= statement.SpanStart) .OfType <ReturnStatementSyntax>() .LastOrDefault(); var variableAnnotation = Guid.NewGuid().ToString(); var newBlock = block.ReplaceNode(conditionalAccessNode, conditionalAccessNode.WhenNotNull.ReplaceNode(invokeNode, IdentifierName(variableName) .WithAdditionalAnnotations(new SyntaxAnnotation(variableAnnotation)) .WithLeadingTrivia(conditionalAccessNode.GetLeadingTrivia()) .WithTrailingTrivia(conditionalAccessNode.GetTrailingTrivia()) )); var variable = newBlock.GetAnnotatedNodes(variableAnnotation).OfType <IdentifierNameSyntax>().First(); newBlock = newBlock.ReplaceNode(variable, variable.AddAwait(_configuration.ConfigureAwaitArgument)); var ifBlock = Block() .WithOpenBraceToken( Token(TriviaList(leadingTrivia), SyntaxKind.OpenBraceToken, TriviaList(typeMetadata.EndOfLineTrivia))) .WithCloseBraceToken( Token(TriviaList(leadingTrivia), SyntaxKind.CloseBraceToken, TriviaList(typeMetadata.EndOfLineTrivia))) .WithStatements(new SyntaxList <StatementSyntax>() .AddRange(newBlock.AppendIndent(typeMetadata.IndentTrivia.ToFullString()).Statements.Skip(index))); var ifStatement = IfStatement( BinaryExpression( SyntaxKind.NotEqualsExpression, IdentifierName(Identifier(TriviaList(), variableName, TriviaList(Space))), LiteralExpression(SyntaxKind.NullLiteralExpression)) .WithOperatorToken( Token(TriviaList(), SyntaxKind.ExclamationEqualsToken, TriviaList(Space))), ifBlock ) .WithIfKeyword( Token(TriviaList(leadingTrivia), SyntaxKind.IfKeyword, TriviaList(Space))) .WithCloseParenToken( Token(TriviaList(), SyntaxKind.CloseParenToken, TriviaList(typeMetadata.EndOfLineTrivia))); var statements = new SyntaxList <StatementSyntax>() .AddRange(newBlock.Statements.Take(index)) .Add(localVar) .Add(ifStatement); if (lastReturnNode?.Expression != null) { // Check if the variable is defined otherwise return default return type value if (lastReturnNode.Expression is IdentifierNameSyntax idNode && statements.OfType <VariableDeclaratorSyntax>().All(o => o.Identifier.ToString() != idNode.Identifier.ValueText)) { lastReturnNode = lastReturnNode.WithExpression(DefaultExpression(funcResult.GetNode().GetReturnType().WithoutTrivia())); } statements = statements.Add(lastReturnNode); } node = node.ReplaceNode(block, newBlock.WithStatements(statements)); } } else { node = node.ReplaceNode(invokeNode, invokeNode.AddAwait(_configuration.ConfigureAwaitArgument)); } } return(node); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, InvocationExpressionSyntax invocation) { if (CheckSpan(invocation, context.Span)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); IMethodSymbol methodSymbol = GetMethodSymbol(invocation, semanticModel, context.CancellationToken); if (methodSymbol != null) { MethodDeclarationSyntax methodDeclaration = await GetMethodDeclarationAsync(methodSymbol, context.CancellationToken).ConfigureAwait(false); if (methodDeclaration != null && !invocation.Ancestors().Any(f => f == methodDeclaration)) { ExpressionSyntax expression = GetMethodExpression(methodDeclaration); if (expression != null) { List <ParameterInfo> parameterInfos = GetParameterInfos(invocation, methodSymbol, semanticModel, context.CancellationToken); if (parameterInfos != null) { INamedTypeSymbol enclosingType = semanticModel.GetEnclosingNamedType(invocation.SpanStart, context.CancellationToken); SemanticModel declarationSemanticModel = (invocation.SyntaxTree == methodDeclaration.SyntaxTree) ? semanticModel : await context.Solution.GetDocument(methodDeclaration.SyntaxTree).GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); var refactoring = new InlineMethodExpressionRefactoring(context.Document, invocation, enclosingType, methodSymbol, methodDeclaration, parameterInfos.ToArray(), semanticModel, declarationSemanticModel, context.CancellationToken); context.RegisterRefactoring("Inline method", c => refactoring.InlineMethodAsync(invocation, expression)); context.RegisterRefactoring("Inline and remove method", c => refactoring.InlineAndRemoveMethodAsync(invocation, expression)); } } else if (methodSymbol.ReturnsVoid && invocation.IsParentKind(SyntaxKind.ExpressionStatement)) { BlockSyntax body = methodDeclaration.Body; if (body != null) { SyntaxList <StatementSyntax> statements = body.Statements; if (statements.Any()) { List <ParameterInfo> parameterInfos = GetParameterInfos(invocation, methodSymbol, semanticModel, context.CancellationToken); if (parameterInfos != null) { var expressionStatement = (ExpressionStatementSyntax)invocation.Parent; INamedTypeSymbol enclosingType = semanticModel.GetEnclosingNamedType(invocation.SpanStart, context.CancellationToken); SemanticModel declarationSemanticModel = (invocation.SyntaxTree == methodDeclaration.SyntaxTree) ? semanticModel : await context.Solution.GetDocument(methodDeclaration.SyntaxTree).GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); var refactoring = new InlineMethodStatementsRefactoring(context.Document, invocation, enclosingType, methodSymbol, methodDeclaration, parameterInfos.ToArray(), semanticModel, declarationSemanticModel, context.CancellationToken); context.RegisterRefactoring("Inline method", c => refactoring.InlineMethodAsync(expressionStatement, statements)); context.RegisterRefactoring("Inline and remove method", c => refactoring.InlineAndRemoveMethodAsync(expressionStatement, statements)); } } } } } } } }
public bool isQueueInvocation(InvocationExpressionSyntax invocation, bool asynch, ExpressionSyntax success, out StatementSyntax result) { result = null; var signal = invocation.Expression as MemberAccessExpressionSyntax; if (signal == null) { return(false); } if (!(signal.Expression is IdentifierNameSyntax)) { return(false); } var signalName = signal.Expression.ToString(); if (asynch && !hasSignal(signalName)) { return(false); } if (!asynch) { if (!invocation .Ancestors() .Where(node => node is ClassDeclarationSyntax) .First() .DescendantNodes() .OfType <MethodDeclarationSyntax>() .Where(method => method .Identifier.ToString() .Equals(signalName)) .Any()) { return(false); } } var queueName = "__queue" + signalName; switch (signal.Name.ToString()) { case "enqueue": Debug.Assert(asynch); if (!hasMember(queueName)) { AddMember(Templates .SignalQueueMember .Get <MemberDeclarationSyntax>(queueName)); } result = Templates .Enqueue .Get <StatementSyntax>(queueName, success); break; case "dequeue": result = asynch ? Templates .DequeueAsynch .Get <StatementSyntax>(queueName, queueName + "_Top") : Templates .DequeueSynch .Get <StatementSyntax>(queueName, queueName + "_Top"); break; default: return(false); } return(true); }
private static bool IsInsideANullCheck(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) => invocation.Ancestors().OfType <IfStatementSyntax>().Any(@if => IsConditionThatChecksForNotEqualsNull(@if.Condition, semanticModel, symbol));
private T TransformFunctionReference <T>(T node, IFunctionAnalyzationResult funcResult, FunctionReferenceTransformationResult transfromReference, ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata) where T : SyntaxNode { var nameNode = node.GetAnnotatedNodes(transfromReference.Annotation).OfType <SimpleNameSyntax>().First(); var funReferenceResult = transfromReference.AnalyzationResult; var bodyFuncReferenceResult = funReferenceResult as IBodyFunctionReferenceAnalyzationResult; var newNameNode = nameNode .WithIdentifier(Identifier(funReferenceResult.AsyncCounterpartName)) .WithTriviaFrom(nameNode); transfromReference.Transformed = newNameNode; var cancellationTokenParamName = funcResult.GetMethodOrAccessor().CancellationTokenRequired ? "cancellationToken" : null; // TODO: remove // If we have a cref change the name to the async counterpart and add/update arguments if (bodyFuncReferenceResult == null) { if (funReferenceResult.IsCref) { var crefNode = (NameMemberCrefSyntax)nameNode.Parent; var paramList = new List <CrefParameterSyntax>(); // If the cref has already the parameters set then use them if (crefNode.Parameters != null) { paramList.AddRange(crefNode.Parameters.Parameters); // If the external async counterpart has a cancellation token, add it if (funReferenceResult.AsyncCounterpartFunction == null && funReferenceResult.ReferenceSymbol.Parameters.Length < funReferenceResult.AsyncCounterpartSymbol.Parameters.Length) { paramList.Add(CrefParameter(IdentifierName(nameof(CancellationToken)))); } } else { // We have to add the parameters to avoid ambiguity var asyncSymbol = funReferenceResult.AsyncCounterpartSymbol; paramList.AddRange(asyncSymbol.Parameters .Select(o => CrefParameter(o.Type .CreateTypeSyntax(true, namespaceMetadata.AnalyzationResult.IsIncluded(o.Type.ContainingNamespace?.ToString()))))); } // If the async counterpart is internal and a token is required add a token parameter if (funReferenceResult.AsyncCounterpartFunction?.GetMethodOrAccessor()?.CancellationTokenRequired == true) { paramList.Add(CrefParameter(IdentifierName(nameof(CancellationToken)))); } node = node.ReplaceNestedNodes( crefNode.Parent as QualifiedCrefSyntax, crefNode, crefNode .ReplaceNode(nameNode, newNameNode) .WithParameters(CrefParameterList(SeparatedList(paramList))), rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithContainer(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(rootNode.Container))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ); } else if (funReferenceResult.IsNameOf) { node = node.ReplaceNestedNodes( nameNode.Parent as MemberAccessExpressionSyntax, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName).WithTriviaFrom(rootNode.Expression))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ); } return(node); } // If we have a method passed as an argument we need to check if we have to wrap it inside a function if (bodyFuncReferenceResult.AsyncDelegateArgument != null) { if (bodyFuncReferenceResult.WrapInsideFunction) { // TODO: move to analyze step var argumentNode = nameNode.Ancestors().OfType <ArgumentSyntax>().First(); var delReturnType = (INamedTypeSymbol)bodyFuncReferenceResult.AsyncDelegateArgument.ReturnType; var returnType = bodyFuncReferenceResult.AsyncCounterpartSymbol.ReturnType; bool returnTypeMismatch; if (bodyFuncReferenceResult.ReferenceFunction != null) { var refMethod = bodyFuncReferenceResult.ReferenceFunction as IMethodAnalyzationResult; if (refMethod != null && refMethod.PreserveReturnType) { returnTypeMismatch = !delReturnType.Equals(returnType); // TODO Generics } else if (delReturnType.IsGenericType) // Generic Task { returnTypeMismatch = delReturnType.TypeArguments.First().IsAwaitRequired(returnType); } else { returnTypeMismatch = delReturnType.IsAwaitRequired(returnType); } } else { returnTypeMismatch = !delReturnType.Equals(returnType); // TODO Generics } var newArgumentExpression = argumentNode.Expression .ReplaceNestedNodes( nameNode.Parent as MemberAccessExpressionSyntax, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ) .WrapInsideFunction(bodyFuncReferenceResult.AsyncDelegateArgument, returnTypeMismatch, namespaceMetadata.TaskConflict, invocation => invocation.AddCancellationTokenArgumentIf(cancellationTokenParamName, bodyFuncReferenceResult)); node = node .ReplaceNode(argumentNode.Expression, newArgumentExpression); } else { node = node.ReplaceNestedNodes( nameNode.Parent as MemberAccessExpressionSyntax, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ); } return(node); } InvocationExpressionSyntax invokeNode = null; var isAccessor = bodyFuncReferenceResult.ReferenceSymbol.IsAccessor(); if (!isAccessor && funReferenceResult.ReferenceNode.IsKind(SyntaxKind.InvocationExpression)) { invokeNode = nameNode.Ancestors().OfType <InvocationExpressionSyntax>().First(); } if (!bodyFuncReferenceResult.AwaitInvocation) { // An arrow method does not have a statement var statement = nameNode.Ancestors().OfType <StatementSyntax>().FirstOrDefault(); var statementInParentFunction = nameNode.Ancestors().TakeWhile(o => !o.Equals(statement)).Any(o => o.IsFunction()); var newNode = (SyntaxNode)statement ?? node; if (invokeNode != null) { newNode = newNode.ReplaceNestedNodes( invokeNode, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode .AddCancellationTokenArgumentIf(cancellationTokenParamName, bodyFuncReferenceResult), funcResult, funReferenceResult, namespaceMetadata, (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression))) ); } else if (isAccessor) { newNode = ConvertAccessor(newNode, nameNode, newNameNode, cancellationTokenParamName, bodyFuncReferenceResult, invNode => UpdateTypeAndRunReferenceTransformers(invNode, funcResult, funReferenceResult, namespaceMetadata, (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression)))); } else { newNode = newNode.ReplaceNestedNodes( nameNode.Parent as MemberAccessExpressionSyntax, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode, funcResult, funReferenceResult, namespaceMetadata, (type, fullName) => rootNode.WithExpression(type.CreateTypeSyntax(false, fullName).WithTriviaFrom(rootNode.Expression))), childNode => RunReferenceTransformers(childNode, funcResult, funReferenceResult, namespaceMetadata) ); } if (statement != null && !statement.IsKind(SyntaxKind.LocalFunctionStatement)) { // Skip adding return statement for arrow functions if (bodyFuncReferenceResult.UseAsReturnValue && !statementInParentFunction) { newNode = ((StatementSyntax)newNode).ToReturnStatement(); } node = node .ReplaceNode(statement, newNode); } else { node = (T)newNode; } } else { // We need to annotate the invocation node because of the AddAwait method as it needs the parent node var invokeAnnotation = Guid.NewGuid().ToString(); if (isAccessor) { node = ConvertAccessor(node, nameNode, newNameNode, cancellationTokenParamName, bodyFuncReferenceResult, invNode => UpdateTypeAndRunReferenceTransformers(invNode, funcResult, funReferenceResult, namespaceMetadata, (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression))) .WithAdditionalAnnotations(new SyntaxAnnotation(invokeAnnotation)) ); } else { node = node.ReplaceNestedNodes( invokeNode, nameNode, newNameNode, rootNode => UpdateTypeAndRunReferenceTransformers(rootNode .AddCancellationTokenArgumentIf(cancellationTokenParamName, bodyFuncReferenceResult), funcResult, funReferenceResult, namespaceMetadata, (memberNode, type, fullName) => memberNode.WithExpression(type.CreateTypeSyntax(true, fullName).WithTriviaFrom(memberNode.Expression))) .WithAdditionalAnnotations(new SyntaxAnnotation(invokeAnnotation)) ); } invokeNode = node.GetAnnotatedNodes(invokeAnnotation).OfType <InvocationExpressionSyntax>().First(); // Check if the invocation has a ?. var conditionalAccessNode = invokeNode.Ancestors() .TakeWhile(o => !(o is StatementSyntax)) .OfType <ConditionalAccessExpressionSyntax>() .FirstOrDefault(o => o.WhenNotNull.Contains(invokeNode)); if (conditionalAccessNode != null) // ?. syntax { // We have to find out which strategy to use, if we have a non assignable expression, we are force to use if statements // otherwise a ternary condition will be used if (!conditionalAccessNode.Parent.IsKind(SyntaxKind.ExpressionStatement) || !invokeNode.Equals(conditionalAccessNode.WhenNotNull)) { node = TransformConditionalAccessToConditionalExpressions(node, nameNode, funReferenceResult, typeMetadata, conditionalAccessNode, invokeNode); } else { node = TransformConditionalAccessToIfStatements(node, nameNode, typeMetadata, conditionalAccessNode, invokeNode); } } else { node = node.ReplaceNode(invokeNode, invokeNode.AddAwait(_configuration.ConfigureAwaitArgument)); } } return(node); }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { var symbol = (IMethodSymbol)SemanticModel.GetSymbolInfo(node).Symbol; if (symbol != null) { if (symbol.IsAPMBeginMethod()) APMDiagnosisDetection(symbol, node); if (symbol.IsAPMEndMethod()) { Result.apmDiagnosisResults.NumAPMEndMethods++; var tmp = node.ArgumentList.Arguments.First().DescendantNodes().OfType<IdentifierNameSyntax>(); if(tmp.Any()) { var id = tmp.First(); if(node.Ancestors().OfType<BlockSyntax>().First().DescendantNodes().OfType<IdentifierNameSyntax>().Where(a=> (a.Identifier.ToString()== id.Identifier.ToString())).Count()>2) Logs.TempLog3.Info("IAsyncResultSomewhereElse {0}\r\n{1}\r\n--------------------", Document.FilePath, node.Ancestors().OfType<BlockSyntax>().First()); } //var ancestors2 = node.Ancestors().OfType<TryStatementSyntax>(); //if (ancestors2.Any()) //{ // Logs.TempLog4.Info("TRYCATCHED ENDXXX:\r\n{0}\r\n---------------------------------------------------", ancestors2.First()); // Result.apmDiagnosisResults.NumAPMEndTryCatchedMethods++; //} //SyntaxNode block = null; //var lambdas = node.Ancestors().OfType<SimpleLambdaExpressionSyntax>(); //if (lambdas.Any()) //{ // block = lambdas.First(); //} //if (block == null) //{ // var lambdas2 = node.Ancestors().OfType<ParenthesizedLambdaExpressionSyntax>(); // if (lambdas2.Any()) // block = lambdas2.First(); //} //if (block == null) //{ // var ancestors3 = node.Ancestors().OfType<MethodDeclarationSyntax>(); // if (ancestors3.Any()) // block = ancestors3.First(); //} //if (block != null) //{ // if (block.DescendantNodes().OfType<MemberAccessExpressionSyntax>().Any(a => a.Name.ToString().StartsWith("Begin") && !a.Name.ToString().Equals("BeginInvoke"))) // { // Logs.TempLog5.Info("NESTED ENDXXX:\r\n{0}\r\n---------------------------------------------------", block); // Result.apmDiagnosisResults.NumAPMEndNestedMethods++; // } //} } } base.VisitInvocationExpression(node); }
private void AnalyzeInvocation(SyntaxNodeAnalysisContext context, InvocationExpressionSyntax node, IMethodSymbol method) { var invocationNodes = node.Parent.Ancestors().OfType <InvocationExpressionSyntax>().ToArray(); var invocations = (from i in invocationNodes let sym = context.SemanticModel.GetSymbolInfo(i) where sym.Symbol?.Kind == SymbolKind.Method let methodSymbol = (IMethodSymbol)sym.Symbol select new StructureMapConfigurationInvocation(methodSymbol, i)).ToArray(); ITypeSymbol plugin; LamarLifecycle lifecycle = null; if (method.Name.Equals("ForSingletonOf")) { lifecycle = LamarLifecycle.Singleton; } var assignment = node.Ancestors().OfType <AssignmentExpressionSyntax>().FirstOrDefault(); ISymbol assignedTo = null; if (assignment != null) { assignedTo = context.SemanticModel.GetSymbolInfo(assignment.Left).Symbol; } var variableDeclaration = node.Ancestors().OfType <VariableDeclarationSyntax>().FirstOrDefault(); if (variableDeclaration != null) { assignedTo = context.SemanticModel.GetDeclaredSymbol(variableDeclaration.Variables[0]); } ITypeSymbol PluginFromArgument(ExpressionSyntax expr) { // ReSharper disable once ConvertIfStatementToSwitchStatement if (expr is TypeOfExpressionSyntax toe) { var typeInfo = context.SemanticModel.GetTypeInfo(toe.Type); return(typeInfo.Type); } // ReSharper disable once InvertIf if (expr is InvocationExpressionSyntax ies && ies.Expression is MemberAccessExpressionSyntax mes) { var sym = context.SemanticModel.GetSymbolInfo(ies); // ReSharper disable once InvertIf if (sym.Symbol != null && sym.Symbol.Name.Equals("GetType")) { var typeInfo = context.SemanticModel.GetTypeInfo(mes.Expression); return(typeInfo.Type); } } if (expr is IdentifierNameSyntax ins) { var sym = context.SemanticModel.GetTypeInfo(ins); return(sym.Type); } return(null); } LamarLifecycle LifecycleFromArgument(ExpressionSyntax expr) { var lifecycleType = context.SemanticModel.GetTypeInfo(expr).Type; return(LifecycleMap[lifecycleType.ToDisplayString()]); } if (method.IsGenericMethod) { plugin = method.TypeArguments[0]; if (node.ArgumentList.Arguments.Count > 0) { lifecycle = LifecycleFromArgument(node.ArgumentList.Arguments[0].Expression); } } else { var expr = node.ArgumentList.Arguments[0].Expression; plugin = PluginFromArgument(expr); } if (plugin == null) { return; } LamarLifecycle FromInvocation(StructureMapConfigurationInvocation i) { switch (i.MethodSymbol.Name) { case "Singleton": { return(LamarLifecycle.Singleton); } case "Scoped": { return(LamarLifecycle.Scoped); } case "Transient": { return(LamarLifecycle.Transient); } default: { return(null); } } } lifecycle = lifecycle ?? invocations.Select(FromInvocation).FirstOrDefault(x => x != null) ?? LamarLifecycle.TransientImplicit; var concretesPluggedBy = new[] { "Use", "Add" }; var concretePluginInvocation = invocations.FirstOrDefault(x => concretesPluggedBy.Any(s => s.Equals(x.MethodSymbol.Name, StringComparison.Ordinal))); var concretePlugin = plugin; ITypeSymbol ConcretePluginFrom(StructureMapConfigurationInvocation invocation) { if (invocation.MethodSymbol.IsGenericMethod) { return(invocation.MethodSymbol.TypeArguments[0]); } var expr = invocation.Invocation.ArgumentList.Arguments[invocation.Invocation.ArgumentList.Arguments.Count - 1].Expression; var pluginToReturn = PluginFromArgument(expr); if (pluginToReturn == null) { if (expr is LambdaExpressionSyntax les) { var bodyType = context.SemanticModel.GetTypeInfo(les.Body); return(bodyType.Type ?? (context.SemanticModel.GetSymbolInfo(expr).Symbol as IMethodSymbol)?.ReturnType); } } return(pluginToReturn); } if (concretePluginInvocation != null) { concretePlugin = ConcretePluginFrom(concretePluginInvocation); } var assembly = context.Compilation.Assembly; var wiringCtx = new LamarWiringCtx(node, plugin, lifecycle, assembly, concretePlugin, assignedTo); host.wirings.Add(wiringCtx); }
// puts the correct arguments in the register statement private async Task<Document> CorrectArgumentsAsync(Document document, InvocationExpressionSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); string methodName = CodeFixHelper.GetRegisterMethodName(declaration); ClassDeclarationSyntax classDeclaration = declaration.AncestorsAndSelf().OfType<ClassDeclarationSyntax>().First(); methodName = CodeFixHelper.GetExistingAnalysisMethodName(classDeclaration); if (methodName == null) { methodName = "AnalyzeIfStatement"; } SyntaxNode statement = CodeFixHelper.CreateRegister(generator, declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(), methodName); SyntaxNode expression = generator.ExpressionStatement(statement); return await ReplaceNode(declaration.Parent, expression.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ParseLeadingTrivia("// Calls the method (first argument) to perform analysis whenever a SyntaxNode of kind IfStatement is found").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { string expression = node.Expression.ToString(); if (expression == _pattern) { string nodeValue = node.ToString(); if (Matches.ContainsKey(nodeValue)) { Matches[nodeValue] += 1; } else { Matches.Add(nodeValue, 1); } var a1 = node.Ancestors() .Where(x => x.IsKind(SyntaxKind.ClassStatement)) .Cast <ClassStatementSyntax>().ToList(); var a2 = node.Ancestors() .Where(x => x.IsKind(SyntaxKind.FunctionStatement) || x.IsKind(SyntaxKind.SubStatement)) .Cast <MethodStatementSyntax>().ToList(); var a3 = node.Ancestors() .Where(x => x.IsKind(SyntaxKind.ClassBlock)) .Cast <ClassBlockSyntax>().ToList(); var a3a = node.Ancestors() .Where(x => x.IsKind(SyntaxKind.ModuleBlock)) .Cast <ModuleBlockSyntax>().ToList(); var a4 = node.Ancestors() .Where(x => x.IsKind(SyntaxKind.FunctionBlock) || x.IsKind(SyntaxKind.SubBlock)) .Cast <MethodBlockSyntax>().ToList(); var a5 = node.Ancestors() .Where(x => x.IsKind(SyntaxKind.FunctionBlock) || x.IsKind(SyntaxKind.SubBlock)) .Cast <MethodBlockSyntax>().ToList(); string className = "unknown"; string moduleName = "unknown"; string typeName = "unknown"; string methodName = "none"; if (a3.Count > 0) { typeName = "Class"; className = node.Ancestors() .Where(x => x.IsKind(SyntaxKind.ClassBlock)) .Cast <ClassBlockSyntax>().First().ClassStatement.Identifier.ToString(); } if (a3a.Count > 0) { typeName = "Module"; moduleName = node.Ancestors() .Where(x => x.IsKind(SyntaxKind.ModuleBlock)) .Cast <ModuleBlockSyntax>().First().ModuleStatement.Identifier.ToString(); } if (a5.Count > 0) { methodName = node.Ancestors() .Where(x => x.IsKind(SyntaxKind.FunctionBlock) || x.IsKind(SyntaxKind.SubBlock)) .Cast <MethodBlockSyntax>().First().SubOrFunctionStatement.Identifier.ToString(); } //string className = node.Ancestors() // .Where(x => x.IsKind(SyntaxKind.ClassStatement)) // .Cast<ClassStatementSyntax>().First().ToString(); //string methodName = node.Ancestors() // .Where(x => x.IsKind(SyntaxKind.FunctionStatement) || x.IsKind(SyntaxKind.SubStatement)) // .Cast<MethodStatementSyntax>().First().ToString(); //StringBuilder.AppendLine(String.Format("{0,6}:({1,-25}) Method:({2,-35}) {3}", // typeName, // typeName == "Class" ? className : moduleName, // Helpers.VB.GetContainingMethod(node), nodeValue)); string messageContext = ""; if (DisplayClassOrModuleName) { // HACK(crhodes) // Figure out how to get Helpers to work messageContext = Helpers.VB.GetContainingContext(node, Display); } if (DisplayMethodName) { // HACK(crhodes) // Figure out how to get Helpers to work messageContext += string.Format(" Method:({0, -35})", Helpers.VB.GetContainingMethodName(node)); } Messages.AppendLine(String.Format("{0} {1}", messageContext, nodeValue)); } // Call base to visit children base.VisitInvocationExpression(node); }
private void ProcessEmitVertex(InvocationExpressionSyntax node) { var model = GetModel(node); DataFlowAnalysis analysis = null; if (_lastVertexEmit is ExpressionSyntax expression) { analysis = model.AnalyzeDataFlow(expression); } else if (_lastVertexEmit is StatementSyntax lastStatement) { var emitStatement = node.Ancestors().OfType <StatementSyntax>().FirstOrDefault(); if (lastStatement.Parent != emitStatement.Parent) { lastStatement = emitStatement.Parent.ChildNodes().Cast <StatementSyntax>().First(); } analysis = model.AnalyzeDataFlow(lastStatement, emitStatement); _lastVertexEmit = emitStatement; } var emit = model.GetSymbolInfo(node.ArgumentList.Arguments.Last().Expression); if (!(emit.Symbol is IFieldSymbol emitParam)) { throw new ShaderGenerationException("EmitVertex argument must be a field"); } var emitAttribute = emit.Symbol.GetAttributes().FirstOrDefault(a => a.AttributeClass.Name.Contains("EmitVertex")); if (emitAttribute == null) { throw new ShaderGenerationException("EmitVertex arguments must be marked with EmitVertexAttribute"); } int streamId = 0; if (node.ArgumentList.Arguments.Count > 1) { streamId = (int)model.GetConstantValue(node.ArgumentList.Arguments.First()).Value; } var assignments = analysis.AlwaysAssigned.Concat(_writeFields); if (!_emittedData.TryGetValue(streamId, out var emissions)) { emissions = new HashSet <ISymbol>(assignments.OfType <IFieldSymbol>(), SymbolEqualityComparer.Default); _emittedData.Add(streamId, emissions); if (assignments.Contains(emitParam)) { emissions.Add(emitParam); } } if (analysis != null) { foreach (var emission in emissions) { if (!assignments.Contains(emission) && !assignments.Contains(emission.ContainingType)) { var type = (emission as IFieldSymbol)?.Type ?? (emission as IParameterSymbol)?.Type; if (type == null || !type.GetMembers().OfType <IFieldSymbol>().All(assignments.Contains)) { throw new ShaderGenerationException($"{emission.Name} must be fully assigned before every call to EmitVertex"); } } } foreach (var assignment in assignments.OfType <IFieldSymbol>().Append <ISymbol>(emitParam).Where(a => !emissions.Contains(a))) { var type = (assignment as IFieldSymbol)?.Type ?? (assignment as IParameterSymbol)?.Type; if (type == null || !type.GetMembers().OfType <IFieldSymbol>().All(emissions.Contains)) { throw new ShaderGenerationException($"{assignment.Name} must be fully assigned before every call to EmitVertex"); } } } _writeFields.Clear(); }
private static bool IsInsideANullCheck(InvocationExpressionSyntax invocation, SemanticModel semanticModel, ISymbol symbol) { var ifs = invocation.Ancestors().OfType<IfStatementSyntax>(); foreach (IfStatementSyntax @if in ifs) { if ([email protected]?.IsKind(SyntaxKind.NotEqualsExpression) ?? true) continue; var equals = (BinaryExpressionSyntax)@if.Condition; if (equals.Left == null || equals.Right == null) continue; ISymbol identifierSymbol; if (equals.Right.IsKind(SyntaxKind.NullLiteralExpression) && equals.Left.IsKind(SyntaxKind.IdentifierName)) identifierSymbol = semanticModel.GetSymbolInfo(equals.Left).Symbol; else if (equals.Left.IsKind(SyntaxKind.NullLiteralExpression) && equals.Right.IsKind(SyntaxKind.IdentifierName)) identifierSymbol = semanticModel.GetSymbolInfo(equals.Right).Symbol; else continue; if (symbol.Equals(identifierSymbol)) return true; } return false; }