public override ImmutableDictionary <string, string> Generate(CodeIndexerService codeIndexerService) { var usings = new List <string>(); var theClasses = _settings.BaseClasses.SelectMany(theClassName => { var theClass = codeIndexerService.GetClassDeclaration(theClassName); var theClassSemanticModel = codeIndexerService.GetSemanticModel(theClass.SyntaxTree); var theClassSymbol = theClassSemanticModel.GetDeclaredSymbol(theClass); return(codeIndexerService.GetAllClassDeclarations().Where(classDecl => { var usingStatementSyntaxes = Utilities.GetDescendantsOfType <UsingDirectiveSyntax>(classDecl.SyntaxTree.GetRoot()); usings.AddRange(usingStatementSyntaxes .Select(us => us.ToString() + "\n")); var aClassSymbol = codeIndexerService.GetSemanticModel(classDecl.SyntaxTree).GetDeclaredSymbol(classDecl); return Utilities.IsBaseClass(aClassSymbol, theClassSymbol); })); }).ToImmutableDictionary(x => x.Identifier.Text); var extensionMethods = new List <string>(); extensionMethods.Add($"namespace {_settings.Namespace} {{\n"); extensionMethods.Add($"public static class {_settings.ExtensionMethodName}Extensions {{\n"); var constructors = new List <Tuple <ClassDeclarationSyntax, ConstructorDeclarationSyntax, SemanticModel> >(); foreach (var aClass in theClasses.Values) { var aClassSemanticModel = codeIndexerService.GetSemanticModel(aClass.SyntaxTree); usings.Add($"using {aClassSemanticModel.GetDeclaredSymbol(aClass).ContainingNamespace};\n"); foreach (var constructor in aClass.Members.OfType <ConstructorDeclarationSyntax>().Where(constructor => constructor.Modifiers.Any(SyntaxKind.PublicKeyword))) { constructors.Add(Tuple.Create(aClass, constructor, aClassSemanticModel)); } } var memberDeduplicationService = new MemberDeduplicationService(); var deduplicatedConstructors = memberDeduplicationService.DeduplicateMembers(constructors, x => x.Item3.GetDeclaredSymbol(x.Item2)); foreach (var deduplicatedMember in deduplicatedConstructors) { var(aClass, constructor, aClassSemanticModel) = deduplicatedMember.Value; var constructorArguments = string.Join(", ", constructor.ParameterList.Parameters.Select(parameter => parameter.Identifier.Text)); var parameters = string.Join(", ", constructor.ParameterList.Parameters.Select(parameter => $"{parameter.Type} {parameter.Identifier.Text}")); usings.AddRange(constructor.ParameterList.Parameters .Select(parameter => aClassSemanticModel.GetSymbolInfo(parameter.Type).Symbol) .Where(symbol => symbol != null) .Select(symbol => $"using {symbol.ContainingNamespace};\n")); var theInterface = aClass.BaseList.Types.First(type => { var symbol = aClassSemanticModel.GetSymbolInfo(type.Type).Symbol as INamedTypeSymbol; return(symbol.TypeKind == TypeKind.Interface); }); var typeArgs = string.Join(", ", aClass.TypeParameterList.Parameters.Select(parameter => parameter.Identifier.Text)); if (!string.IsNullOrWhiteSpace(typeArgs)) { typeArgs = $"<{typeArgs}>"; } extensionMethods.Add($"public static {theInterface.Type} {_settings.ExtensionMethodName}{typeArgs}(this {parameters}) {{\n"); extensionMethods.Add($"return new {aClass.Identifier}{typeArgs}({constructorArguments});"); extensionMethods.Add("}\n"); } extensionMethods.Add("}\n}\n"); return(ImmutableDictionary <string, string> .Empty .Add($"{_settings.ExtensionMethodName}Extensions.g.cs", string.Join("", usings.Distinct().OrderBy(x => x).Concat(extensionMethods)))); }