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;
        }
Example #3
0
        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);
        }
Example #8
0
        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);
        }
Example #9
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(">");
        }
        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;
        }