private string AddIdSpanForImplicitConstructorIfNecessary(HtmlElementInfo hyperlinkInfo, string html) { if (hyperlinkInfo != null && hyperlinkInfo.DeclaredSymbol != null) { INamedTypeSymbol namedTypeSymbol = hyperlinkInfo.DeclaredSymbol as INamedTypeSymbol; if (namedTypeSymbol != null) { var implicitInstanceConstructor = namedTypeSymbol.Constructors.FirstOrDefault(c => !c.IsStatic && c.IsImplicitlyDeclared); if (implicitInstanceConstructor != null) { var symbolId = SymbolIdService.GetId(implicitInstanceConstructor); html = Markup.Tag("span", html, new Dictionary <string, string> { { "id", symbolId } }); projectGenerator.AddDeclaredSymbol( implicitInstanceConstructor, symbolId, documentRelativeFilePathWithoutHtmlExtension, 0); } } } return(html); }
public HtmlElementInfo GenerateHyperlinkToReferences(ISymbol symbol, bool isLargeFile = false) { string symbolId = SymbolIdService.GetId(symbol); string referencesFilePath = Path.Combine(ProjectDestinationFolder, Constants.ReferencesFileName, symbolId + ".html"); string href = Paths.MakeRelativeToFile(referencesFilePath, documentDestinationFilePath); href = href.Replace('\\', '/'); var result = new HtmlElementInfo { Name = "a", Attributes = { { "id", symbolId }, { "href", href }, { "target", "n" }, }, DeclaredSymbol = symbol, DeclaredSymbolId = symbolId }; if (!isLargeFile) { var dataGlyph = string.Format("{0},{1}", SymbolIdService.GetGlyphNumber(symbol), GetSymbolDepth(symbol)); result.Attributes.Add("data-glyph", dataGlyph); } return result; }
public HtmlElementInfo GenerateHyperlinkToReferences(ISymbol symbol, bool isLargeFile = false) { string symbolId = SymbolIdService.GetId(symbol); string referencesFilePath = Path.Combine(ProjectDestinationFolder, Constants.ReferencesFileName, symbolId + ".html"); string href = Paths.MakeRelativeToFile(referencesFilePath, documentDestinationFilePath); href = href.Replace('\\', '/'); var result = new HtmlElementInfo { Name = "a", Attributes = { ["id"] = symbolId, ["href"] = href, ["target"] = "n", }, DeclaredSymbol = symbol, DeclaredSymbolId = symbolId }; if (!isLargeFile) { var dataGlyph = string.Format("{0},{1}", SymbolIdService.GetGlyphNumber(symbol), GetSymbolDepth(symbol)); result.Attributes.Add("data-glyph", dataGlyph); } return(result); }
private HtmlElementInfo TryProcessPartialKeyword(INamedTypeSymbol symbol) { if (symbol.Locations.Length > 1) { string symbolId = SymbolIdService.GetId(symbol); string partialFilePath = Path.Combine(ProjectDestinationFolder, Constants.PartialResolvingFileName, symbolId + ".html"); string href = Paths.MakeRelativeToFile(partialFilePath, documentDestinationFilePath); href = href.Replace('\\', '/'); var result = new HtmlElementInfo() { Name = "a", Attributes = { { "href", href }, { "target", "s" }, } }; return(result); } return(null); }
private HtmlElementInfo ProcessReference(Classification.Range range, ISymbol symbol, ReferenceKind kind, bool isLargeFile = false) { ClassifiedSpan classifiedSpan = range.ClassifiedSpan; var methodSymbol = symbol as IMethodSymbol; if (methodSymbol != null && methodSymbol.ReducedFrom != null) { symbol = methodSymbol.ReducedFrom; } HtmlElementInfo result = null; if (symbol.IsImplicitlyDeclared) { if (methodSymbol?.MethodKind == MethodKind.Constructor && symbol.ContainingSymbol != null) { return(ProcessReference(range, symbol.ContainingSymbol, ReferenceKind.Instantiation)); } } if (symbol.Kind == SymbolKind.Local || symbol.Kind == SymbolKind.Parameter || symbol.Kind == SymbolKind.TypeParameter) { if (isLargeFile) { return(null); } return(HighlightReference(symbol)); } if (methodSymbol?.MethodKind == MethodKind.Constructor && methodSymbol.ContainingType != null) { ProcessReference(range, methodSymbol.ContainingType, ReferenceKind.Instantiation); } if ((symbol.Kind == SymbolKind.Event || symbol.Kind == SymbolKind.Field || symbol.Kind == SymbolKind.Method || symbol.Kind == SymbolKind.NamedType || symbol.Kind == SymbolKind.Property) && symbol.Locations.Length >= 1) { var typeSymbol = symbol as ITypeSymbol; string symbolId = SymbolIdService.GetId(symbol); var location = symbol.Locations[0]; string destinationAssemblyName = null; if (location.IsInSource) { result = GenerateHyperlink(symbol, symbolId, location.SourceTree, out destinationAssemblyName); } else if (location.IsInMetadata && location.MetadataModule != null) { var metadataModule = location.MetadataModule; result = GenerateHyperlink(symbolId, symbol, metadataModule, isLargeFile, out destinationAssemblyName); } if (result == null) { return(result); } if (result.Attributes == null || !result.Attributes.TryGetValue("href", out string target) || !target.Contains("@")) { // only register a reference to the symbol if it's not a symbol from an external assembly. // if this links to a symbol in a different index, link target contain @. projectGenerator.AddReference( this.documentDestinationFilePath, Text, destinationAssemblyName, symbol, symbolId, classifiedSpan.TextSpan.Start, classifiedSpan.TextSpan.End, kind); } } // don't make this and var into hyperlinks in large files to save space if (isLargeFile && (range.Text == "this" || range.Text == "var")) { result = null; } return(result); }
private HtmlElementInfo TryProcessGuid(Classification.Range range) { var text = range.Text; var spanStart = range.ClassifiedSpan.TextSpan.Start; var spanEnd = range.ClassifiedSpan.TextSpan.End; if (text.StartsWith("@")) { text = text.Substring(1); spanStart++; } if (text.StartsWith("\"") && text.EndsWith("\"") && text.Length >= 2) { spanStart++; spanEnd--; text = text.Substring(1, text.Length - 2); } // quick check to reject non-Guids even before trying to parse if (text.Length != 32 && text.Length != 36 && text.Length != 38) { return(null); } if (!Guid.TryParse(text, out Guid guid)) { return(null); } var symbolId = guid.ToString(); var referencesFilePath = Path.Combine( SolutionDestinationFolder, Constants.GuidAssembly, Constants.ReferencesFileName, symbolId + ".html"); string href = Paths.MakeRelativeToFile(referencesFilePath, documentDestinationFilePath); href = href.Replace('\\', '/'); var link = new HtmlElementInfo { Name = "a", Attributes = { { "href", href }, { "target", "n" }, }, DeclaredSymbolId = symbolId }; projectGenerator.AddReference( this.documentDestinationFilePath, Text, Constants.GuidAssembly, null, symbolId, spanStart, spanEnd, ReferenceKind.GuidUsage); return(link); }
private string GenerateRange(StreamWriter writer, Classification.Range range, int lineCount = 0) { var html = range.Text; html = Markup.HtmlEscape(html); bool isLargeFile = IsLargeFile(lineCount); string classAttributeValue = GetClassAttribute(html, range); HtmlElementInfo hyperlinkInfo = GenerateLinks(range, isLargeFile); if (hyperlinkInfo == null) { if (classAttributeValue == null || isLargeFile) { return(html); } if (classAttributeValue == "k") { return("<b>" + html + "</b>"); } } var sb = new StringBuilder(); var elementName = "span"; if (hyperlinkInfo != null) { elementName = hyperlinkInfo.Name; } sb.Append("<" + elementName); bool overridingClassAttributeSpecified = false; if (hyperlinkInfo != null) { foreach (var attribute in hyperlinkInfo.Attributes) { AddAttribute(sb, attribute.Key, attribute.Value); if (attribute.Key == "class") { overridingClassAttributeSpecified = true; } } } if (!overridingClassAttributeSpecified) { AddAttribute(sb, "class", classAttributeValue); } sb.Append('>'); html = AddIdSpanForImplicitConstructorIfNecessary(hyperlinkInfo, html); sb.Append(html); sb.Append("</" + elementName + ">"); html = sb.ToString(); if (hyperlinkInfo != null && hyperlinkInfo.DeclaredSymbol != null) { writer.Flush(); long streamPosition = writer.BaseStream.Length; streamPosition += html.IndexOf(hyperlinkInfo.Attributes["id"] + ".html"); projectGenerator.AddDeclaredSymbol( hyperlinkInfo.DeclaredSymbol, hyperlinkInfo.DeclaredSymbolId, documentRelativeFilePathWithoutHtmlExtension, streamPosition); } return(html); }
private HtmlElementInfo GenerateLinks(ClassifiedRange range, string destinationHtmlFilePath, Dictionary <string, int> localSymbolIdMap) { HtmlElementInfo result = null; var localRelativePath = destinationHtmlFilePath.Substring( Path.Combine( Paths.SolutionDestinationFolder, Constants.TypeScriptFiles).Length); if (!string.IsNullOrEmpty(range.definitionSymbolId)) { var definitionSymbolId = SymbolIdService.GetId(range.definitionSymbolId); if (range.IsSymbolLocalOnly()) { var localId = GetLocalId(definitionSymbolId, localSymbolIdMap); result = new HtmlElementInfo { Name = "span", Attributes = { { "id", "r" + localId + " rd" }, { "class", "r" + localId + " r" } } }; return(result); } result = new HtmlElementInfo { Name = "a", Attributes = { { "id", definitionSymbolId }, { "href", "/TypeScriptFiles/" + Constants.ReferencesFileName + "/" + definitionSymbolId + ".html" }, { "target", "n" } } }; var searchString = range.searchString; if (!string.IsNullOrEmpty(searchString) && searchString.Length > 2) { lock (declarations) { searchString = searchString.StripQuotes(); if (IsWellFormed(searchString)) { var declaration = string.Join(";", searchString, // symbol name definitionSymbolId, // 8-byte symbol ID range.definitionKind, // kind (e.g. "class") Markup.EscapeSemicolons(range.fullName), // symbol full name and signature GetGlyph(range.definitionKind) // glyph number ); declarations.Add(declaration); } } } } if (range.hyperlinks == null || range.hyperlinks.Length == 0) { return(result); } var hyperlink = range.hyperlinks[0]; var symbolId = SymbolIdService.GetId(hyperlink.symbolId); if (range.IsSymbolLocalOnly() || localSymbolIdMap.ContainsKey(symbolId)) { var localId = GetLocalId(symbolId, localSymbolIdMap); result = new HtmlElementInfo { Name = "span", Attributes = { { "class", "r" + localId + " r" } } }; return(result); } var hyperlinkDestinationFile = Path.GetFullPath(hyperlink.sourceFile); hyperlinkDestinationFile = GetDestinationFilePath(hyperlinkDestinationFile); string href = ""; if (!string.Equals(hyperlinkDestinationFile, destinationHtmlFilePath, StringComparison.OrdinalIgnoreCase)) { href = Paths.MakeRelativeToFile(hyperlinkDestinationFile, destinationHtmlFilePath); href = href.Replace('\\', '/'); } href = href + "#" + symbolId; if (result == null) { result = new HtmlElementInfo { Name = "a", Attributes = { { "href", href }, { "target", "s" }, } }; } else if (!result.Attributes.ContainsKey("href")) { result.Attributes.Add("href", href); result.Attributes.Add("target", "s"); } lock (this.references) { var lineNumber = range.lineNumber + 1; var linkToReference = ".." + localRelativePath + "#" + lineNumber.ToString(); var start = range.column; var end = range.column + range.text.Length; var lineText = Markup.HtmlEscape(range.lineText, ref start, ref end); var reference = new Reference { FromAssemblyId = Constants.TypeScriptFiles, ToAssemblyId = Constants.TypeScriptFiles, FromLocalPath = localRelativePath.Substring(0, localRelativePath.Length - ".html".Length).Replace('\\', '/'), Kind = ReferenceKind.Reference, ToSymbolId = symbolId, ToSymbolName = range.text, ReferenceLineNumber = lineNumber, ReferenceLineText = lineText, ReferenceColumnStart = start, ReferenceColumnEnd = end, Url = linkToReference.Replace('\\', '/') }; if (!references.TryGetValue(symbolId, out List <Reference> bucket)) { bucket = new List <Reference>(); references.Add(symbolId, bucket); } bucket.Add(reference); } return(result); }
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(">"); }
private HtmlElementInfo GenerateLinks(ClassifiedRange range, string destinationHtmlFilePath, Dictionary<string, int> localSymbolIdMap) { HtmlElementInfo result = null; var localRelativePath = destinationHtmlFilePath.Substring( Path.Combine( Paths.SolutionDestinationFolder, Constants.TypeScriptFiles).Length); if (!string.IsNullOrEmpty(range.definitionSymbolId)) { var definitionSymbolId = SymbolIdService.GetId(range.definitionSymbolId); if (range.IsSymbolLocalOnly()) { var localId = GetLocalId(definitionSymbolId, localSymbolIdMap); result = new HtmlElementInfo { Name = "span", Attributes = { { "id", "r" + localId + " rd" }, { "class", "r" + localId + " r" } } }; return result; } result = new HtmlElementInfo { Name = "a", Attributes = { { "id", definitionSymbolId }, { "href", "/TypeScriptFiles/" + Constants.ReferencesFileName + "/" + definitionSymbolId + ".html" }, { "target", "n" } } }; var searchString = range.searchString; if (!string.IsNullOrEmpty(searchString) && searchString.Length > 2) { lock (declarations) { searchString = searchString.StripQuotes(); if (IsWellFormed(searchString)) { var declaration = string.Join(";", searchString, // symbol name definitionSymbolId, // 8-byte symbol ID range.definitionKind, // kind (e.g. "class") Markup.EscapeSemicolons(range.fullName), // symbol full name and signature GetGlyph(range.definitionKind) // glyph number ); declarations.Add(declaration); } } } } if (range.hyperlinks == null || range.hyperlinks.Length == 0) { return result; } var hyperlink = range.hyperlinks[0]; var symbolId = SymbolIdService.GetId(hyperlink.symbolId); if (range.IsSymbolLocalOnly() || localSymbolIdMap.ContainsKey(symbolId)) { var localId = GetLocalId(symbolId, localSymbolIdMap); result = new HtmlElementInfo { Name = "span", Attributes = { { "class", "r" + localId + " r" } } }; return result; } var hyperlinkDestinationFile = Path.GetFullPath(hyperlink.sourceFile); hyperlinkDestinationFile = GetDestinationFilePath(hyperlinkDestinationFile); string href = ""; if (!string.Equals(hyperlinkDestinationFile, destinationHtmlFilePath, StringComparison.OrdinalIgnoreCase)) { href = Paths.MakeRelativeToFile(hyperlinkDestinationFile, destinationHtmlFilePath); href = href.Replace('\\', '/'); } href = href + "#" + symbolId; if (result == null) { result = new HtmlElementInfo { Name = "a", Attributes = { { "href", href }, { "target", "s" }, } }; } else if (!result.Attributes.ContainsKey("href")) { result.Attributes.Add("href", href); result.Attributes.Add("target", "s"); } lock (this.references) { var lineNumber = range.lineNumber + 1; var linkToReference = ".." + localRelativePath + "#" + lineNumber.ToString(); var start = range.column; var end = range.column + range.text.Length; var lineText = Markup.HtmlEscape(range.lineText, ref start, ref end); var reference = new Reference { FromAssemblyId = Constants.TypeScriptFiles, ToAssemblyId = Constants.TypeScriptFiles, FromLocalPath = localRelativePath.Substring(0, localRelativePath.Length - ".html".Length).Replace('\\', '/'), Kind = ReferenceKind.Reference, ToSymbolId = symbolId, ToSymbolName = range.text, ReferenceLineNumber = lineNumber, ReferenceLineText = lineText, ReferenceColumnStart = start, ReferenceColumnEnd = end, Url = linkToReference.Replace('\\', '/') }; List<Reference> bucket = null; if (!references.TryGetValue(symbolId, out bucket)) { bucket = new List<Reference>(); references.Add(symbolId, bucket); } bucket.Add(reference); } return result; }
private string AddIdSpanForImplicitConstructorIfNecessary(HtmlElementInfo hyperlinkInfo, string html) { if (hyperlinkInfo != null && hyperlinkInfo.DeclaredSymbol != null) { INamedTypeSymbol namedTypeSymbol = hyperlinkInfo.DeclaredSymbol as INamedTypeSymbol; if (namedTypeSymbol != null) { var implicitInstanceConstructor = namedTypeSymbol.Constructors.FirstOrDefault(c => !c.IsStatic && c.IsImplicitlyDeclared); if (implicitInstanceConstructor != null) { var symbolId = SymbolIdService.GetId(implicitInstanceConstructor); html = Markup.Tag("span", html, new Dictionary<string, string> { { "id", symbolId } }); projectGenerator.AddDeclaredSymbol( implicitInstanceConstructor, symbolId, documentRelativeFilePathWithoutHtmlExtension, 0); } } } return html; }
private HtmlElementInfo TryProcessPartialKeyword(INamedTypeSymbol symbol) { if (symbol.Locations.Length > 1) { string symbolId = SymbolIdService.GetId(symbol); string partialFilePath = Path.Combine(ProjectDestinationFolder, Constants.PartialResolvingFileName, symbolId + ".html"); string href = Paths.MakeRelativeToFile(partialFilePath, documentDestinationFilePath); href = href.Replace('\\', '/'); var result = new HtmlElementInfo() { Name = "a", Attributes = { { "href", href }, { "target", "s" }, } }; return result; } return null; }
private HtmlElementInfo TryProcessGuid(Classification.Range range) { var text = range.Text; var spanStart = range.ClassifiedSpan.TextSpan.Start; var spanEnd = range.ClassifiedSpan.TextSpan.End; if (text.StartsWith("@")) { text = text.Substring(1); spanStart++; } if (text.StartsWith("\"") && text.EndsWith("\"") && text.Length >= 2) { spanStart++; spanEnd--; text = text.Substring(1, text.Length - 2); } // quick check to reject non-Guids even before trying to parse if (text.Length != 32 && text.Length != 36 && text.Length != 38) { return null; } Guid guid; if (!Guid.TryParse(text, out guid)) { return null; } var symbolId = guid.ToString(); var referencesFilePath = Path.Combine( SolutionDestinationFolder, Constants.GuidAssembly, Constants.ReferencesFileName, symbolId + ".html"); string href = Paths.MakeRelativeToFile(referencesFilePath, documentDestinationFilePath); href = href.Replace('\\', '/'); var link = new HtmlElementInfo { Name = "a", Attributes = { { "href", href }, { "target", "n" }, }, DeclaredSymbolId = symbolId }; projectGenerator.AddReference( this.documentDestinationFilePath, Text, Constants.GuidAssembly, null, symbolId, spanStart, spanEnd, ReferenceKind.GuidUsage); return link; }