public async Task <QuickInfoResult> QuickInfo(IEnumerable <UnsavedFile> unsavedFiles, int offset)
        {
            var dataAssociation = GetAssociatedData(_editor);

            var workspace = RoslynWorkspace.GetWorkspace(dataAssociation.Solution);

            var document = GetDocument(dataAssociation, _editor.SourceFile, workspace);

            var semanticModel = await document.GetSemanticModelAsync();

            var descriptionService = workspace.Services.GetLanguageServices(semanticModel.Language).GetService <ISymbolDisplayService>();

            var root = semanticModel.SyntaxTree.GetRoot(CancellationToken.None);

            SyntaxToken syntaxToken;

            try
            {
                syntaxToken = root.FindToken(offset);
            }
            catch (ArgumentOutOfRangeException)
            {
                return(null);
            }

            if (!syntaxToken.Span.IntersectsWith(offset))
            {
                return(null);
            }

            var node = GetBestFitResolveableNode(syntaxToken.Parent);

            var symbolInfo = semanticModel.GetSymbolInfo(node, CancellationToken.None);

            var symbol = symbolInfo.Symbol ?? semanticModel.GetDeclaredSymbol(node, CancellationToken.None);

            if (symbol != null)
            {
                var sections = await descriptionService.ToDescriptionGroupsAsync(workspace, semanticModel, offset, new[] { symbol }.AsImmutable(), default(CancellationToken)).ConfigureAwait(false);

                ImmutableArray <TaggedText> parts;

                var styledText = StyledText.Create();
                var theme      = ColorScheme.CurrentColorScheme;


                if (sections.TryGetValue(SymbolDescriptionGroups.MainDescription, out parts))
                {
                    TaggedTextUtil.AppendTaggedText(styledText, theme, parts);
                }

                // if generating quick info for an attribute, bind to the class instead of the constructor
                if (symbol.ContainingType?.IsAttribute() == true)
                {
                    symbol = symbol.ContainingType;
                }

                var formatter     = workspace.Services.GetLanguageServices(semanticModel.Language).GetService <IDocumentationCommentFormattingService>();
                var documentation = symbol.GetDocumentationParts(semanticModel, offset, formatter, CancellationToken.None);

                if (documentation != null && documentation.Any())
                {
                    styledText.AppendLine();
                    TaggedTextUtil.AppendTaggedText(styledText, theme, documentation);
                }

                if (sections.TryGetValue(SymbolDescriptionGroups.AnonymousTypes, out parts))
                {
                    if (!parts.IsDefaultOrEmpty)
                    {
                        styledText.AppendLine();
                        TaggedTextUtil.AppendTaggedText(styledText, theme, parts);
                    }
                }

                if (sections.TryGetValue(SymbolDescriptionGroups.AwaitableUsageText, out parts))
                {
                    if (!parts.IsDefaultOrEmpty)
                    {
                        styledText.AppendLine();
                        TaggedTextUtil.AppendTaggedText(styledText, theme, parts);
                    }
                }

                if (sections.TryGetValue(SymbolDescriptionGroups.Exceptions, out parts))
                {
                    if (!parts.IsDefaultOrEmpty)
                    {
                        styledText.AppendLine();
                        TaggedTextUtil.AppendTaggedText(styledText, theme, parts);
                    }
                }

                if (sections.TryGetValue(SymbolDescriptionGroups.Captures, out parts))
                {
                    if (!parts.IsDefaultOrEmpty)
                    {
                        styledText.AppendLine();
                        TaggedTextUtil.AppendTaggedText(styledText, theme, parts);
                    }
                }

                return(new QuickInfoResult(styledText));
            }

            return(null);
        }
        private static StyledText InfoTextFromCursor(ClangCursor cursor)
        {
            var result = StyledText.Create();

            string     name = "";
            CursorKind kind = (CursorKind)cursor.Kind;

            switch (cursor.Kind)
            {
            case NClang.CursorKind.CXXAccessSpecifier:
                name = "(Access Specifier) " + cursor.CxxAccessSpecifier;
                break;

            default:
                name = cursor.Spelling;
                break;
            }

            var theme = ColorScheme.CurrentColorScheme;

            if (cursor.Kind == NClang.CursorKind.VarDeclaration)
            {
                switch (cursor.Linkage)
                {
                case NClang.LinkageKind.NoLinkage:
                    result.Append("(local variable) ");
                    break;

                case NClang.LinkageKind.Internal:
                    result.Append("(static variable) ");
                    break;

                case NClang.LinkageKind.External:
                    result.Append("(global variable) ");
                    break;
                }
            }

            switch (cursor.CxxAccessSpecifier)
            {
            case CXXAccessSpecifier.Private:
                result.Append("(private) ");
                break;

            case CXXAccessSpecifier.Protected:
                result.Append("(protected) ");
                break;

            case CXXAccessSpecifier.Public:
                result.Append("(public) ");
                break;
            }

            if (cursor.ResultType != null)
            {
                result.Append(cursor.ResultType.Spelling + " ", IsBuiltInType(cursor.ResultType) ? theme.Keyword : theme.Type);
            }
            else if (cursor.CursorType != null)
            {
                switch (kind)
                {
                case CursorKind.ClassDeclaration:
                case CursorKind.CXXThisExpression:
                    result.Append("class ", theme.Keyword);
                    break;

                case CursorKind.Namespace:
                    result.Append("namespace ", theme.Keyword);
                    break;

                case CursorKind.TypedefDeclaration:
                    result.Append("typedef ", theme.Keyword);
                    break;

                case CursorKind.EnumDeclaration:
                    result.Append("enum ", theme.Keyword);
                    break;

                case CursorKind.StructDeclaration:
                    result.Append("struct ", theme.Keyword);
                    break;

                case CursorKind.UnionDeclaration:
                    result.Append("union ", theme.Keyword);
                    break;
                }

                result.Append(cursor.CursorType.Spelling + " ", IsBuiltInType(cursor.ResultType) ? theme.Keyword : theme.Type);
            }

            switch (kind)
            {
            case CursorKind.UnionDeclaration:
            case CursorKind.TypedefDeclaration:
            case CursorKind.StructDeclaration:
            case CursorKind.ClassDeclaration:
            case CursorKind.CXXThisExpression:
            case CursorKind.Namespace:
            case CursorKind.EnumDeclaration:
                break;

            default:
                result.Append(name);
                break;
            }

            string parsedDocumentation = "";

            switch (kind)
            {
            case CursorKind.EnumConstantDeclaration:
                result.Append(" = " + cursor.EnumConstantDeclUnsignedValue.ToString());
                result.Append(" (0x" + cursor.EnumConstantDeclUnsignedValue.ToString("X") + ")");
                break;

            case CursorKind.FunctionDeclaration:
            case CursorKind.CXXMethod:
            case CursorKind.Constructor:
            case CursorKind.Destructor:
                result.Append(" (");

                for (var i = 0; i < cursor.ArgumentCount; i++)
                {
                    var argument = cursor.GetArgument(i);

                    result.Append(argument.CursorType.Spelling + " ", IsBuiltInType(argument.CursorType) ? theme.Keyword : theme.Type);

                    result.Append(argument.Spelling + (i == cursor.ArgumentCount - 1 ? "" : ", "));
                }

                if (cursor.IsVariadic)
                {
                    result.Append(", ... variadic");
                }

                if (cursor.ArgumentCount == 0)
                {
                    result.Append("void", theme.Keyword);
                }

                result.Append(")");

                if (cursor.ParsedComment.FullCommentAsXml != null)
                {
                    var documentation = XDocument.Parse(cursor.ParsedComment.FullCommentAsXml);

                    var function = documentation.Element("Function");

                    var parameters = function.Element("Parameters");

                    if (parameters != null)
                    {
                        var arguments = parameters.Elements("Parameter");

                        foreach (var argument in arguments)
                        {
                            var isVarArgs = argument.Element("IsVarArg");

                            var discussion = argument.Element("Discussion");

                            var paragraph = discussion.Element("Para");

                            if (paragraph != null)
                            {
                                if (isVarArgs != null)
                                {
                                    parsedDocumentation += paragraph.Value + Environment.NewLine;
                                }
                                else
                                {
                                    var inx = argument.Element("Index");

                                    if (inx != null)
                                    {
                                        parsedDocumentation += paragraph.Value + Environment.NewLine;
                                    }
                                }
                            }
                        }
                    }
                }
                break;
            }

            if (cursor.BriefCommentText != null || !string.IsNullOrEmpty(parsedDocumentation))
            {
                result.AppendLine();

                if (cursor.BriefCommentText != null)
                {
                    result.AppendLine(cursor.BriefCommentText);
                }

                if (!string.IsNullOrEmpty(parsedDocumentation))
                {
                    result.Append(parsedDocumentation);
                }
            }

            return(result);
        }