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; StructureMapLifecycle lifecycle = null; if (method.Name.Equals("ForSingletonOf")) { lifecycle = StructureMapLifecycle.Singleton; } 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); } StructureMapLifecycle 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 (node.ArgumentList.Arguments.Count > 1) { lifecycle = LifecycleFromArgument(node.ArgumentList.Arguments[1].Expression); } } if (plugin == null) { return; } StructureMapLifecycle FromInvocation(StructureMapConfigurationInvocation i) { switch (i.MethodSymbol.Name) { case "LifecycleIs": { if (i.MethodSymbol.IsGenericMethod) { var lifecycleType = i.MethodSymbol.TypeArguments[0]; return(LifecycleMap[lifecycleType.ToDisplayString()]); } else { var lifecycleType = context.SemanticModel.GetTypeInfo(i.Invocation.ArgumentList.Arguments[0].Expression).Type; return(LifecycleMap[lifecycleType.ToDisplayString()]); } } case "Singleton": { return(StructureMapLifecycle.Singleton); } case "AlwaysUnique": { return(StructureMapLifecycle.Unique); } case "Transient": { return(StructureMapLifecycle.Transient); } default: { return(null); } } } lifecycle = lifecycle ?? invocations.Select(FromInvocation).FirstOrDefault(x => x != null) ?? StructureMapLifecycle.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 StructureMapWiringCtx(node, plugin, lifecycle, assembly, concretePlugin); host.wirings.Add(wiringCtx); }
private static void WriteLocations(StructureMapWiringCtx item) { Console.WriteLine($"\t\t{item.Invocation.GetLocation()}"); }