Esempio n. 1
0
        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))));
        }
Esempio n. 2
0
        public override ImmutableDictionary <string, string> Generate(CodeIndexerService codeIndexerService)
        {
            var results = new Dictionary <string, string>();

            foreach (var iface in _settings.InterfacesToImplement)
            {
                var interfaceDeclaration = codeIndexerService.GetInterfaceDeclaration(iface);

                var className         = $"Anonymous{iface.Substring(1)}";
                var sourceCodeBuilder = new StringBuilder();

                var typeParameters = interfaceDeclaration.TypeParameterList.Parameters.Select(tps => tps.Identifier.Text).ToImmutableList();
                var genericParams  = "";
                if (typeParameters.Count > 0)
                {
                    genericParams = $"<{string.Join(", ", typeParameters)}>";
                }

                var usings = new List <string>();

                sourceCodeBuilder.AppendLine(
                    $"namespace {_settings.Namespace} {{\npublic class {className}{genericParams} : {iface}{genericParams} {{");

                var semanticModel            = codeIndexerService.GetSemanticModel(interfaceDeclaration.SyntaxTree);
                var delegateMemberCandidates = new List <MemberToBeDelegated>();
                var candidateParameters      = new List <Parameter>();
                GetInterfacesToImplementWith(semanticModel.GetDeclaredSymbol(interfaceDeclaration), candidateParameters, delegateMemberCandidates);

                var delegateMemberService        = new DelegateMemberService();
                var memberDeduplicationService   = new MemberDeduplicationService();
                var deduplicatedDelegatedMembers = memberDeduplicationService
                                                   .DeduplicateMembers(delegateMemberCandidates, delegated => delegated.Member).ToImmutableList();
                var parameters = candidateParameters.Where(candidateParameter =>
                                                           deduplicatedDelegatedMembers.Any(deduplicatedDelegatedMember =>
                                                                                            deduplicatedDelegatedMember.Value.MemberName == candidateParameter.MemberName))
                                 .ToImmutableList();
                var getEnumerator = deduplicatedDelegatedMembers.FirstOrDefault(delegateMemberCandidate =>
                                                                                delegateMemberCandidate.Value.Member.Name == "GetEnumerator");

                foreach (var baseInterface in Utilities.GetBaseInterfaces(semanticModel.GetDeclaredSymbol(interfaceDeclaration)))
                {
                    var newUsing =
                        $"using {string.Join(".", baseInterface.ContainingNamespace.ConstituentNamespaces)};";
                    if (!newUsing.Contains("global namespace"))
                    {
                        usings.Add(newUsing);
                    }
                }

                foreach (var usingDirective in Utilities.GetBaseInterfaces(semanticModel.GetDeclaredSymbol(interfaceDeclaration))
                         .SelectMany(symbol => symbol.DeclaringSyntaxReferences).Select(syntaxRef => syntaxRef.SyntaxTree)
                         .SelectMany(syntaxTree => Utilities.GetDescendantsOfType <UsingDirectiveSyntax>(syntaxTree.GetRoot())))
                {
                    var newUsing = usingDirective.ToString();
                    if (!newUsing.Contains("global namespace"))
                    {
                        usings.Add(newUsing);
                    }
                }

                var parameterString = string.Join(", ", parameters
                                                  .OrderBy(parameter => parameter.DelegateType).ThenBy(parameter => parameter.ParameterName)
                                                  .Select(parameter => $"{parameter.Type} {parameter.ParameterName}"));

                sourceCodeBuilder.AppendLine(string.Join("\n", parameters
                                                         .OrderBy(parameter => parameter.DelegateType).ThenBy(parameter => parameter.ParameterName)
                                                         .Select(parameter => parameter.ToMemberDeclaration())));

                sourceCodeBuilder.AppendLine($"public {className}({parameterString}) {{");

                var memberAssignments = parameters
                                        .Select(parameter => $"{parameter.MemberName} = {parameter.ParameterName};");
                sourceCodeBuilder.AppendLine(string.Join("\n", memberAssignments));
                sourceCodeBuilder.AppendLine("}");

                foreach (var deduplicatedMember in deduplicatedDelegatedMembers)
                {
                    delegateMemberService.DelegateMember(deduplicatedMember.Value.Member, deduplicatedMember.Value.MemberName, deduplicatedMember.Value.SetMemberName, deduplicatedMember.ImplementExplicitly, sourceCodeBuilder, usings, deduplicatedMember.Value.Type, null);
                }

                if (getEnumerator != null)
                {
                    sourceCodeBuilder.AppendLine("IEnumerator IEnumerable.GetEnumerator() {");
                    sourceCodeBuilder.Append($"return {getEnumerator.Value.MemberName}.GetEnumerator();");
                    sourceCodeBuilder.AppendLine("}");
                }

                sourceCodeBuilder.AppendLine("}\n}\n");

                usings = usings.Distinct().OrderBy(x => x).ToList();

                var filePath = $"{className}.g.cs";
                results.Add(filePath, $"{string.Join("\n",usings)}\n{sourceCodeBuilder}");
            }

            return(results.ToImmutableDictionary());
        }