private static void WriteLocations(LamarWiringCtx item) { Console.WriteLine($"\t\t{item.Invocation.GetLocation()}"); }
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); }