예제 #1
0
        /// <summary>
        /// Prepares the <see cref="NamespaceMemberBuilder"/> from the <paramref name="symbol"/>
        /// and adds it to <see cref="AssemblyMemberBuilder.Namespaces"/>
        /// </summary>
        /// <param name="symbol">Source <see cref="INamespaceSymbol"/></param>
        /// <param name="root">Builder root</param>
        /// <param name="assembly">Parent <see cref="AssemblyMemberBuilder"/></param>
        /// <param name="level">Hierarchy level (used to indent the console output)</param>
        private static void BuildNamespace(INamespaceSymbol symbol, RootMemberBuilder root, AssemblyMemberBuilder assembly, int level)
        {
            var children        = symbol.GetMembers().ToArray();
            var childNamespaces = children.OfType <INamespaceSymbol>().ToArray();
            var childTypes      = children.OfType <ITypeSymbol>().ToArray();

            NamespaceMemberBuilder n = null;

            if (childTypes.Length > 0) //check if not "empty" namespace resp. part of "dot syntax" (when there is a ns a.b.c.d and "d" is the only one containing the types, the a,b and c are in symbols hierarchy as "empty" ns
            {
                n = new NamespaceMemberBuilder()
                {
                    Name            = SymbolDisplay.ToDisplayString(symbol),
                    NameBase        = SymbolDisplay.ToDisplayString(symbol),
                    Symbol          = symbol,
                    DocumentationId = symbol.GetDocumentationCommentId(),
                };

                //ns documentation - internal class NamespaceDoc { }
                var docClass = symbol.GetMembers("NamespaceDoc").OfType <INamedTypeSymbol>().FirstOrDefault();
                if (docClass != null)
                {
                    n.DocumentationXml = docClass.GetDocumentationCommentXml();
                    n.Documentation    = Documentation.Read(n.DocumentationXml);
                }

                assembly.Namespaces.Add(n);
                Console.WriteLine($"{new string(' ', level)} read as {n}");

                foreach (var memberSymbol in childTypes)
                {
                    Build(memberSymbol, root, assembly, n, null, level + 1);
                }
            }

            foreach (var memberSymbol in childNamespaces)
            {
                Build(memberSymbol, root, assembly, n, null, level + 1);
            }
        }
예제 #2
0
        /// <summary>
        /// Walks through the Roslyn symbols hierarchy and prepares the member builders hierarchy into the given <paramref name="root"/> builder.
        /// </summary>
        /// <param name="symbol">Symbol to process</param>
        /// <param name="root">Root builder</param>
        /// <param name="assembly">Containing assembly builder</param>
        /// <param name="ns">Containing namespace builder</param>
        /// <param name="type">Containing type builder (used for nested types)</param>
        /// <param name="level">Hierarchy level (used to indent the console output)</param>
        private static void Build(ISymbol symbol, RootMemberBuilder root, AssemblyMemberBuilder assembly, NamespaceMemberBuilder ns,
                                  TypeMemberBuilder type, int level)
        {
            Console.WriteLine($"{new string(' ', level)}Checking the {symbol.Kind}: {symbol.Name}");
            try
            {
                switch (symbol)
                {
                case IAssemblySymbol assemblySymbol:
                    BuildAssembly(assemblySymbol, root, level);
                    break;

                case INamespaceSymbol namespaceSymbol:
                    BuildNamespace(namespaceSymbol, root, assembly, level);
                    break;

                case INamedTypeSymbol typeSymbol:
                    BuildType(typeSymbol, root, assembly, ns, type, level);
                    break;

                case IFieldSymbol fieldSymbol:
                    BuildField(fieldSymbol, root, type, level);
                    break;

                case IPropertySymbol propertySymbol:
                    BuildProperty(propertySymbol, root, type, level);
                    break;

                case IMethodSymbol methodSymbol:
                    BuildMethod(methodSymbol, root, type, level);
                    break;

                case IEventSymbol eventSymbol:
                    BuildEvent(eventSymbol, root, type, level);
                    break;
                }
            }
            catch (Exception exception)
            {
                ConsoleUtils.WriteErr($"{new string(' ', level)}Exception '{exception.Message}' while processing {symbol.Kind}: {symbol.Name}");
                throw;
            }
        }
예제 #3
0
        /// <summary>
        /// Prepares the <see cref="TypeMemberBuilder"/> from the <paramref name="symbol"/>
        /// and adds it to <see cref="NamespaceMemberBuilder.Types"/>
        /// </summary>
        /// <param name="symbol">Source <see cref="INamedTypeSymbol"/></param>
        /// <param name="root">Builder root</param>
        /// <param name="assembly">Containing <see cref="AssemblyMemberBuilder"/></param>
        /// <param name="ns">Parent <see cref="NamespaceMemberBuilder"/></param>
        /// <param name="type">Parent <see cref="TypeMemberBuilder"/> for nested types</param>
        /// <param name="level">Hierarchy level (used to indent the console output)</param>
        // ReSharper disable once SuggestBaseTypeForParameter
        private static void BuildType(INamedTypeSymbol symbol, RootMemberBuilder root, AssemblyMemberBuilder assembly, NamespaceMemberBuilder ns, TypeMemberBuilder type, int level)
        {
            if (symbol.IsImplicitlyDeclared)
            {
                return;
            }
            if (symbol.GetAttributes().Any(a => a.AttributeClassString() == "System.Runtime.CompilerServices.CompilerGeneratedAttribute"))
            {
                return;
            }
            if (symbol.Name.Contains("NuProps"))
            {
            }
            var t = new TypeMemberBuilder()
            {
                Name             = type == null ? symbol.Name : $"{type.Name}.{symbol.Name}",
                Symbol           = symbol,
                SourceFiles      = symbol.DeclaringSyntaxReferences.Select(dsr => dsr.SyntaxTree.FilePath).ToList(),
                DocumentationId  = symbol.GetDocumentationCommentId(),
                DocumentationXml = symbol.GetDocumentationCommentXml(),
                Documentation    = Documentation.Read(symbol.GetDocumentationCommentXml()),
                TypeKind         = symbol.TypeKind.ToTypeKindEnum(),
                TypeRef          = TypeRef.GetOrCreate(symbol, root),

                Modifier   = ModifierEnumExtensions.Modifier(symbol.DeclaredAccessibility),
                IsAbstract = symbol.IsAbstract,
                IsExtern   = symbol.IsExtern,
                IsSealed   = symbol.IsSealed,
                IsStatic   = symbol.IsStatic,
                IsNew      = symbol.GetIsNew(),
                IsGeneric  = symbol.IsGenericType &&
                             symbol.TypeParameters != null &&
                             symbol.TypeParameters.Length > 0
            };

            t.NameBase = t.Name;

            //Get the implemented interfaces
            var typeInterfaces = symbol.Interfaces;

            if (typeInterfaces != null && typeInterfaces.Length > 0)
            {
                //directly implemented
                t.InterfacesTypeRefs = typeInterfaces.Select(i => TypeRef.GetOrCreate(i, root)).ToList();
            }

            var typeAllInterfaces = symbol.AllInterfaces;

            if (typeAllInterfaces != null && typeAllInterfaces.Length > 0)
            {
                //includes the inherited
                t.AllInterfacesTypeRefs = typeAllInterfaces.Select(i => TypeRef.GetOrCreate(i, root)).ToList();
                foreach (var implementedInterface in typeAllInterfaces)
                {
                    var interfaceMembers = implementedInterface.GetMembers();
                    if (interfaceMembers == null)
                    {
                        continue;
                    }

                    foreach (var interfaceMember in interfaceMembers.Where(
                                 im => im.Kind == SymbolKind.Event ||
                                 im.Kind == SymbolKind.Property ||
                                 im.Kind == SymbolKind.Method))
                    {
                        var implementationMember = symbol.FindImplementationForInterfaceMember(interfaceMember);
                        if (implementationMember == null)
                        {
                            continue;
                        }

                        t.InterfaceImplementationsByInterfaceMember.Add(interfaceMember, implementationMember);

                        if (!t.InterfaceMembersByInterfaceImplementation.TryGetValue(implementationMember, out var interfaceMemberList))
                        {
                            interfaceMemberList = new List <ISymbol>();
                            t.InterfaceMembersByInterfaceImplementation.Add(implementationMember, interfaceMemberList);
                        }
                        ((List <ISymbol>)interfaceMemberList).Add(interfaceMember);
                    }
                }
            }

            //Get the attributes
            t.SetAttributes(root);

            if (t.IsGeneric)
            {
                //Process the type parameters
                t.TypeParameters = GetTypeParameters(symbol.TypeParameters, root);
                t.Name          += $"<{string.Join(",", t.TypeParameters.Select(tp => tp.Name))}>"; // add types to name
            }

            if (t.TypeKind == TypeKindEnum.Delegate)
            {
                //Process delegate - delegates only have parameters and return value
                t.DelegateReturnType = TypeRef.GetOrCreate(symbol.DelegateInvokeMethod.ReturnType, root);
                t.DelegateParameters = GetMethodParameters(symbol.DelegateInvokeMethod.Parameters, root);
            }

            ns.Types.Add(t);
            Console.WriteLine($"{new string(' ', level)} read as {t}");

            foreach (var subType in symbol.GetMembers())
            {
                if (!subType.IsImplicitlyDeclared)
                {
                    Build(subType, root, assembly, ns, t, level + 1);
                }
            }
        }