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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_HOVER_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HOVER_H
11 
12 #include "ParsedAST.h"
13 #include "Protocol.h"
14 #include "support/Markup.h"
15 #include "clang/Index/IndexSymbol.h"
16 
17 namespace clang {
18 namespace clangd {
19 
20 /// Contains detailed information about a Symbol. Especially useful when
21 /// generating hover responses. It can be rendered as a hover panel, or
22 /// embedding clients can use the structured information to provide their own
23 /// UI.
24 struct HoverInfo {
25   /// Contains pretty-printed type and desugared type
26   struct PrintedType {
27     PrintedType() = default;
PrintedTypeHoverInfo::PrintedType28     PrintedType(const char *Type) : Type(Type) {}
PrintedTypeHoverInfo::PrintedType29     PrintedType(const char *Type, const char *AKAType)
30         : Type(Type), AKA(AKAType) {}
31 
32     /// Pretty-printed type
33     std::string Type;
34     /// Desugared type
35     llvm::Optional<std::string> AKA;
36   };
37 
38   /// Represents parameters of a function, a template or a macro.
39   /// For example:
40   /// - void foo(ParamType Name = DefaultValue)
41   /// - #define FOO(Name)
42   /// - template <ParamType Name = DefaultType> class Foo {};
43   struct Param {
44     /// The printable parameter type, e.g. "int", or "typename" (in
45     /// TemplateParameters), might be None for macro parameters.
46     llvm::Optional<PrintedType> Type;
47     /// None for unnamed parameters.
48     llvm::Optional<std::string> Name;
49     /// None if no default is provided.
50     llvm::Optional<std::string> Default;
51   };
52 
53   /// For a variable named Bar, declared in clang::clangd::Foo::getFoo the
54   /// following fields will hold:
55   /// - NamespaceScope: clang::clangd::
56   /// - LocalScope: Foo::getFoo::
57   /// - Name: Bar
58 
59   /// Scopes might be None in cases where they don't make sense, e.g. macros and
60   /// auto/decltype.
61   /// Contains all of the enclosing namespaces, empty string means global
62   /// namespace.
63   llvm::Optional<std::string> NamespaceScope;
64   /// Remaining named contexts in symbol's qualified name, empty string means
65   /// symbol is not local.
66   std::string LocalScope;
67   /// Name of the symbol, does not contain any "::".
68   std::string Name;
69   llvm::Optional<Range> SymRange;
70   index::SymbolKind Kind = index::SymbolKind::Unknown;
71   std::string Documentation;
72   /// Source code containing the definition of the symbol.
73   std::string Definition;
74   const char *DefinitionLanguage = "cpp";
75   /// Access specifier for declarations inside class/struct/unions, empty for
76   /// others.
77   std::string AccessSpecifier;
78   /// Printable variable type.
79   /// Set only for variables.
80   llvm::Optional<PrintedType> Type;
81   /// Set for functions and lambdas.
82   llvm::Optional<PrintedType> ReturnType;
83   /// Set for functions, lambdas and macros with parameters.
84   llvm::Optional<std::vector<Param>> Parameters;
85   /// Set for all templates(function, class, variable).
86   llvm::Optional<std::vector<Param>> TemplateParameters;
87   /// Contains the evaluated value of the symbol if available.
88   llvm::Optional<std::string> Value;
89   /// Contains the byte-size of fields and types where it's interesting.
90   llvm::Optional<uint64_t> Size;
91   /// Contains the offset of fields within the enclosing class.
92   llvm::Optional<uint64_t> Offset;
93   /// Contains the padding following a field within the enclosing class.
94   llvm::Optional<uint64_t> Padding;
95   // Set when symbol is inside function call. Contains information extracted
96   // from the callee definition about the argument this is passed as.
97   llvm::Optional<Param> CalleeArgInfo;
98   struct PassType {
99     // How the variable is passed to callee.
100     enum PassMode { Ref, ConstRef, Value };
101     PassMode PassBy = Ref;
102     // True if type conversion happened. This includes calls to implicit
103     // constructor, as well as built-in type conversions. Casting to base class
104     // is not considered conversion.
105     bool Converted = false;
106   };
107   // Set only if CalleeArgInfo is set.
108   llvm::Optional<PassType> CallPassType;
109 
110   /// Produce a user-readable information.
111   markup::Document present() const;
112 };
113 
114 inline bool operator==(const HoverInfo::PrintedType &LHS,
115                        const HoverInfo::PrintedType &RHS) {
116   return std::tie(LHS.Type, LHS.AKA) == std::tie(RHS.Type, RHS.AKA);
117 }
118 
119 inline bool operator==(const HoverInfo::PassType &LHS,
120                        const HoverInfo::PassType &RHS) {
121   return std::tie(LHS.PassBy, LHS.Converted) ==
122          std::tie(RHS.PassBy, RHS.Converted);
123 }
124 
125 // Try to infer structure of a documentation comment (e.g. line breaks).
126 // FIXME: move to another file so CodeComplete doesn't depend on Hover.
127 void parseDocumentation(llvm::StringRef Input, markup::Document &Output);
128 
129 llvm::raw_ostream &operator<<(llvm::raw_ostream &,
130                               const HoverInfo::PrintedType &);
131 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const HoverInfo::Param &);
132 inline bool operator==(const HoverInfo::Param &LHS,
133                        const HoverInfo::Param &RHS) {
134   return std::tie(LHS.Type, LHS.Name, LHS.Default) ==
135          std::tie(RHS.Type, RHS.Name, RHS.Default);
136 }
137 
138 /// Get the hover information when hovering at \p Pos.
139 llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
140                                    const format::FormatStyle &Style,
141                                    const SymbolIndex *Index);
142 
143 } // namespace clangd
144 } // namespace clang
145 
146 #endif
147