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); }