public async Task Generate()
        {
            if (Configuration.CalculateRoslynSemantics)
            {
                this.Text = await Document.GetTextAsync();

                this.Root = await Document.GetSyntaxRootAsync();

                this.SemanticModel = await Document.GetSemanticModelAsync();

                this.SemanticFactsService = WorkspaceHacks.GetSemanticFactsService(this.Document);
                this.SyntaxFactsService   = WorkspaceHacks.GetSyntaxFactsService(this.Document);

                var semanticFactsServiceType = SemanticFactsService.GetType();
                var isWrittenTo = semanticFactsServiceType.GetMethod("IsWrittenTo");
                this.isWrittenToDelegate = (Func <SemanticModel, SyntaxNode, CancellationToken, bool>)
                                           Delegate.CreateDelegate(typeof(Func <SemanticModel, SyntaxNode, CancellationToken, bool>), SemanticFactsService, isWrittenTo);

                var syntaxFactsServiceType = SyntaxFactsService.GetType();
                var getBindableParent      = syntaxFactsServiceType.GetMethod("GetBindableParent");
                this.getBindableParentDelegate = (Func <SyntaxToken, SyntaxNode>)
                                                 Delegate.CreateDelegate(typeof(Func <SyntaxToken, SyntaxNode>), SyntaxFactsService, getBindableParent);

                this.DeclaredSymbols = new HashSet <ISymbol>();

                Interlocked.Increment(ref projectGenerator.DocumentCount);
                Interlocked.Add(ref projectGenerator.LinesOfCode, Text.Lines.Count);
                Interlocked.Add(ref projectGenerator.BytesOfCode, Text.Length);
            }

            CalculateDocumentDestinationPath();
            CalculateRelativePathToRoot();

            // add the file itself as a "declared symbol", so that clicking on document in search
            // results redirects to the document
            ProjectGenerator.AddDeclaredSymbolToRedirectMap(
                this.projectGenerator.SymbolIDToListOfLocationsMap,
                SymbolIdService.GetId(this.Document),
                documentRelativeFilePathWithoutHtmlExtension,
                0);

            if (File.Exists(documentDestinationFilePath))
            {
                // someone already generated this file, likely a shared linked file from elsewhere
                return;
            }

            this.classifier = new Classification();

            Log.Write(documentDestinationFilePath);

            try
            {
                var directoryName = Path.GetDirectoryName(documentDestinationFilePath);
                var sanitized     = Paths.SanitizeFolder(directoryName);
                if (directoryName != sanitized)
                {
                    Log.Exception("Illegal characters in path: " + directoryName + " Project: " + this.projectGenerator.AssemblyName);
                }

                if (Configuration.CreateFoldersOnDisk)
                {
                    Directory.CreateDirectory(directoryName);
                }
            }
            catch (PathTooLongException)
            {
                // there's one case where a path is too long - we don't care enough about it
                return;
            }

            if (Configuration.WriteDocumentsToDisk)
            {
                using (var streamWriter = new StreamWriter(
                           documentDestinationFilePath,
                           append: false,
                           encoding: Encoding.UTF8))
                {
                    await GenerateHtml(streamWriter);
                }
            }
            else
            {
                using (var memoryStream = new MemoryStream())
                    using (var streamWriter = new StreamWriter(memoryStream))
                    {
                        await GeneratePre(streamWriter);
                    }
            }
        }
예제 #2
0
        private void GenerateRange(
            StringBuilder sb,
            ClassifiedRange range,
            string destinationFilePath,
            Dictionary <string, int> localSymbolIdMap)
        {
            var html = range.text;

            html = Markup.HtmlEscape(html);

            var localRelativePath = destinationFilePath.Substring(
                Path.Combine(
                    Paths.SolutionDestinationFolder,
                    Constants.TypeScriptFiles).Length + 1);

            localRelativePath = localRelativePath.Substring(0, localRelativePath.Length - ".html".Length);

            string          classAttributeValue = GetSpanClass(range.classification);
            HtmlElementInfo hyperlinkInfo       = GenerateLinks(range, destinationFilePath, localSymbolIdMap);

            if (hyperlinkInfo == null)
            {
                if (classAttributeValue == null)
                {
                    sb.Append(html);
                    return;
                }

                if (classAttributeValue == "k")
                {
                    sb.Append("<b>").Append(html).Append("</b>");
                    return;
                }
            }

            var elementName = "span";

            if (hyperlinkInfo != null)
            {
                elementName = hyperlinkInfo.Name;
            }

            sb.Append("<").Append(elementName);
            bool overridingClassAttributeSpecified = false;

            if (hyperlinkInfo != null)
            {
                foreach (var attribute in hyperlinkInfo.Attributes)
                {
                    const string typeScriptFilesR = "/TypeScriptFiles/R/";
                    if (attribute.Key == "href" && attribute.Value.StartsWith(typeScriptFilesR, StringComparison.Ordinal))
                    {
                        var streamPosition = sb.Length + 7 + typeScriptFilesR.Length; // exact offset into <a href="HERE
                        ProjectGenerator.AddDeclaredSymbolToRedirectMap(
                            SymbolIDToListOfLocationsMap,
                            attribute.Value.Substring(typeScriptFilesR.Length, 16),
                            localRelativePath,
                            streamPosition);
                    }

                    AddAttribute(sb, attribute.Key, attribute.Value);
                    if (attribute.Key == "class")
                    {
                        overridingClassAttributeSpecified = true;
                    }
                }
            }

            if (!overridingClassAttributeSpecified)
            {
                AddAttribute(sb, "class", classAttributeValue);
            }

            sb.Append('>');

            sb.Append(html);
            sb.Append("</").Append(elementName).Append(">");
        }