Exemple #1
0
    public ExampleSyntax()
    {
        Dependencies.Add(nameof(ExampleCode));
        DependencyOf.Add(nameof(Content));

        ProcessModules = new ModuleList
        {
            new ConcatDocuments(nameof(Code)),
            new ConcatDocuments(nameof(ExampleCode)),
            new CacheDocuments(
                new AnalyzeCSharp()
                .WhereNamespaces(true)
                .WherePublic()
                .WithCssClasses("code", "cs")
                .WithDestinationPrefix("syntax")
                .WithAssemblySymbols()
                // we need to load Spectre.Console for compiling, but we don't need to process it in Statiq
                .WhereNamespaces(i => !i.StartsWith("Spectre.Console"))
                .WithImplicitInheritDoc(false),
                new ExecuteConfig(Config.FromDocument((doc, _) =>
            {
                // Add metadata
                var metadataItems = new MetadataItems
                {
                    // Calculate an xref that includes a "api-" prefix to avoid collisions
                    { WebKeys.Xref, "syntax-" + doc.GetString(CodeAnalysisKeys.CommentId) },
                };

                var contentProvider = doc.ContentProvider;
                return(doc.Clone(metadataItems, contentProvider));
            }))).WithoutSourceMapping()
        };
    }
Exemple #2
0
    public Api()
    {
        Dependencies.Add(nameof(Code));
        DependencyOf.Add(nameof(Content));

        ProcessModules = new ModuleList
        {
            new ConcatDocuments(nameof(Code)),
            new CacheDocuments(
                new AnalyzeCSharp()
                .WhereNamespaces(ns => ns.StartsWith("Spectre.Console") && !ns.Contains("Analyzer") &&
                                 !ns.Contains("Testing") && !ns.Contains("Examples"))
                .WherePublic(true)
                .WithCssClasses("code", "cs")
                .WithDestinationPrefix("api")
                .WithAssemblySymbols()
                .WithImplicitInheritDoc(false),
                new ExecuteConfig(Config.FromDocument((doc, ctx) =>
            {
                // Calculate a type name to link lookup for auto linking
                string name = null;

                var kind = doc.GetString(CodeAnalysisKeys.Kind);
                switch (kind)
                {
                case "NamedType":
                    name = doc.GetString(CodeAnalysisKeys.DisplayName);
                    break;

                case "Method":
                    var containingType = doc.GetDocument(CodeAnalysisKeys.ContainingType);
                    if (containingType != null)
                    {
                        name =
                            $"{containingType.GetString(CodeAnalysisKeys.DisplayName)}.{doc.GetString(CodeAnalysisKeys.DisplayName)}";
                    }
                    break;
                }

                if (name != null)
                {
                    var typeNameLinks = ctx.GetRequiredService <TypeNameLinks>();
                    typeNameLinks.Links.AddOrUpdate(WebUtility.HtmlEncode(name), ctx.GetLink(doc),
                                                    (_, _) => string.Empty);
                }

                // Add metadata
                var metadataItems = new MetadataItems
                {
                    { WebKeys.Xref, doc.GetString(CodeAnalysisKeys.CommentId) },
                    { WebKeys.Layout, "api/_layout.cshtml" },
                    { Constants.Hidden, true }
                };

                var contentProvider = doc.ContentProvider.CloneWithMediaType(MediaTypes.Html);
                metadataItems.Add(WebKeys.ContentType, ContentType.Content);
                return(doc.Clone(metadataItems, contentProvider));
            }))).WithoutSourceMapping()
        };
    }
Exemple #3
0
        private void AddXmlDocumentation(ISymbol symbol, MetadataItems metadata)
        {
            string documentationCommentXml = symbol.GetDocumentationCommentXml(expandIncludes: true);
            XmlDocumentationParser xmlDocumentationParser
                = new XmlDocumentationParser(symbol, _commentIdToDocument, _cssClasses);
            IEnumerable <string> otherHtmlElementNames = xmlDocumentationParser.Parse(documentationCommentXml);

            // Add standard HTML elements
            metadata.AddRange(new []
            {
                new MetadataItem(CodeAnalysisKeys.CommentXml, documentationCommentXml),
                new MetadataItem(CodeAnalysisKeys.Example, (k, m) => xmlDocumentationParser.Process().Example),
                new MetadataItem(CodeAnalysisKeys.Remarks, (k, m) => xmlDocumentationParser.Process().Remarks),
                new MetadataItem(CodeAnalysisKeys.Summary, (k, m) => xmlDocumentationParser.Process().Summary),
                new MetadataItem(CodeAnalysisKeys.Returns, (k, m) => xmlDocumentationParser.Process().Returns),
                new MetadataItem(CodeAnalysisKeys.Value, (k, m) => xmlDocumentationParser.Process().Value),
                new MetadataItem(CodeAnalysisKeys.Exceptions, (k, m) => xmlDocumentationParser.Process().Exceptions),
                new MetadataItem(CodeAnalysisKeys.Permissions, (k, m) => xmlDocumentationParser.Process().Permissions),
                new MetadataItem(CodeAnalysisKeys.Params, (k, m) => xmlDocumentationParser.Process().Params),
                new MetadataItem(CodeAnalysisKeys.TypeParams, (k, m) => xmlDocumentationParser.Process().TypeParams),
                new MetadataItem(CodeAnalysisKeys.SeeAlso, (k, m) => xmlDocumentationParser.Process().SeeAlso)
            });

            // Add other HTML elements with keys of [ElementName]Html
            metadata.AddRange(otherHtmlElementNames.Select(x =>
                                                           new MetadataItem(FirstLetterToUpper(x) + "Comments",
                                                                            (k, m) => xmlDocumentationParser.Process().OtherComments[x])));
        }
Exemple #4
0
            // We need to build the tree from the bottom up so that the children don't have to be lazy
            // This also sorts the children once they're created
            public void GenerateOutputDocuments(Tree tree, IExecutionContext context)
            {
                // Recursively build output documents for children
                foreach (TreeNode child in Children)
                {
                    child.GenerateOutputDocuments(tree, context);
                }

                // We're done if we've already created the output document
                if (OutputDocument != null)
                {
                    return;
                }

                // Sort the child documents since they're created now
                Children.Sort((x, y) => tree._sort(x.OutputDocument, y.OutputDocument));

                // Create this output document
                MetadataItems metadata = new MetadataItems();

                if (tree._childrenKey != null)
                {
                    metadata.Add(tree._childrenKey, new ReadOnlyCollection <IDocument>(Children.Select(x => x.OutputDocument).ToArray()));
                }
                if (tree._parentKey != null)
                {
                    metadata.Add(tree._parentKey, new CachedDelegateMetadataValue(_ => Parent?.OutputDocument));
                }
                if (tree._previousSiblingKey != null)
                {
                    metadata.Add(tree._previousSiblingKey, new CachedDelegateMetadataValue(_ => GetPreviousSibling()?.OutputDocument));
                }
                if (tree._nextSiblingKey != null)
                {
                    metadata.Add(tree._nextSiblingKey, new CachedDelegateMetadataValue(_ => GetNextSibling()?.OutputDocument));
                }
                if (tree._previousKey != null)
                {
                    metadata.Add(tree._previousKey, new CachedDelegateMetadataValue(_ => GetPrevious()?.OutputDocument));
                }
                if (tree._nextKey != null)
                {
                    metadata.Add(tree._nextKey, new CachedDelegateMetadataValue(_ => GetNext()?.OutputDocument));
                }
                if (tree._treePathKey != null)
                {
                    metadata.Add(tree._treePathKey, TreePath);
                }
                if (InputDocument == null)
                {
                    // There's no input document for this node so we need to make a placeholder
                    metadata.Add(Keys.TreePlaceholder, true);
                    OutputDocument = tree._placeholderFactory(TreePath, metadata, context) ?? context.GetDocument(metadata);
                }
                else
                {
                    OutputDocument = context.GetDocument(InputDocument, metadata);
                }
            }
Exemple #5
0
 internal void AddMetadataItem(MetadataItem item)
 {
     if (MetadataItems == null)
     {
         MetadataItems = new List <MetadataItem>();
     }
     MetadataItems.Add(item);
 }
Exemple #6
0
        private static IDocument TreePlaceholderFactory(object[] path, MetadataItems items, IExecutionContext context)
        {
            FilePath indexPath = new FilePath(string.Join("/", path.Concat(new[] { "index.html" })));

            items.Add(Keys.RelativeFilePath, indexPath);
            items.Add(Keys.Title, Title.GetTitle(indexPath));
            return(context.GetDocument(context.GetContentStream("@Html.Partial(\"_ChildPages\")"), items));
        }
Exemple #7
0
 private IDocument AddMemberDocument(ISymbol symbol, bool xmlDocumentation, MetadataItems items)
 {
     items.AddRange(new[]
     {
         new MetadataItem(CodeAnalysisKeys.ContainingType, DocumentFor(symbol.ContainingType))
     });
     return(AddDocument(symbol, xmlDocumentation, items));
 }
Exemple #8
0
        private IDocument Write(IDocument input, IExecutionContext context, FilePath outputPath)
        {
            IFile output = context.FileSystem.GetOutputFile(outputPath);

            if (output != null)
            {
                using (Stream inputStream = input.GetStream())
                {
                    if (_ignoreEmptyContent && inputStream.Length == 0)
                    {
                        return(input);
                    }
                    if (!_onlyMetadata)
                    {
                        using (Stream outputStream = _append ? output.OpenAppend() : output.OpenWrite())
                        {
                            inputStream.CopyTo(outputStream);
                            if (!_append)
                            {
                                outputStream.SetLength(inputStream.Length);
                            }
                        }
                    }
                }
                Trace.Verbose($"{(_onlyMetadata ? "Set metadata for" : "Wrote")} file {output.Path.FullPath} from {input.SourceString()}");
                FilePath      relativePath             = context.FileSystem.GetOutputPath().GetRelativePath(output.Path) ?? output.Path.FileName;
                FilePath      fileNameWithoutExtension = output.Path.FileNameWithoutExtension;
                MetadataItems metadata = new MetadataItems
                {
                    { Keys.RelativeFilePath, relativePath },
                    { Keys.RelativeFilePathBase, fileNameWithoutExtension == null
                        ? null : relativePath.Directory.CombineFile(output.Path.FileNameWithoutExtension) },
                    { Keys.RelativeFileDir, relativePath.Directory }
                };
                if (_onlyMetadata)
                {
                    metadata.Add(Keys.WritePath, outputPath);
                }
                else
                {
                    metadata.AddRange(new MetadataItems
                    {
                        { Keys.DestinationFileBase, fileNameWithoutExtension },
                        { Keys.DestinationFileExt, output.Path.Extension },
                        { Keys.DestinationFileName, output.Path.FileName },
                        { Keys.DestinationFileDir, output.Path.Directory },
                        { Keys.DestinationFilePath, output.Path },
                        { Keys.DestinationFilePathBase, fileNameWithoutExtension == null
                            ? null : output.Path.Directory.CombineFile(output.Path.FileNameWithoutExtension) },
                    });
                }
                return(_onlyMetadata
                    ? context.GetDocument(input, metadata)
                    : context.GetDocument(input, output.OpenRead(), metadata));
            }
            return(input);
        }
Exemple #9
0
        private void AddDocument(ISymbol symbol, bool xmlDocumentation, MetadataItems items)
        {
            // Get universal metadata
            items.AddRange(new []
            {
                // In general, cache the values that need calculation and don't cache the ones that are just properties of ISymbol
                new MetadataItem(CodeAnalysisKeys.IsResult, !_finished),
                new MetadataItem(CodeAnalysisKeys.SymbolId, (k, m) => GetId(symbol), true),
                new MetadataItem(CodeAnalysisKeys.Symbol, symbol),
                new MetadataItem(CodeAnalysisKeys.Name, (k, m) => symbol.Name),
                new MetadataItem(CodeAnalysisKeys.FullName, (k, m) => GetFullName(symbol), true),
                new MetadataItem(CodeAnalysisKeys.DisplayName, (k, m) => GetDisplayName(symbol), true),
                new MetadataItem(CodeAnalysisKeys.QualifiedName, (k, m) => GetQualifiedName(symbol), true),
                new MetadataItem(CodeAnalysisKeys.Kind, (k, m) => symbol.Kind.ToString()),
                new MetadataItem(CodeAnalysisKeys.ContainingNamespace, DocumentFor(symbol.ContainingNamespace)),
                new MetadataItem(CodeAnalysisKeys.Syntax, (k, m) => GetSyntax(symbol), true)
            });

            // Add metadata that's specific to initially-processed symbols
            if (!_finished)
            {
                items.AddRange(new[]
                {
                    new MetadataItem(Keys.WritePath, (k, m) => _writePath(m), true),
                    new MetadataItem(Keys.RelativeFilePath, (k, m) => m.FilePath(Keys.WritePath)),
                    new MetadataItem(Keys.RelativeFilePathBase, (k, m) =>
                    {
                        FilePath writePath = m.FilePath(Keys.WritePath);
                        return(writePath.Directory.CombineFile(writePath.FileNameWithoutExtension));
                    }),
                    new MetadataItem(Keys.RelativeFileDir, (k, m) => m.FilePath(Keys.WritePath).Directory)
                });
            }

            // XML Documentation
            if (xmlDocumentation && (!_finished || _docsForImplicitSymbols))
            {
                AddXmlDocumentation(symbol, items);
            }

            // Create the document and add it to the cache
            IDocument document = _context.GetDocument(new FilePath(NormalizedPath.AbstractProvider, symbol.ToDisplayString(), true), null, items);

            _symbolToDocument.GetOrAdd(symbol, _ => document);

            // Map the comment ID to the document
            if (!_finished)
            {
                string documentationCommentId = symbol.GetDocumentationCommentId();
                if (documentationCommentId != null)
                {
                    _commentIdToDocument.GetOrAdd(documentationCommentId, _ => document);
                }
            }
        }
Exemple #10
0
        private IDocument AddDocumentCommon(ISymbol symbol, bool xmlDocumentation, MetadataItems items)
        {
            // Get universal metadata
            string commentId = symbol.GetDocumentationCommentId();

            items.AddRange(new[]
            {
                // In general, cache the values that need calculation and don't cache the ones that are just properties of ISymbol
                new MetadataItem(CodeAnalysisKeys.IsResult, !_finished),
                new MetadataItem(CodeAnalysisKeys.SymbolId, _ => GetId(symbol), true),
                new MetadataItem(CodeAnalysisKeys.CommentId, commentId),
                new MetadataItem(CodeAnalysisKeys.Name, metadata => string.IsNullOrEmpty(symbol.Name) ? metadata.String(CodeAnalysisKeys.FullName) : symbol.Name),
                new MetadataItem(CodeAnalysisKeys.FullName, _ => GetFullName(symbol), true),
                new MetadataItem(CodeAnalysisKeys.DisplayName, _ => GetDisplayName(symbol), true),
                new MetadataItem(CodeAnalysisKeys.QualifiedName, _ => GetQualifiedName(symbol), true),
                new MetadataItem(CodeAnalysisKeys.Kind, _ => symbol.Kind.ToString()),
                new MetadataItem(CodeAnalysisKeys.ContainingNamespace, DocumentFor(symbol.ContainingNamespace)),
                new MetadataItem(CodeAnalysisKeys.Syntax, _ => GetSyntax(symbol), true),
                new MetadataItem(CodeAnalysisKeys.IsStatic, _ => symbol.IsStatic),
                new MetadataItem(CodeAnalysisKeys.IsAbstract, _ => symbol.IsAbstract),
                new MetadataItem(CodeAnalysisKeys.IsVirtual, _ => symbol.IsVirtual),
                new MetadataItem(CodeAnalysisKeys.IsOverride, _ => symbol.IsOverride),
                new MetadataItem(CodeAnalysisKeys.OriginalDefinition, DocumentFor(GetOriginalSymbolDefinition(symbol)))
            });

            // Add metadata that's specific to initially-processed symbols
            if (!_finished)
            {
                items.AddRange(new[]
                {
                    new MetadataItem(Keys.WritePath, x => _writePath(x), true),
                    new MetadataItem(Keys.RelativeFilePath, x => x.FilePath(Keys.WritePath)),
                    new MetadataItem(Keys.RelativeFilePathBase, x =>
                    {
                        FilePath writePath = x.FilePath(Keys.WritePath);
                        return(writePath.Directory.CombineFile(writePath.FileNameWithoutExtension));
                    }),
                    new MetadataItem(Keys.RelativeFileDir, x => x.FilePath(Keys.WritePath).Directory)
                });
            }

            // XML Documentation
            if (xmlDocumentation && (!_finished || _docsForImplicitSymbols))
            {
                AddXmlDocumentation(symbol, items);
            }

            // Create the document and add it to caches
            IDocument document = _symbolToDocument.GetOrAdd(
                symbol,
                _ => _context.GetDocument(new FilePath((Uri)null, symbol.ToDisplayString(), PathKind.Absolute), (Stream)null, items));

            return(document);
        }
        /// <inheritdoc />
        protected override IEnumerable <IDocument> ExecuteContext(IExecutionContext context)
        {
            // Partition the pages and get a total before skip/take
            IDocument[][] pages =
                Partition(context.Inputs, _pageSize)
                .ToArray();

            // Skip/take the pages
            pages = pages
                    .Skip(_skipPages)
                    .Take(_takePages)
                    .ToArray();

            // Special case for no pages, create an empty one
            if (pages.Length == 0)
            {
                pages = new[] { Array.Empty <IDocument>() };
            }

            // Create the documents per page, setting previous and next values as we go
            Stack <(IDocument, LazyDocumentMetadataValue)> results = new Stack <(IDocument, LazyDocumentMetadataValue)>();

            for (int c = 0; c < pages.Length; c++)
            {
                MetadataItems items = new MetadataItems
                {
                    { Keys.Children, pages[c] },
                    { Keys.Index, c + 1 },
                    { Keys.TotalPages, pages.Length },
                    { Keys.TotalItems, context.Inputs.Length }
                };
                if (results.Count > 0)
                {
                    items.Add(Keys.Previous, new LazyDocumentMetadataValue(results.Peek().Item1));
                }
                LazyDocumentMetadataValue next = null;
                if (c < pages.Length - 1)
                {
                    next = new LazyDocumentMetadataValue();
                    items.Add(Keys.Next, next);
                }
                IDocument document = context.CreateDocument(
                    _source,
                    _source.IsNull ? _source : _source.GetRelativeInputPath(),
                    items);
                if (results.Count > 0)
                {
                    results.Peek().Item2.OriginalDocument = document;
                }
                results.Push((document, next));
            }

            return(results.Select(x => x.Item1).Reverse());
        }
Exemple #12
0
            public void ReturnsNullWhenKeyNotFound()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems();
                IMetadata     metadata        = new Metadata(initialMetadata);

                // When
                IEnumerable <IDocument> result = metadata.GetDocuments("A");

                // Then
                result.ShouldBeNull();
            }
Exemple #13
0
            public void ReturnsEmptyListWhenKeyNotFound()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems();
                IMetadata     metadata        = new Metadata(initialMetadata);

                // When
                DocumentList <IDocument> result = metadata.GetDocumentList("A");

                // Then
                Assert.IsEmpty(result);
            }
Exemple #14
0
            public void CanCloneWithNewValues()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems();
                Metadata      metadata        = new Metadata(initialMetadata);

                // When
                metadata = new Metadata(metadata, new[] { new KeyValuePair <string, object>("A", "a") });

                // Then
                Assert.AreEqual("a", metadata["A"]);
            }
        public override bool Execute()
        {
            StringBuilder builder = new StringBuilder();

            // we always generate global configs
            builder.AppendLine("is_global = true");

            // collect the properties into a global section
            foreach (var prop in PropertyItems)
            {
                builder
                .Append("build_property.")
                .Append(prop.ItemSpec)
                .Append(" = ")
                .AppendLine(prop.GetMetadata("Value"));
            }

            // group the metadata items by their full path
            var groupedItems = MetadataItems.GroupBy(
                i => NormalizeWithForwardSlash(i.GetMetadata("FullPath"))
                );

            foreach (var group in groupedItems)
            {
                // write the section for this item
                builder.AppendLine().Append("[");
                EncodeString(builder, group.Key);
                builder.AppendLine("]");

                foreach (var item in group)
                {
                    string itemType     = item.GetMetadata("ItemType");
                    string metadataName = item.GetMetadata("MetadataName");
                    if (
                        !string.IsNullOrWhiteSpace(itemType) &&
                        !string.IsNullOrWhiteSpace(metadataName)
                        )
                    {
                        builder
                        .Append("build_metadata.")
                        .Append(itemType)
                        .Append(".")
                        .Append(metadataName)
                        .Append(" = ")
                        .AppendLine(item.GetMetadata(metadataName));
                    }
                }
            }

            ConfigFileContents = builder.ToString();
            return(true);
        }
Exemple #16
0
        private static void AddImage(MetadataItems metadata, IAsset?asset)
        {
            if (asset == null)
            {
                return;
            }

            var localPath = KontentAssetHelper.GetLocalFileName(asset.Url + "?w=800&h=800", "img");
            var download  = new KontentImageDownload(asset.Url, localPath);

            metadata.Add(FeedKeys.Image, localPath);
            metadata.Add("KONTENT-ASSET-DOWNLOADS", download); // TODO : an upcoming version of Kontent.Statiq will provide this key
        }
Exemple #17
0
            public void ReturnsCorrectDirectoryPathForDirectoryPath(string path, string expected)
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems();
                IMetadata     metadata        = new Metadata(initialMetadata);

                // When
                metadata = new Metadata(metadata, new[] { new KeyValuePair <string, object>("A", new NormalizedPath(path)) });
                NormalizedPath result = metadata.GetPath("A");

                // Then
                result.FullPath.ShouldBe(expected);
            }
Exemple #18
0
            public void ReturnsTrueForSameKeysWithDifferentCase()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems {
                    { "A", "a" }
                };
                Metadata metadata = new Metadata(initialMetadata);

                // When
                bool contains = metadata.ContainsKey("a");

                // Then
                Assert.IsTrue(contains);
            }
Exemple #19
0
        private IDocument AddNamespaceDocument(INamespaceSymbol symbol, bool xmlDocumentation)
        {
            string        displayName = GetDisplayName(symbol);
            MetadataItems items       = new MetadataItems
            {
                { CodeAnalysisKeys.Symbol, _ => _namespaceDisplayNameToSymbols[displayName].ToImmutableList() },
                { CodeAnalysisKeys.SpecificKind, _ => symbol.Kind.ToString() },
                // We need to aggregate the results across all matching namespaces
                { CodeAnalysisKeys.MemberNamespaces, DocumentsFor(_namespaceDisplayNameToSymbols[displayName].SelectMany(x => x.GetNamespaceMembers())) },
                { CodeAnalysisKeys.MemberTypes, DocumentsFor(_namespaceDisplayNameToSymbols[displayName].SelectMany(x => x.GetTypeMembers())) }
            };

            return(AddDocumentCommon(symbol, xmlDocumentation, items));
        }
Exemple #20
0
            public void ReturnsCorrectFilePathForFilePath(string path, string expected)
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems();
                IMetadata     metadata        = new Metadata(initialMetadata);

                // When
                metadata = new Metadata(metadata, new[] { new KeyValuePair <string, object>("A", new FilePath(path)) });
                object result = metadata.GetFilePath("A");

                // Then
                Assert.IsInstanceOf <FilePath>(result);
                Assert.AreEqual(expected, ((FilePath)result).FullPath);
            }
        public override void VisitNamedType(INamedTypeSymbol symbol)
        {
            // Only visit the original definition until we're finished
            INamedTypeSymbol originalDefinition = GetOriginalSymbolDefinition(symbol);

            if (!_finished && !SymbolEqualityComparer.Default.Equals(originalDefinition, symbol))
            {
                VisitNamedType(originalDefinition);
                return;
            }

            if (ShouldIncludeSymbol(symbol))
            {
                MetadataItems metadata = new MetadataItems
                {
                    { CodeAnalysisKeys.SpecificKind, _ => symbol.TypeKind.ToString() },
                    { CodeAnalysisKeys.ContainingType, DocumentFor(symbol.ContainingType) },
                    { CodeAnalysisKeys.MemberTypes, DocumentsFor(symbol.GetTypeMembers()) },
                    { CodeAnalysisKeys.BaseTypes, DocumentsFor(GetBaseTypes(symbol)) },
                    { CodeAnalysisKeys.AllInterfaces, DocumentsFor(symbol.AllInterfaces) },
                    { CodeAnalysisKeys.Members, DocumentsFor(GetAccessibleMembersInThisAndBaseTypes(symbol, symbol).Where(MemberPredicate)) },
                    { CodeAnalysisKeys.Operators, DocumentsFor(GetAccessibleMembersInThisAndBaseTypes(symbol, symbol).Where(OperatorPredicate)) },
                    { CodeAnalysisKeys.ExtensionMethods, _ => DocumentsFor(_extensionMethods.Where(x => x.ReduceExtensionMethod(symbol) != null)) },
                    { CodeAnalysisKeys.Constructors, DocumentsFor(symbol.Constructors.Where(x => !x.IsImplicitlyDeclared)) },
                    { CodeAnalysisKeys.TypeParameters, DocumentsFor(symbol.TypeParameters) },
                    { CodeAnalysisKeys.TypeArguments, DocumentsFor(symbol.TypeArguments) },
                    { CodeAnalysisKeys.Accessibility, _ => symbol.DeclaredAccessibility.ToString() },
                    { CodeAnalysisKeys.Attributes, GetAttributeDocuments(symbol) }
                };
                if (!_finished)
                {
                    metadata.AddRange(new[]
                    {
                        new MetadataItem(CodeAnalysisKeys.DerivedTypes, _ => GetDerivedTypes(symbol), true),
                        new MetadataItem(CodeAnalysisKeys.ImplementingTypes, _ => GetImplementingTypes(symbol), true)
                    });
                }
                AddDocumentCommon(symbol, true, metadata);

                // Descend if not finished, and only if this type was included
                if (!_finished)
                {
                    Parallel.ForEach(
                        symbol.GetMembers()
                        .Where(MemberPredicate)
                        .Concat(symbol.Constructors.Where(x => !x.IsImplicitlyDeclared)),
                        s => s.Accept(this));
                }
            }
        }
Exemple #22
0
            public void ReturnsTrueForValidValue()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems {
                    { "A", "a" }
                };
                Metadata metadata = new Metadata(initialMetadata);

                // When
                bool contains = metadata.ContainsKey("A");

                // Then
                Assert.IsTrue(contains);
            }
Exemple #23
0
            public void ReturnsCorrectStringForDirectoryPath(string path, string expected)
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems();
                IMetadata     metadata        = new Metadata(initialMetadata);

                // When
                metadata = new Metadata(metadata, new[] { new KeyValuePair <string, object>("A", new NormalizedPath(path)) });
                object result = metadata.GetString("A");

                // Then
                Assert.IsInstanceOf <string>(result);
                Assert.AreEqual(expected, result);
            }
Exemple #24
0
            public void GetWithMetadataValueReturnsCorrectResult()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems {
                    { "A", "a" }
                };
                IMetadata metadata = new Metadata(initialMetadata);

                // When
                object value = metadata.Get("A");

                // Then
                Assert.AreEqual("a", value);
            }
Exemple #25
0
        // Used for everything but namespace documents
        private IDocument AddDocument(ISymbol symbol, bool xmlDocumentation, MetadataItems items)
        {
            items.AddRange(new[]
            {
                new MetadataItem(CodeAnalysisKeys.Symbol, symbol)
            });

            // Add the containing assembly, but only if it's not the code analysis compilation
            if (symbol.ContainingAssembly?.Name != AnalyzeCSharp.CompilationAssemblyName && _assemblySymbols)
            {
                items.Add(new MetadataItem(CodeAnalysisKeys.ContainingAssembly, DocumentFor(symbol.ContainingAssembly)));
            }

            return(AddDocumentCommon(symbol, xmlDocumentation, items));
        }
Exemple #26
0
            public void ReturnsEmptyListForSingleInt()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems {
                    { "A", 1 }
                };
                IMetadata metadata = new Metadata(initialMetadata);

                // When
                DocumentList <IDocument> result = metadata.GetDocumentList("A");

                // Then
                Assert.IsNotNull(result);
                CollectionAssert.IsEmpty(result);
            }
Exemple #27
0
            public void MissingKeyThrowsKeyNotFoundException()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems();
                Metadata      metadata        = new Metadata(initialMetadata);

                // When
                TestDelegate test = () =>
                {
                    object value = metadata["A"];
                };

                // Then
                Assert.Throws <KeyNotFoundException>(test);
            }
Exemple #28
0
            public void ReturnsCorrectResultForArray()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems {
                    { "A", new[] { 1, 2, 3 } }
                };
                IMetadata metadata = new Metadata(initialMetadata);

                // When
                IReadOnlyList <int> result = metadata.GetList <int>("A");

                // Then
                Assert.IsNotNull(result);
                CollectionAssert.AreEqual(result, new[] { 1, 2, 3 });
            }
Exemple #29
0
            public void NullKeyThrowsKeyNotFoundException()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems();
                Metadata      metadata        = new Metadata(initialMetadata);

                // When
                TestDelegate test = () =>
                {
                    object value = metadata[null];
                };

                // Then
                Assert.Throws <ArgumentNullException>(test);
            }
Exemple #30
0
            public void ContainsNewValues()
            {
                // Given
                MetadataItems initialMetadata = new MetadataItems {
                    { "A", "a" }
                };
                Metadata metadata = new Metadata(initialMetadata);

                // When
                Metadata clone = new Metadata(metadata, new Dictionary <string, object> {
                    { "B", "b" }
                });

                // Then
                Assert.AreEqual("b", clone["B"]);
            }
        private void AddDocument(ISymbol symbol, bool xmlDocumentation, MetadataItems items)
        {
            // Get universal metadata
            items.AddRange(new []
            {
                // In general, cache the values that need calculation and don't cache the ones that are just properties of ISymbol
                new MetadataItem(CodeAnalysisKeys.IsResult, !_finished),
                new MetadataItem(CodeAnalysisKeys.SymbolId, (k, m) => GetId(symbol), true),
                new MetadataItem(CodeAnalysisKeys.Symbol, symbol),
                new MetadataItem(CodeAnalysisKeys.Name, (k, m) => symbol.Name),
                new MetadataItem(CodeAnalysisKeys.FullName, (k, m) => GetFullName(symbol), true),
                new MetadataItem(CodeAnalysisKeys.DisplayName, (k, m) => GetDisplayName(symbol), true),
                new MetadataItem(CodeAnalysisKeys.QualifiedName, (k, m) => GetQualifiedName(symbol), true),
                new MetadataItem(CodeAnalysisKeys.Kind, (k, m) => symbol.Kind.ToString()),
                new MetadataItem(CodeAnalysisKeys.ContainingNamespace, DocumentFor(symbol.ContainingNamespace)),
                new MetadataItem(CodeAnalysisKeys.Syntax, (k, m) => GetSyntax(symbol), true)
            });

            // Add metadata that's specific to initially-processed symbols
            if (!_finished)
            {
                items.AddRange(new[]
                {
                    new MetadataItem(Keys.WritePath, (k, m) => _writePath(m), true),
                    new MetadataItem(Keys.RelativeFilePath, 
                        (k, m) => m.String(Keys.WritePath)),
                    new MetadataItem(Keys.RelativeFilePathBase, 
                        (k, m) => PathHelper.RemoveExtension(m.String(Keys.WritePath))),
                    new MetadataItem(Keys.RelativeFileDir, 
                        (k, m) => Path.GetDirectoryName(m.String(Keys.WritePath)))
                });
            }

            // XML Documentation
            if (xmlDocumentation && (!_finished || _docsForImplicitSymbols))
            {
                AddXmlDocumentation(symbol, items);
            }

            // Create the document and add it to the cache
            IDocument document = _context.GetNewDocument(symbol.ToDisplayString(), null, items);
            _symbolToDocument.GetOrAdd(symbol, _ => document);

            // Map the comment ID to the document
            if (!_finished)
            {
                string documentationCommentId = symbol.GetDocumentationCommentId();
                if (documentationCommentId != null)
                {
                    _commentIdToDocument.GetOrAdd(documentationCommentId, _ => document);
                }
            }
        }
 private void AddDocumentForMember(ISymbol symbol, bool xmlDocumentation, MetadataItems items)
 {
     items.AddRange(new[]
     {
         new MetadataItem(CodeAnalysisKeys.ContainingType, DocumentFor(symbol.ContainingType))
     });
     AddDocument(symbol, xmlDocumentation, items);
 }
        private void AddXmlDocumentation(ISymbol symbol, MetadataItems metadata)
        {
            string documentationCommentXml = symbol.GetDocumentationCommentXml(expandIncludes: true);
            XmlDocumentationParser xmlDocumentationParser
                = new XmlDocumentationParser(symbol, _commentIdToDocument, _cssClasses, _context.Trace);
            IEnumerable<string> otherHtmlElementNames = xmlDocumentationParser.Parse(documentationCommentXml);

            // Add standard HTML elements
            metadata.AddRange(new []
            {
                new MetadataItem(CodeAnalysisKeys.CommentXml, documentationCommentXml),
                new MetadataItem(CodeAnalysisKeys.Example, (k, m) => xmlDocumentationParser.Process().Example),
                new MetadataItem(CodeAnalysisKeys.Remarks, (k, m) => xmlDocumentationParser.Process().Remarks),
                new MetadataItem(CodeAnalysisKeys.Summary, (k, m) => xmlDocumentationParser.Process().Summary),
                new MetadataItem(CodeAnalysisKeys.Returns, (k, m) => xmlDocumentationParser.Process().Returns),
                new MetadataItem(CodeAnalysisKeys.Value, (k, m) => xmlDocumentationParser.Process().Value),
                new MetadataItem(CodeAnalysisKeys.Exceptions, (k, m) => xmlDocumentationParser.Process().Exceptions),
                new MetadataItem(CodeAnalysisKeys.Permissions, (k, m) => xmlDocumentationParser.Process().Permissions),
                new MetadataItem(CodeAnalysisKeys.Params, (k, m) => xmlDocumentationParser.Process().Params),
                new MetadataItem(CodeAnalysisKeys.TypeParams, (k, m) => xmlDocumentationParser.Process().TypeParams),
                new MetadataItem(CodeAnalysisKeys.SeeAlso, (k, m) => xmlDocumentationParser.Process().SeeAlso)
            });

            // Add other HTML elements with keys of [ElementName]Html
            metadata.AddRange(otherHtmlElementNames.Select(x => 
                new MetadataItem(FirstLetterToUpper(x) + "Comments",
                    (k, m) => xmlDocumentationParser.Process().OtherComments[x])));
        }
        public override void VisitNamedType(INamedTypeSymbol symbol)
        {
            if (_finished || _symbolPredicate == null || _symbolPredicate(symbol))
            {
                MetadataItems metadata = new MetadataItems
                {
                    { CodeAnalysisKeys.SpecificKind, (k, m) => symbol.TypeKind.ToString() },
                    { CodeAnalysisKeys.ContainingType, DocumentFor(symbol.ContainingType) },
                    { CodeAnalysisKeys.MemberTypes, DocumentsFor(symbol.GetTypeMembers()) },
                    { CodeAnalysisKeys.BaseType, DocumentFor(symbol.BaseType) },
                    { CodeAnalysisKeys.AllInterfaces, DocumentsFor(symbol.AllInterfaces) },
                    { CodeAnalysisKeys.Members, DocumentsFor(symbol.GetMembers().Where(MemberPredicate)) },
                    { CodeAnalysisKeys.Constructors,
                        DocumentsFor(symbol.Constructors.Where(x => !x.IsImplicitlyDeclared)) },
                    { CodeAnalysisKeys.TypeParameters, DocumentsFor(symbol.TypeParameters) },
                    { CodeAnalysisKeys.Accessibility, (k, m) => symbol.DeclaredAccessibility.ToString() }
                };
                if (!_finished)
                {
                    metadata.AddRange(new []
                    {
                        new MetadataItem(CodeAnalysisKeys.DerivedTypes, (k, m) => GetDerivedTypes(symbol), true),
                        new MetadataItem(CodeAnalysisKeys.ImplementingTypes, (k, m) => GetImplementingTypes(symbol), true)
                    });
                }
                AddDocument(symbol, true, metadata);

                // Descend if not finished, and only if this type was included
                if (!_finished)
                {
                    Parallel.ForEach(symbol.GetMembers()
                        .Where(MemberPredicate)
                        .Concat(symbol.Constructors.Where(x => !x.IsImplicitlyDeclared)),
                        s => s.Accept(this));
                }
            }
        }
Exemple #35
0
 private IDocument Write(IDocument input, IExecutionContext context, FilePath outputPath)
 {
     IFile output = context.FileSystem.GetOutputFile(outputPath);
     if (output != null)
     {
         using (Stream inputStream = input.GetStream())
         {
             if (_ignoreEmptyContent && inputStream.Length == 0)
             {
                 return input;
             }
             if (!_onlyMetadata)
             {
                 using (Stream outputStream = _append ? output.OpenAppend() : output.OpenWrite())
                 {
                     inputStream.CopyTo(outputStream);
                 }
             }
         }
         Trace.Verbose($"{(_onlyMetadata ? "Set metadata for" : "Wrote")} file {output.Path.FullPath} from {input.SourceString()}");
         FilePath relativePath = context.FileSystem.GetOutputPath().GetRelativePath(output.Path) ?? output.Path.FileName;
         FilePath fileNameWithoutExtension = output.Path.FileNameWithoutExtension;
         MetadataItems metadata = new MetadataItems
         {
             { Keys.RelativeFilePath, relativePath },
             { Keys.RelativeFilePathBase, fileNameWithoutExtension == null
                 ? null : relativePath.Directory.CombineFile(output.Path.FileNameWithoutExtension) },
             { Keys.RelativeFileDir, relativePath.Directory }
         };
         if (_onlyMetadata)
         {
             metadata.Add(Keys.WritePath, outputPath);
         }
         else
         {
             metadata.AddRange(new MetadataItems
             {
                 { Keys.DestinationFileBase, fileNameWithoutExtension },
                 { Keys.DestinationFileExt, output.Path.Extension },
                 { Keys.DestinationFileName, output.Path.FileName },
                 { Keys.DestinationFileDir, output.Path.Directory },
                 { Keys.DestinationFilePath, output.Path },
                 { Keys.DestinationFilePathBase, fileNameWithoutExtension == null
                     ? null : output.Path.Directory.CombineFile(output.Path.FileNameWithoutExtension) },
             });
         }
         return _onlyMetadata
             ? context.GetDocument(input, metadata)
             : context.GetDocument(input, output.OpenRead(), metadata);
     }
     return input;
 }