Esempio n. 1
0
        /// <summary>
        /// Two things are happening to declared symbols at the time we write the definition to HTML stream.
        /// First, the symbol is added to DeclaredSymbols (to be later written to D.txt for each project).
        /// Second, the redirect from SymbolId to local file path is added to A.txt (metadata to source redirect).
        /// </summary>
        /// <param name="declaredSymbol">Declared symbol. Can be null for files.</param>
        /// <param name="symbolId">ID of the declared symbol.</param>
        /// <param name="documentRelativeFilePath">Project-local path to the file where the symbol is defined.</param>
        /// <param name="positionInFile">Exact byte position in the HTML file stream being generated where the 16-char
        /// symbol ID starts, to later be back patched to 0000000000000000 if the symbol has no references.</param>
        public void AddDeclaredSymbol(
            ISymbol declaredSymbol,
            string symbolId,
            string documentRelativeFilePath,
            long positionInFile)
        {
            if (declaredSymbol != null)
            {
                if (declaredSymbol.Kind == SymbolKind.Local ||
                    declaredSymbol.Kind == SymbolKind.Parameter ||
                    declaredSymbol.Kind == SymbolKind.TypeParameter)
                {
                    return;
                }

                // We care about indexing even private symbols for NavigateTo
                lock (DeclaredSymbols)
                {
                    var declaredSymbolName = declaredSymbol.Name;
                    if (declaredSymbolName != ".ctor" &&
                        declaredSymbolName != ".cctor" &&
                        !DeclaredSymbols.ContainsKey(declaredSymbol))
                    {
                        DeclaredSymbols.Add(declaredSymbol, symbolId);
                    }
                }
            }

            AddDeclaredSymbolToRedirectMap(SymbolIDToListOfLocationsMap, symbolId, documentRelativeFilePath, positionInFile);
        }
Esempio n. 2
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 GenerateLinks(Classification.Range range, bool isLargeFile = false)
        {
            var text = range.Text;

            if (range.ClassificationType == Constants.ClassificationLiteral)
            {
                return(TryProcessGuid(range));
            }

            if (range.ClassificationType != Constants.ClassificationIdentifier &&
                range.ClassificationType != Constants.ClassificationTypeName &&
                text != "this" &&
                text != "base" &&
                text != "string" &&
                text != "var" &&
                text != "New" &&
                text != "new" &&
                text != "[" &&
                text != "partial" &&
                text != "Partial")
            {
                return(null);
            }

            var position = range.ClassifiedSpan.TextSpan.Start;
            var token    = Root.FindToken(position, findInsideTrivia: true);

            if (IsZeroLengthArrayAllocation(token))
            {
                projectGenerator.AddReference(
                    this.documentDestinationFilePath,
                    Text,
                    "mscorlib",
                    null,
                    "EmptyArrayAllocation",
                    range.ClassifiedSpan.TextSpan.Start,
                    range.ClassifiedSpan.TextSpan.End,
                    ReferenceKind.EmptyArrayAllocation);
                return(null);
            }

            // now that we've passed the empty array allocation check, disable all further new keywords
            if (range.ClassificationType == Constants.ClassificationKeyword && text == "new")
            {
                return(null);
            }

            var declaredSymbol = SemanticModel.GetDeclaredSymbol(token.Parent);

            if (declaredSymbol is IParameterSymbol && text == "this")
            {
                // it's a 'this' in the first parameter of an extension method - we don't want it to
                // hyperlink to anything
                return(null);
            }

            if (declaredSymbol != null)
            {
                if (token.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.PartialKeyword) ||
                    token.IsKind(Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.PartialKeyword))
                {
                    if (declaredSymbol is INamedTypeSymbol)
                    {
                        return(TryProcessPartialKeyword((INamedTypeSymbol)declaredSymbol));
                    }

                    return(null);
                }

                var explicitlyImplementedMember = GetExplicitlyImplementedMember(declaredSymbol);
                if (explicitlyImplementedMember == null)
                {
                    if (token.Span.Contains(position) &&
                        (declaredSymbol.Kind == SymbolKind.Event ||
                         declaredSymbol.Kind == SymbolKind.Field ||
                         declaredSymbol.Kind == SymbolKind.Local ||
                         declaredSymbol.Kind == SymbolKind.Method ||
                         declaredSymbol.Kind == SymbolKind.NamedType ||
                         declaredSymbol.Kind == SymbolKind.Parameter ||
                         declaredSymbol.Kind == SymbolKind.Property ||
                         declaredSymbol.Kind == SymbolKind.TypeParameter
                        ) &&
                        DeclaredSymbols.Add(declaredSymbol))
                    {
                        if ((declaredSymbol.Kind == SymbolKind.Method ||
                             declaredSymbol.Kind == SymbolKind.Property ||
                             declaredSymbol.Kind == SymbolKind.Event) &&
                            !declaredSymbol.IsStatic)
                        {
                            // declarations of overridden members are also "references" to their
                            // base members. This is needed for "Find Overridding Members" and
                            // "Find Implementations"
                            AddReferencesToOverriddenMembers(range, token, declaredSymbol);
                            AddReferencesToImplementedMembers(range, token, declaredSymbol);
                        }

                        return(ProcessDeclaredSymbol(declaredSymbol, isLargeFile));
                    }
                }
                else
                {
                    projectGenerator.AddImplementedInterfaceMember(
                        declaredSymbol,
                        explicitlyImplementedMember);
                    return(ProcessReference(
                               range,
                               explicitlyImplementedMember,
                               ReferenceKind.InterfaceMemberImplementation));
                }
            }
            else
            {
                return(ProcessReference(range, token, isLargeFile));
            }

            return(null);
        }