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 void GenerateXamlFile(string xamlFile)
        {
            var projectSourceFolder = Path.GetDirectoryName(ProjectFilePath);

            if (!Path.IsPathRooted(xamlFile))
            {
                xamlFile = Path.Combine(Path.GetDirectoryName(ProjectFilePath), xamlFile);
            }

            xamlFile = Path.GetFullPath(xamlFile);
            var sourceXmlFile = xamlFile;

            if (!File.Exists(sourceXmlFile))
            {
                return;
            }

            var relativePath = Paths.MakeRelativeToFolder(sourceXmlFile, projectSourceFolder);

            relativePath = relativePath.Replace("..", "parent");

            var destinationHtmlFile = Path.Combine(ProjectDestinationFolder, relativePath) + ".html";

            var xamlSupport = new XamlSupport(this);

            xamlSupport.GenerateXaml(sourceXmlFile, destinationHtmlFile, relativePath);

            OtherFiles.Add(relativePath);
            AddDeclaredSymbolToRedirectMap(SymbolIDToListOfLocationsMap, SymbolIdService.GetId(relativePath), relativePath, 0);
        }
        private static string GetAssemblyFromSymbol(ISymbol symbol)
        {
            ITypeSymbol type         = (ITypeSymbol)GetTypeFromSymbol(symbol);
            string      metadataName = type.MetadataName;

            if (type.ContainingNamespace != null)
            {
                var namespaceName = type.ContainingNamespace.ToDisplayString(QualifiedNameOnlyFormat);
                if (!string.IsNullOrEmpty(namespaceName))
                {
                    metadataName = namespaceName + "." + metadataName;
                }
            }

            var forwardedTo = symbol.ContainingAssembly.ResolveForwardedType(metadataName);

            if (forwardedTo != null)
            {
                symbol = forwardedTo;
            }

            var assembly = SymbolIdService.GetAssemblyId(symbol.ContainingAssembly);

            return(assembly);
        }
Beispiel #4
0
        public void GenerateBaseMembers()
        {
            Log.Write("Base members...");

            var assemblyReferencesDataFolder = Path.Combine(
                this.SolutionGenerator.SolutionDestinationFolder,
                this.AssemblyName,
                Constants.ReferencesFileName);

            Directory.CreateDirectory(assemblyReferencesDataFolder);

            lock (this.BaseMembers)
            {
                var lines = new List <string>(this.BaseMembers.Count);
                foreach (var kvp in this.BaseMembers.OrderBy(b => SymbolIdService.GetId(b.Key)))
                {
                    var fromMemberId = SymbolIdService.GetId(kvp.Key);
                    var line         =
                        fromMemberId + ";" +
                        SymbolIdService.GetAssemblyId(kvp.Value.ContainingAssembly) + ";" +
                        SymbolIdService.GetId(kvp.Value);
                    lines.Add(line);

                    // just make sure the references file for this symbol exists, so that even if symbols
                    // that aren't referenced anywhere get a reference file with a base member link if there
                    // is a base member for the symbol
                    var referencesFile = Path.Combine(assemblyReferencesDataFolder, fromMemberId + ".txt");
                    File.AppendAllText(referencesFile, "");
                }

                var fileName = Path.Combine(ProjectDestinationFolder, Constants.BaseMembersFileName + ".txt");
                File.WriteAllLines(fileName, lines);
            }
        }
Beispiel #5
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);
        }
 public DeclaredSymbolInfo(ISymbol symbol, string assemblyName = null)
 {
     ID           = SymbolIdService.GetIdULong(symbol);
     Name         = SymbolIdService.GetName(symbol);
     Kind         = SymbolKindText.GetSymbolKind(symbol);
     Description  = SymbolIdService.GetDisplayString(symbol);
     Glyph        = SymbolIdService.GetGlyphNumber(symbol);
     AssemblyName = assemblyName;
 }
        private void GenerateProjectFile()
        {
            var projectExtension = Path.GetExtension(ProjectFilePath);

            if (!File.Exists(ProjectFilePath) ||
                ".dll".Equals(projectExtension, StringComparison.OrdinalIgnoreCase) ||
                ".winmd".Equals(projectExtension, StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            ProjectCollection projectCollection = null;

            try
            {
                var title = Path.GetFileName(ProjectFilePath);
                var destinationFileName = Path.Combine(ProjectDestinationFolder, title) + ".html";

                AddDeclaredSymbolToRedirectMap(SymbolIDToListOfLocationsMap, SymbolIdService.GetId(title), title, 0);

                // ProjectCollection caches the environment variables it reads at startup
                // and doesn't re-get them later. We need a new project collection to read
                // the latest set of environment variables.
                projectCollection   = new ProjectCollection();
                this.msbuildProject = new Project(
                    ProjectFilePath,
                    null,
                    null,
                    projectCollection,
                    ProjectLoadSettings.IgnoreMissingImports);

                var msbuildSupport = new MSBuildSupport(this);
                msbuildSupport.Generate(ProjectFilePath, destinationFileName, msbuildProject, true);

                GenerateXmlFiles(msbuildProject);

                GenerateXamlFiles(msbuildProject);

                GenerateResxFiles(msbuildProject);

                GenerateTypeScriptFiles(msbuildProject);

                OtherFiles.Add(title);
            }
            catch (Exception ex)
            {
                Log.Exception("Exception during Project file generation: " + ProjectFilePath + "\r\n" + ex.ToString());
            }
            finally
            {
                if (projectCollection != null)
                {
                    projectCollection.UnloadAllProjects();
                    projectCollection.Dispose();
                }
            }
        }
Beispiel #8
0
 private void AddFileToRedirectMap(string filePath)
 {
     lock (SymbolIDToListOfLocationsMap)
     {
         SymbolIDToListOfLocationsMap.Add(
             SymbolIdService.GetId(filePath),
             new List <Tuple <string, long> > {
             Tuple.Create(filePath, 0L)
         });
     }
 }
        public HtmlElementInfo GenerateHyperlink(
            ISymbol symbol,
            string symbolId,
            SyntaxTree syntaxTree,
            out string assemblyName)
        {
            string href = null;

            assemblyName = SymbolIdService.GetAssemblyId(GetAssemblyFromSymbol(symbol));

            // if it's in a different assembly, use the URL to a redirecting file for that assembly
            if (assemblyName != Document.Project.AssemblyName)
            {
                href = GetAbsoluteLink(symbolId, assemblyName);
            }
            else // it's in the same assembly, we can just use the direct path without redirects
            {
                string referencedSymbolDestinationFilePath = null;
                if (symbol.Locations.Length > 1)
                {
                    referencedSymbolDestinationFilePath = Path.Combine(
                        SolutionDestinationFolder,
                        assemblyName,
                        Constants.PartialResolvingFileName,
                        symbolId);
                }
                else
                {
                    var referenceRelativeFilePath = Paths.GetRelativePathInProject(syntaxTree, Document.Project);
                    referencedSymbolDestinationFilePath = Path.Combine(projectGenerator.ProjectDestinationFolder, referenceRelativeFilePath);
                }

                href = Paths.MakeRelativeToFile(referencedSymbolDestinationFilePath, documentDestinationFilePath) + ".html";
                if (referencedSymbolDestinationFilePath + ".html" == documentDestinationFilePath)
                {
                    href = "";
                }
                else
                {
                    href = href.Replace('\\', '/');
                }

                href = href + "#" + symbolId;
            }

            return(new HtmlElementInfo
            {
                Name = "a",
                Attributes =
                {
                    { "href", href },
                }
            });
        }
        private void GenerateXmlFile(string filePath)
        {
            if (File.Exists(filePath = NormalizeFilePath(filePath)))
            {
                var relativePath = AddOtherFileRelativeToProject(filePath);

                var destinationHtmlFile = Path.Combine(ProjectDestinationFolder, relativePath) + ".html";
                new XmlSupport(this).Generate(filePath, destinationHtmlFile, relativePath);

                AddDeclaredSymbolToRedirectMap(SymbolIDToListOfLocationsMap, SymbolIdService.GetId(relativePath), relativePath, 0);
            }
        }
Beispiel #11
0
        private string GetProjectDestinationPath(Project project, string solutionDestinationPath)
        {
            var assemblyName = project.AssemblyName;

            if (assemblyName == "<Error>")
            {
                return(null);
            }

            AssemblyName = SymbolIdService.GetAssemblyId(assemblyName);
            string subfolder = Path.Combine(solutionDestinationPath, AssemblyName);

            return(subfolder);
        }
Beispiel #12
0
 public static IEnumerable <string> GetReferencePaths(IAssemblySymbol assemblySymbol)
 {
     foreach (var referenceIdentity in GetReferences(assemblySymbol))
     {
         var resolved = Resolve(referenceIdentity.Name);
         if (!string.IsNullOrEmpty(resolved))
         {
             yield return(resolved);
         }
         else
         {
             Log.Message(SymbolIdService.GetAssemblyId(assemblySymbol) + " references an assembly that cannot be resolved: " + referenceIdentity.Name);
         }
     }
 }
        private static string GetSymbolName(ISymbol symbol, string symbolId)
        {
            string symbolName = null;

            if (symbol != null)
            {
                symbolName = SymbolIdService.GetName(symbol);
                if (symbolName == ".ctor")
                {
                    symbolName = SymbolIdService.GetName(symbol.ContainingType) + " .ctor";
                }
            }
            else
            {
                symbolName = symbolId;
            }

            return(symbolName);
        }
        private string GetAssemblyFromSymbol(ISymbol symbol)
        {
            ITypeSymbol type         = (ITypeSymbol)GetTypeFromSymbol(symbol);
            string      metadataName = type.MetadataName;

            if (type.ContainingNamespace != null)
            {
                var namespaceName = type.ContainingNamespace.ToDisplayString(QualifiedNameOnlyFormat);
                if (!string.IsNullOrEmpty(namespaceName))
                {
                    metadataName = namespaceName + "." + metadataName;
                }
            }

            var forwardedTo = symbol.ContainingAssembly.ResolveForwardedType(metadataName);

            if (forwardedTo != null)
            {
                symbol = forwardedTo;
            }

            type = (ITypeSymbol)GetTypeFromSymbol(symbol);
            var    forwardKey = ValueTuple.Create(type.ContainingAssembly.Name, (type?.OriginalDefinition ?? type).GetDocumentationCommentId());
            string forwardedToAssembly;

            if (projectGenerator.SolutionGenerator.TypeForwards.TryGetValue(forwardKey, out forwardedToAssembly))
            {
                lock (projectGenerator.ForwardedReferenceAssemblies)
                {
                    projectGenerator.ForwardedReferenceAssemblies.Add(
                        type.ContainingAssembly.Name + "->" + forwardedToAssembly);
                }
                return(forwardedToAssembly);
            }

            var assembly = SymbolIdService.GetAssemblyId(symbol.ContainingAssembly);

            return(assembly);
        }
        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);
        }
Beispiel #16
0
        private void GenerateDeclarations()
        {
            Log.Write("Declarations...");

            var lines = new List <string>();

            if (DeclaredSymbols != null)
            {
                foreach (var declaredSymbol in DeclaredSymbols
                         .OrderBy(s => SymbolIdService.GetName(s.Key))
                         .ThenBy(s => s.Value))
                {
                    lines.Add(string.Join(";",
                                          SymbolIdService.GetName(declaredSymbol.Key),                                   // symbol name
                                          declaredSymbol.Value,                                                          // 8-byte symbol ID
                                          SymbolKindText.GetSymbolKind(declaredSymbol.Key),                              // kind (e.g. "class")
                                          Markup.EscapeSemicolons(SymbolIdService.GetDisplayString(declaredSymbol.Key)), // symbol full name and signature
                                          SymbolIdService.GetGlyphNumber(declaredSymbol.Key)));                          // icon number
                }
            }

            if (OtherFiles != null)
            {
                foreach (var document in OtherFiles.OrderBy(d => d))
                {
                    lines.Add(string.Join(";",
                                          Path.GetFileName(document),
                                          SymbolIdService.GetId(document),
                                          "file",
                                          Markup.EscapeSemicolons(document),
                                          Serialization.GetIconForExtension(document)));
                }
            }

            Serialization.WriteDeclaredSymbols(ProjectDestinationFolder, lines);
        }
        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 void Diagnostics(ClassifiedSpan classifiedSpan, SyntaxToken token, ISymbol symbol)
        {
            var tokenText = token.ToString();

            if (!(symbol is INamedTypeSymbol) ||
                classifiedSpan.ClassificationType == "t" ||
                tokenText == "this" ||
                tokenText == "base" ||
                tokenText == "var")
            {
                return;
            }

            if (tokenText == "SR" ||
                tokenText == "SR2" ||
                tokenText == "SRID" ||
                tokenText == "Strings" ||
                tokenText == "Res" ||
                tokenText == "VisualStudioVersionInfo" ||
                tokenText == "Error" ||
                tokenText == "Resource" ||
                tokenText == "Resources" ||
                tokenText == "AssemblyRef" ||
                tokenText == "ProjectResources")
            {
                return;
            }

            var symbolDisplayString = SymbolIdService.GetDisplayString(symbol);

            if (symbolDisplayString == "System.SR" ||
                symbolDisplayString == "System.Web.SR" ||
                symbolDisplayString == "ThisAssembly")
            {
                return;
            }

            if (!reportedSymbolDisplayStrings.Add(symbolDisplayString))
            {
                return;
            }

            if (reportedDiagnostics)
            {
                return;
            }

            reportedDiagnostics = true;

            string message =
                this.documentDestinationFilePath + "\r\n" +
                token.ToString() + ", " + token.Span.Start + "\r\n" +
                (classifiedSpan.ClassificationType ?? "null classification type") + "\r\n" +
                symbolDisplayString;

            var diagnostics = this.SemanticModel.GetDiagnostics().Where(d =>
            {
                var diagnostic = d.GetMessage();
                if (diagnostic.Contains("The type or namespace name 'Resources'") ||
                    diagnostic.Contains("must declare a body because it is not marked abstract"))
                {
                    return(false);
                }

                return(true);
            });

            if (diagnostics.Any())
            {
                var diagnosticsMessage = string.Join("\r\n", diagnostics.Select(d => d.ToString()));
                message = message + "\r\n" + diagnosticsMessage;
            }

            Log.Exception("Classification: " + message);
        }
Beispiel #19
0
        private string ProcessAttributeValue(ClassifiedRange range, string text, bool isRootProject)
        {
            var node            = range.Node;
            var attributeSyntax = node.GetParent(2) as XmlAttributeSyntax;

            if (attributeSyntax != null)
            {
                var parentElement = attributeSyntax.ParentElement;

                if (parentElement?.Name == "Output" &&
                    (attributeSyntax.Name == "ItemName" || attributeSyntax.Name == "PropertyName") &&
                    !text.Contains("%"))
                {
                    if (attributeSyntax.Name == "ItemName")
                    {
                        return(ProcessItemName(
                                   range.LineText,
                                   range.LineNumber + 1,
                                   range.Column,
                                   text,
                                   isRootProject,
                                   isUsage: false));
                    }
                    else
                    {
                        return(ProcessPropertyName(
                                   range.LineText,
                                   range.LineNumber + 1,
                                   range.Column,
                                   text,
                                   isRootProject,
                                   isUsage: false));
                    }
                }

                if (parentElement?.Name == "Target")
                {
                    if (attributeSyntax.Name == "Name")
                    {
                        return(ProcessTargetName(
                                   range.LineText,
                                   range.LineNumber + 1,
                                   range.Column,
                                   text,
                                   isRootProject,
                                   isUsage: false));
                    }

                    if (attributeSyntax.Name == "DependsOnTargets" ||
                        attributeSyntax.Name == "BeforeTargets" ||
                        attributeSyntax.Name == "AfterTargets")
                    {
                        return(ProcessExpressions(range, text, isRootProject, ProcessSemicolonSeparatedList));
                    }
                }

                if (parentElement?.Name == "CallTarget" && attributeSyntax.Name == "Targets")
                {
                    return(ProcessExpressions(range, text, isRootProject, ProcessSemicolonSeparatedList));
                }

                if (parentElement?.Name == "UsingTask" && attributeSyntax.Name == "TaskName")
                {
                    var    taskName = attributeSyntax.Value;
                    var    assemblyFileAttribute = parentElement.Attributes.FirstOrDefault(a => a.Name == "AssemblyFile");
                    var    assemblyNameAttribute = parentElement.Attributes.FirstOrDefault(a => a.Name == "AssemblyName");
                    string assemblyName          = null;
                    if (assemblyFileAttribute != null && !string.IsNullOrWhiteSpace(assemblyFileAttribute.Value))
                    {
                        var assemblyFilePath = assemblyFileAttribute.Value;
                        assemblyFilePath = project.ExpandString(assemblyFilePath);
                        assemblyName     = Path.GetFileNameWithoutExtension(assemblyFilePath);
                    }
                    else if (assemblyNameAttribute != null && !string.IsNullOrWhiteSpace(assemblyNameAttribute.Value))
                    {
                        assemblyName = assemblyNameAttribute.Value;
                        assemblyName = project.ExpandString(assemblyName);
                        int comma = assemblyName.IndexOf(',');
                        if (comma > -1)
                        {
                            assemblyName = assemblyName.Substring(0, comma);
                        }
                    }

                    if (assemblyName != null)
                    {
                        var symbolId = SymbolIdService.GetId("T:" + taskName);
                        ProjectGenerator.AddReference(
                            destinationHtmlFilePath,
                            range.LineText,
                            range.Column,
                            taskName.Length,
                            range.LineNumber,
                            isRootProject ? ProjectGenerator.AssemblyName : Constants.MSBuildFiles,
                            assemblyName,
                            null,
                            symbolId,
                            ReferenceKind.Instantiation);

                        var url    = string.Format("/{0}/A.html#{1}", assemblyName, symbolId);
                        var result = string.Format("<a href=\"{0}\" class=\"msbuildlink\">{1}</a>", url, text);
                        return(result);
                    }
                }
            }

            return(ProcessExpressions(range, text, isRootProject));
        }
        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);
                    }
            }
        }
Beispiel #21
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);
        }