175 lines · c
1//===--- Hover.h - Information about code at the cursor location -*- C++-*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_HOVER_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HOVER_H11 12#include "ParsedAST.h"13#include "Protocol.h"14#include "support/Markup.h"15#include "clang/Index/IndexSymbol.h"16#include <optional>17#include <string>18#include <vector>19 20namespace clang {21namespace clangd {22 23/// Contains detailed information about a Symbol. Especially useful when24/// generating hover responses. It can be rendered as a hover panel, or25/// embedding clients can use the structured information to provide their own26/// UI.27struct HoverInfo {28 /// Contains pretty-printed type and desugared type29 struct PrintedType {30 PrintedType() = default;31 PrintedType(const char *Type) : Type(Type) {}32 PrintedType(const char *Type, const char *AKAType)33 : Type(Type), AKA(AKAType) {}34 35 /// Pretty-printed type36 std::string Type;37 /// Desugared type38 std::optional<std::string> AKA;39 };40 41 /// Represents parameters of a function, a template or a macro.42 /// For example:43 /// - void foo(ParamType Name = DefaultValue)44 /// - #define FOO(Name)45 /// - template <ParamType Name = DefaultType> class Foo {};46 struct Param {47 /// The printable parameter type, e.g. "int", or "typename" (in48 /// TemplateParameters), might be std::nullopt for macro parameters.49 std::optional<PrintedType> Type;50 /// std::nullopt for unnamed parameters.51 std::optional<std::string> Name;52 /// std::nullopt if no default is provided.53 std::optional<std::string> Default;54 };55 56 /// For a variable named Bar, declared in clang::clangd::Foo::getFoo the57 /// following fields will hold:58 /// - NamespaceScope: clang::clangd::59 /// - LocalScope: Foo::getFoo::60 /// - Name: Bar61 62 /// Scopes might be None in cases where they don't make sense, e.g. macros and63 /// auto/decltype.64 /// Contains all of the enclosing namespaces, empty string means global65 /// namespace.66 std::optional<std::string> NamespaceScope;67 /// Remaining named contexts in symbol's qualified name, empty string means68 /// symbol is not local.69 std::string LocalScope;70 /// Name of the symbol, does not contain any "::".71 std::string Name;72 /// Header providing the symbol (best match). Contains ""<>.73 std::string Provider;74 std::optional<Range> SymRange;75 index::SymbolKind Kind = index::SymbolKind::Unknown;76 std::string Documentation;77 // required to create a comments::CommandTraits object without the ASTContext78 CommentOptions CommentOpts;79 /// Source code containing the definition of the symbol.80 std::string Definition;81 const char *DefinitionLanguage = "cpp";82 /// Access specifier for declarations inside class/struct/unions, empty for83 /// others.84 std::string AccessSpecifier;85 /// Printable variable type.86 /// Set only for variables.87 std::optional<PrintedType> Type;88 /// Set for functions and lambdas.89 std::optional<PrintedType> ReturnType;90 /// Set for functions, lambdas and macros with parameters.91 std::optional<std::vector<Param>> Parameters;92 /// Set for all templates(function, class, variable).93 std::optional<std::vector<Param>> TemplateParameters;94 /// Contains the evaluated value of the symbol if available.95 std::optional<std::string> Value;96 /// Contains the bit-size of fields and types where it's interesting.97 std::optional<uint64_t> Size;98 /// Contains the offset of fields within the enclosing class.99 std::optional<uint64_t> Offset;100 /// Contains the padding following a field within the enclosing class.101 std::optional<uint64_t> Padding;102 /// Contains the alignment of fields and types where it's interesting.103 std::optional<uint64_t> Align;104 // Set when symbol is inside function call. Contains information extracted105 // from the callee definition about the argument this is passed as.106 std::optional<Param> CalleeArgInfo;107 struct PassType {108 // How the variable is passed to callee.109 enum PassMode { Ref, ConstRef, Value };110 PassMode PassBy = Ref;111 // True if type conversion happened. This includes calls to implicit112 // constructor, as well as built-in type conversions. Casting to base class113 // is not considered conversion.114 bool Converted = false;115 };116 // Set only if CalleeArgInfo is set.117 std::optional<PassType> CallPassType;118 // Filled when hovering over the #include line. Contains the names of symbols119 // from a #include'd file that are used in the main file, sorted in120 // alphabetical order.121 std::vector<std::string> UsedSymbolNames;122 123 /// Produce a user-readable information based on the specified markup kind.124 std::string present(MarkupKind Kind) const;125 126private:127 void usedSymbolNamesToMarkup(markup::Document &Output) const;128 void providerToMarkupParagraph(markup::Document &Output) const;129 void definitionScopeToMarkup(markup::Document &Output) const;130 void calleeArgInfoToMarkupParagraph(markup::Paragraph &P) const;131 void valueToMarkupParagraph(markup::Paragraph &P) const;132 void offsetToMarkupParagraph(markup::Paragraph &P) const;133 void sizeToMarkupParagraph(markup::Paragraph &P) const;134 135 /// Parse and render the hover information as Doxygen documentation.136 markup::Document presentDoxygen() const;137 138 /// Render the hover information as a default documentation.139 markup::Document presentDefault() const;140};141 142inline bool operator==(const HoverInfo::PrintedType &LHS,143 const HoverInfo::PrintedType &RHS) {144 return std::tie(LHS.Type, LHS.AKA) == std::tie(RHS.Type, RHS.AKA);145}146 147inline bool operator==(const HoverInfo::PassType &LHS,148 const HoverInfo::PassType &RHS) {149 return std::tie(LHS.PassBy, LHS.Converted) ==150 std::tie(RHS.PassBy, RHS.Converted);151}152 153// Try to infer structure of a documentation comment (e.g. line breaks).154// FIXME: move to another file so CodeComplete doesn't depend on Hover.155void parseDocumentation(llvm::StringRef Input, markup::Document &Output);156 157llvm::raw_ostream &operator<<(llvm::raw_ostream &,158 const HoverInfo::PrintedType &);159llvm::raw_ostream &operator<<(llvm::raw_ostream &, const HoverInfo::Param &);160inline bool operator==(const HoverInfo::Param &LHS,161 const HoverInfo::Param &RHS) {162 return std::tie(LHS.Type, LHS.Name, LHS.Default) ==163 std::tie(RHS.Type, RHS.Name, RHS.Default);164}165 166/// Get the hover information when hovering at \p Pos.167std::optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,168 const format::FormatStyle &Style,169 const SymbolIndex *Index);170 171} // namespace clangd172} // namespace clang173 174#endif175