コード例 #1
0
 private void DisplayName(CodeFileTokensBuilder builder, ISymbol symbol, ISymbol definedSymbol = null)
 {
     foreach (var symbolDisplayPart in symbol.ToDisplayParts(_defaultDisplayFormat))
     {
         builder.Append(MapToken(definedSymbol, symbolDisplayPart));
     }
 }
コード例 #2
0
        private void Build(CodeFileTokensBuilder builder, INamespaceSymbol namespaceSymbol, List <NavigationItem> navigationItems)
        {
            builder.Keyword(SyntaxKind.NamespaceKeyword);
            builder.Space();
            BuildNamespaceName(builder, namespaceSymbol);

            builder.Space();
            builder.Punctuation(SyntaxKind.OpenBraceToken);
            builder.IncrementIndent();
            builder.NewLine();

            List <NavigationItem> namespaceItems = new List <NavigationItem>();

            foreach (var namedTypeSymbol in SymbolOrderProvider.OrderTypes(namespaceSymbol.GetTypeMembers()))
            {
                BuildType(builder, namedTypeSymbol, namespaceItems);
            }

            CloseBrace(builder);

            var namespaceItem = new NavigationItem()
            {
                NavigationId = namespaceSymbol.GetId(),
                Text         = namespaceSymbol.ToDisplayString(),
                ChildItems   = namespaceItems.ToArray(),
                Tags         = { { "TypeKind", "namespace" } }
            };

            navigationItems.Add(namespaceItem);
        }
コード例 #3
0
 private void BuildTypedConstant(CodeFileTokensBuilder builder, TypedConstant typedConstant)
 {
     if (typedConstant.IsNull)
     {
         builder.Keyword(SyntaxKind.NullKeyword);
     }
     else if (typedConstant.Kind == TypedConstantKind.Enum)
     {
         new CodeFileBuilderEnumFormatter(builder).Format(typedConstant.Type, typedConstant.Value);
     }
     else
     {
         if (typedConstant.Value is string s)
         {
             builder.Append(
                 ObjectDisplay.FormatLiteral(s, ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.EscapeNonPrintableCharacters),
                 CodeFileTokenKind.StringLiteral);
         }
         else
         {
             builder.Append(
                 ObjectDisplay.FormatPrimitive(typedConstant.Value, ObjectDisplayOptions.None),
                 CodeFileTokenKind.Literal);
         }
     }
 }
コード例 #4
0
        private void BuildMember(CodeFileTokensBuilder builder, ISymbol member)
        {
            BuildAttributes(builder, member.GetAttributes());

            builder.WriteIndent();
            NodeFromSymbol(builder, member);
            if (member.Kind == SymbolKind.Method &&
                !member.IsAbstract &&
                member.ContainingType.TypeKind != TypeKind.Interface)
            {
                builder.Space();
                builder.Punctuation(SyntaxKind.OpenBraceToken);
                builder.Punctuation(SyntaxKind.CloseBraceToken);
            }
            else if (member.Kind == SymbolKind.Field && member.ContainingType.TypeKind == TypeKind.Enum)
            {
                builder.Punctuation(SyntaxKind.CommaToken);
            }
            else if (member.Kind != SymbolKind.Property)
            {
                builder.Punctuation(SyntaxKind.SemicolonToken);
            }

            builder.NewLine();
        }
コード例 #5
0
        public CodeFile Build(IAssemblySymbol assemblySymbol)
        {
            var assemblyItems = new List <NavigationItem>();
            var builder       = new CodeFileTokensBuilder();

            foreach (var namespaceSymbol in EnumerateNamespaces(assemblySymbol))
            {
                if (namespaceSymbol.IsGlobalNamespace)
                {
                    foreach (var namedTypeSymbol in SortTypes(namespaceSymbol.GetTypeMembers()))
                    {
                        BuildType(builder, namedTypeSymbol, assemblyItems);
                    }
                }
                else
                {
                    Build(builder, namespaceSymbol, assemblyItems);
                }
            }

            var node = new CodeFile()
            {
                Tokens     = builder.Tokens.ToArray(),
                Version    = CodeFile.CurrentVersion,
                Navigation = assemblyItems,
            };

            return(node);
        }
コード例 #6
0
 private static void CloseBrace(CodeFileTokensBuilder builder)
 {
     builder.DecrementIndent();
     builder.WriteIndent();
     builder.Punctuation(SyntaxKind.CloseBraceToken);
     builder.NewLine();
 }
コード例 #7
0
 private void BuildNamespaceName(CodeFileTokensBuilder builder, INamespaceSymbol namespaceSymbol)
 {
     if (!namespaceSymbol.ContainingNamespace.IsGlobalNamespace)
     {
         BuildNamespaceName(builder, namespaceSymbol.ContainingNamespace);
         builder.Punctuation(SyntaxKind.DotToken);
     }
     NodeFromSymbol(builder, namespaceSymbol);
 }
コード例 #8
0
 private void NodeFromSymbol(CodeFileTokensBuilder builder, ISymbol symbol)
 {
     builder.Append(new CodeFileToken()
     {
         DefinitionId = symbol.GetId(),
         Kind         = CodeFileTokenKind.LineIdMarker
     });
     DisplayName(builder, symbol, symbol);
 }
コード例 #9
0
        private void BuildType(CodeFileTokensBuilder builder, INamedTypeSymbol namedType, List <NavigationItem> navigationBuilder)
        {
            if (!IsAccessible(namedType))
            {
                return;
            }

            var navigationItem = new NavigationItem()
            {
                NavigationId = GetId(namedType),
                Text         = namedType.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
            };

            navigationBuilder.Add(navigationItem);
            navigationItem.Tags.Add("TypeKind", "type_" + namedType.TypeKind.ToString().ToLowerInvariant());

            builder.WriteIndent();
            NodeFromSymbol(builder, namedType, true);
            if (namedType.TypeKind == TypeKind.Delegate)
            {
                builder.Punctuation(SyntaxKind.SemicolonToken);
                builder.NewLine();
                return;
            }

            builder.Space();
            builder.Punctuation(SyntaxKind.OpenBraceToken);
            builder.IncrementIndent();
            builder.NewLine();

            foreach (var namedTypeSymbol in SortTypes(namedType.GetTypeMembers()))
            {
                BuildType(builder, namedTypeSymbol, navigationBuilder);
            }

            foreach (var member in SortMembers(namedType.GetMembers()))
            {
                if (member.Kind == SymbolKind.NamedType || member.IsImplicitlyDeclared || !IsAccessible(member))
                {
                    continue;
                }
                if (member is IMethodSymbol method)
                {
                    if (method.MethodKind == MethodKind.PropertyGet ||
                        method.MethodKind == MethodKind.PropertySet ||
                        method.MethodKind == MethodKind.EventAdd ||
                        method.MethodKind == MethodKind.EventRemove ||
                        method.MethodKind == MethodKind.EventRaise)
                    {
                        continue;
                    }
                }
                BuildMember(builder, member);
            }

            CloseBrace(builder);
        }
コード例 #10
0
        private void BuildTypedConstant(CodeFileTokensBuilder builder, TypedConstant typedConstant)
        {
            if (typedConstant.IsNull)
            {
                builder.Keyword(SyntaxKind.NullKeyword);
            }
            else if (typedConstant.Kind == TypedConstantKind.Enum)
            {
                new CodeFileBuilderEnumFormatter(builder).Format(typedConstant.Type, typedConstant.Value);
            }
            else if (typedConstant.Kind == TypedConstantKind.Type)
            {
                builder.Keyword(SyntaxKind.TypeOfKeyword);
                builder.Punctuation("(");
                DisplayName(builder, (ITypeSymbol)typedConstant.Value);
                builder.Punctuation(")");
            }
            else if (typedConstant.Kind == TypedConstantKind.Array)
            {
                builder.Keyword(SyntaxKind.NewKeyword);
                builder.Punctuation("[] {");

                bool first = true;

                foreach (var value in typedConstant.Values)
                {
                    if (!first)
                    {
                        builder.Punctuation(SyntaxKind.CommaToken);
                        builder.Space();
                    }
                    else
                    {
                        first = false;
                    }

                    BuildTypedConstant(builder, value);
                }
                builder.Punctuation("}");
            }
            else
            {
                if (typedConstant.Value is string s)
                {
                    builder.Append(
                        ObjectDisplay.FormatLiteral(s, ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.EscapeNonPrintableCharacters),
                        CodeFileTokenKind.StringLiteral);
                }
                else
                {
                    builder.Append(
                        ObjectDisplay.FormatPrimitive(typedConstant.Value, ObjectDisplayOptions.None),
                        CodeFileTokenKind.Literal);
                }
            }
        }
コード例 #11
0
 private void DisplayName(CodeFileTokensBuilder builder, ISymbol symbol, ISymbol definedSymbol = null)
 {
     if (NeedsAccessibility(symbol))
     {
         builder.Keyword(SyntaxFacts.GetText(ToEffectiveAccessibility(symbol.DeclaredAccessibility)));
         builder.Space();
     }
     foreach (var symbolDisplayPart in symbol.ToDisplayParts(_defaultDisplayFormat))
     {
         builder.Append(MapToken(definedSymbol, symbolDisplayPart));
     }
 }
コード例 #12
0
        public CodeFile Build(IAssemblySymbol assemblySymbol, bool runAnalysis, List <DependencyInfo> dependencies)
        {
            _assembly = assemblySymbol;
            var analyzer = new Analyzer();

            if (runAnalysis)
            {
                analyzer.VisitAssembly(assemblySymbol);
            }
            var builder = new CodeFileTokensBuilder();

            BuildDependencies(builder, dependencies);

            var navigationItems = new List <NavigationItem>();

            foreach (var namespaceSymbol in SymbolOrderProvider.OrderNamespaces(EnumerateNamespaces(assemblySymbol)))
            {
                if (namespaceSymbol.IsGlobalNamespace)
                {
                    foreach (var namedTypeSymbol in SymbolOrderProvider.OrderTypes(namespaceSymbol.GetTypeMembers()))
                    {
                        BuildType(builder, namedTypeSymbol, navigationItems);
                    }
                }
                else
                {
                    Build(builder, namespaceSymbol, navigationItems);
                }
            }

            NavigationItem assemblyNavigationItem = new NavigationItem()
            {
                Text       = assemblySymbol.Name + ".dll",
                ChildItems = navigationItems.ToArray(),
                Tags       = { { "TypeKind", "assembly" } }
            };

            var node = new CodeFile()
            {
                Name          = $"{assemblySymbol.Name} ({assemblySymbol.Identity.Version})",
                Language      = "C#",
                Tokens        = builder.Tokens.ToArray(),
                VersionString = CurrentVersion,
                Navigation    = new[] { assemblyNavigationItem },
                Diagnostics   = analyzer.Results.ToArray(),
                PackageName   = assemblySymbol.Name
            };

            return(node);
        }
コード例 #13
0
        private void BuildDocumentation(CodeFileTokensBuilder builder, ISymbol symbol)
        {
            var lines = symbol.GetDocumentationCommentXml().Trim().Split(_newlineChars);

            if (lines.All(string.IsNullOrWhiteSpace))
            {
                return;
            }
            builder.Append(null, CodeFileTokenKind.DocumentRangeStart);
            foreach (var line in lines)
            {
                builder.WriteIndent();
                builder.Comment("// " + line.Trim());
                builder.NewLine();
            }
            builder.Append(null, CodeFileTokenKind.DocumentRangeEnd);
        }
コード例 #14
0
 private void NodeFromSymbol(CodeFileTokensBuilder builder, ISymbol symbol, bool prependVisibility = false)
 {
     builder.Append(new CodeFileToken()
     {
         DefinitionId = GetId(symbol),
         Kind         = CodeFileTokenKind.LineIdMarker
     });
     if (prependVisibility)
     {
         builder.Keyword(SyntaxFacts.GetText(ToEffectiveAccessibility(symbol.DeclaredAccessibility)));
         builder.Space();
     }
     foreach (var symbolDisplayPart in symbol.ToDisplayParts(_defaultDisplayFormat))
     {
         builder.Append(MapToken(symbol, symbolDisplayPart));
     }
 }
コード例 #15
0
        private void BuildMember(CodeFileTokensBuilder builder, ISymbol member)
        {
            BuildDocumentation(builder, member);
            BuildAttributes(builder, member.GetAttributes());

            builder.WriteIndent();
            NodeFromSymbol(builder, member);

            if (member.Kind == SymbolKind.Field && member.ContainingType.TypeKind == TypeKind.Enum)
            {
                builder.Punctuation(SyntaxKind.CommaToken);
            }
            else if (member.Kind != SymbolKind.Property)
            {
                builder.Punctuation(SyntaxKind.SemicolonToken);
            }

            builder.NewLine();
        }
コード例 #16
0
        private static void BuildClassModifiers(CodeFileTokensBuilder builder, INamedTypeSymbol namedType)
        {
            if (namedType.IsAbstract)
            {
                builder.Keyword(SyntaxKind.AbstractKeyword);
                builder.Space();
            }

            if (namedType.IsStatic)
            {
                builder.Keyword(SyntaxKind.StaticKeyword);
                builder.Space();
            }

            if (namedType.IsSealed)
            {
                builder.Keyword(SyntaxKind.SealedKeyword);
                builder.Space();
            }
        }
コード例 #17
0
        private void BuildBaseType(CodeFileTokensBuilder builder, INamedTypeSymbol namedType)
        {
            bool first = true;

            if (namedType.BaseType != null &&
                namedType.BaseType.SpecialType == SpecialType.None)
            {
                builder.Punctuation(SyntaxKind.ColonToken);
                builder.Space();
                first = false;

                DisplayName(builder, namedType.BaseType);
            }

            foreach (var typeInterface in namedType.Interfaces)
            {
                if (!IsAccessible(typeInterface))
                {
                    continue;
                }

                if (!first)
                {
                    builder.Punctuation(SyntaxKind.CommaToken);
                    builder.Space();
                }
                else
                {
                    builder.Punctuation(SyntaxKind.ColonToken);
                    builder.Space();
                    first = false;
                }

                DisplayName(builder, typeInterface);
            }

            if (!first)
            {
                builder.Space();
            }
        }
コード例 #18
0
        public static void BuildDependencies(CodeFileTokensBuilder builder, List <DependencyInfo> dependencies)
        {
            if (dependencies != null && dependencies.Any())
            {
                builder.NewLine();
                builder.Append("Dependencies:", CodeFileTokenKind.Text);
                builder.NewLine();
                foreach (DependencyInfo dependency in dependencies)
                {
                    builder.Append(new CodeFileToken(dependency.Name, CodeFileTokenKind.Text)
                    {
                        // allow dependency to be commentable
                        DefinitionId = dependency.Name
                    });
                    // don't include the version in the API sign-off diffs
                    builder.Append(null, CodeFileTokenKind.SkipDiffRangeStart);
                    builder.Append($"-{dependency.Version}", CodeFileTokenKind.Text);
                    builder.Append(null, CodeFileTokenKind.SkipDiffRangeEnd);
                    builder.NewLine();
                }

                builder.NewLine();
            }
        }
コード例 #19
0
 public CodeFileBuilderEnumFormatter(CodeFileTokensBuilder builder) : base(null, SymbolDisplayFormat.FullyQualifiedFormat, false, null, 0, false)
 {
     _builder = builder;
 }
コード例 #20
0
 private void BuildVisibility(CodeFileTokensBuilder builder, ISymbol symbol)
 {
     builder.Keyword(SyntaxFacts.GetText(ToEffectiveAccessibility(symbol.DeclaredAccessibility)));
 }
コード例 #21
0
        private void BuildType(CodeFileTokensBuilder builder, INamedTypeSymbol namedType, List <NavigationItem> navigationBuilder)
        {
            if (!IsAccessible(namedType))
            {
                return;
            }

            var navigationItem = new NavigationItem()
            {
                NavigationId = namedType.GetId(),
                Text         = namedType.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
            };

            navigationBuilder.Add(navigationItem);
            navigationItem.Tags.Add("TypeKind", namedType.TypeKind.ToString().ToLowerInvariant());

            BuildDocumentation(builder, namedType);
            BuildAttributes(builder, namedType.GetAttributes());

            builder.WriteIndent();
            BuildVisibility(builder, namedType);

            builder.Space();

            switch (namedType.TypeKind)
            {
            case TypeKind.Class:
                BuildClassModifiers(builder, namedType);
                builder.Keyword(SyntaxKind.ClassKeyword);
                break;

            case TypeKind.Delegate:
                builder.Keyword(SyntaxKind.DelegateKeyword);
                break;

            case TypeKind.Enum:
                builder.Keyword(SyntaxKind.EnumKeyword);
                break;

            case TypeKind.Interface:
                builder.Keyword(SyntaxKind.InterfaceKeyword);
                break;

            case TypeKind.Struct:
                if (namedType.IsReadOnly)
                {
                    builder.Keyword(SyntaxKind.ReadOnlyKeyword);
                    builder.Space();
                }
                builder.Keyword(SyntaxKind.StructKeyword);
                break;
            }

            builder.Space();

            NodeFromSymbol(builder, namedType);
            if (namedType.TypeKind == TypeKind.Delegate)
            {
                builder.Punctuation(SyntaxKind.SemicolonToken);
                builder.NewLine();
                return;
            }

            builder.Space();

            BuildBaseType(builder, namedType);

            builder.Punctuation(SyntaxKind.OpenBraceToken);
            builder.IncrementIndent();
            builder.NewLine();

            foreach (var namedTypeSymbol in SymbolOrderProvider.OrderTypes(namedType.GetTypeMembers()))
            {
                BuildType(builder, namedTypeSymbol, navigationBuilder);
            }

            foreach (var member in SymbolOrderProvider.OrderMembers(namedType.GetMembers()))
            {
                if (member.Kind == SymbolKind.NamedType || member.IsImplicitlyDeclared || !IsAccessible(member))
                {
                    continue;
                }
                if (member is IMethodSymbol method)
                {
                    if (method.MethodKind == MethodKind.PropertyGet ||
                        method.MethodKind == MethodKind.PropertySet ||
                        method.MethodKind == MethodKind.EventAdd ||
                        method.MethodKind == MethodKind.EventRemove ||
                        method.MethodKind == MethodKind.EventRaise)
                    {
                        continue;
                    }
                }
                BuildMember(builder, member);
            }

            CloseBrace(builder);
        }
コード例 #22
0
        private void BuildAttributes(CodeFileTokensBuilder builder, ImmutableArray <AttributeData> attributes)
        {
            const string attributeSuffix = "Attribute";

            foreach (var attribute in attributes)
            {
                if (!IsAccessible(attribute.AttributeClass) || IsSkippedAttribute(attribute.AttributeClass))
                {
                    continue;
                }
                builder.WriteIndent();
                builder.Punctuation(SyntaxKind.OpenBracketToken);
                var name = attribute.AttributeClass.Name;
                if (name.EndsWith(attributeSuffix))
                {
                    name = name.Substring(0, name.Length - attributeSuffix.Length);
                }
                builder.Append(name, CodeFileTokenKind.TypeName);
                if (attribute.ConstructorArguments.Any())
                {
                    builder.Punctuation(SyntaxKind.OpenParenToken);
                    bool first = true;

                    foreach (var argument in attribute.ConstructorArguments)
                    {
                        if (!first)
                        {
                            builder.Punctuation(SyntaxKind.CommaToken);
                            builder.Space();
                        }
                        else
                        {
                            first = false;
                        }
                        BuildTypedConstant(builder, argument);
                    }

                    foreach (var argument in attribute.NamedArguments)
                    {
                        if (!first)
                        {
                            builder.Punctuation(SyntaxKind.CommaToken);
                            builder.Space();
                        }
                        else
                        {
                            first = false;
                        }
                        builder.Append(argument.Key, CodeFileTokenKind.Text);
                        builder.Space();
                        builder.Punctuation(SyntaxKind.EqualsToken);
                        builder.Space();
                        BuildTypedConstant(builder, argument.Value);
                    }

                    builder.Punctuation(SyntaxKind.CloseParenToken);
                }
                builder.Punctuation(SyntaxKind.CloseBracketToken);
                builder.NewLine();
            }
        }