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); } } }
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(">"); }