summaryrefslogtreecommitdiff
path: root/clang-tools-extra/clangd/Hover.h
blob: 891a9d9ec55469f3f8e6fd5837c11d6ec7132575 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//===--- Hover.h - Information about code at the cursor location -*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_HOVER_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HOVER_H

#include "ParsedAST.h"
#include "Protocol.h"
#include "support/Markup.h"
#include "clang/Index/IndexSymbol.h"
#include <optional>
#include <string>
#include <vector>

namespace clang {
namespace clangd {

/// Contains detailed information about a Symbol. Especially useful when
/// generating hover responses. It can be rendered as a hover panel, or
/// embedding clients can use the structured information to provide their own
/// UI.
struct HoverInfo {
  /// Contains pretty-printed type and desugared type
  struct PrintedType {
    PrintedType() = default;
    PrintedType(const char *Type) : Type(Type) {}
    PrintedType(const char *Type, const char *AKAType)
        : Type(Type), AKA(AKAType) {}

    /// Pretty-printed type
    std::string Type;
    /// Desugared type
    std::optional<std::string> AKA;
  };

  /// Represents parameters of a function, a template or a macro.
  /// For example:
  /// - void foo(ParamType Name = DefaultValue)
  /// - #define FOO(Name)
  /// - template <ParamType Name = DefaultType> class Foo {};
  struct Param {
    /// The printable parameter type, e.g. "int", or "typename" (in
    /// TemplateParameters), might be std::nullopt for macro parameters.
    std::optional<PrintedType> Type;
    /// std::nullopt for unnamed parameters.
    std::optional<std::string> Name;
    /// std::nullopt if no default is provided.
    std::optional<std::string> Default;
  };

  /// For a variable named Bar, declared in clang::clangd::Foo::getFoo the
  /// following fields will hold:
  /// - NamespaceScope: clang::clangd::
  /// - LocalScope: Foo::getFoo::
  /// - Name: Bar

  /// Scopes might be None in cases where they don't make sense, e.g. macros and
  /// auto/decltype.
  /// Contains all of the enclosing namespaces, empty string means global
  /// namespace.
  std::optional<std::string> NamespaceScope;
  /// Remaining named contexts in symbol's qualified name, empty string means
  /// symbol is not local.
  std::string LocalScope;
  /// Name of the symbol, does not contain any "::".
  std::string Name;
  /// Header providing the symbol (best match). Contains ""<>.
  std::string Provider;
  std::optional<Range> SymRange;
  index::SymbolKind Kind = index::SymbolKind::Unknown;
  std::string Documentation;
  /// Source code containing the definition of the symbol.
  std::string Definition;
  const char *DefinitionLanguage = "cpp";
  /// Access specifier for declarations inside class/struct/unions, empty for
  /// others.
  std::string AccessSpecifier;
  /// Printable variable type.
  /// Set only for variables.
  std::optional<PrintedType> Type;
  /// Set for functions and lambdas.
  std::optional<PrintedType> ReturnType;
  /// Set for functions, lambdas and macros with parameters.
  std::optional<std::vector<Param>> Parameters;
  /// Set for all templates(function, class, variable).
  std::optional<std::vector<Param>> TemplateParameters;
  /// Contains the evaluated value of the symbol if available.
  std::optional<std::string> Value;
  /// Contains the byte-size of fields and types where it's interesting.
  std::optional<uint64_t> Size;
  /// Contains the offset of fields within the enclosing class.
  std::optional<uint64_t> Offset;
  /// Contains the padding following a field within the enclosing class.
  std::optional<uint64_t> Padding;
  // Set when symbol is inside function call. Contains information extracted
  // from the callee definition about the argument this is passed as.
  std::optional<Param> CalleeArgInfo;
  struct PassType {
    // How the variable is passed to callee.
    enum PassMode { Ref, ConstRef, Value };
    PassMode PassBy = Ref;
    // True if type conversion happened. This includes calls to implicit
    // constructor, as well as built-in type conversions. Casting to base class
    // is not considered conversion.
    bool Converted = false;
  };
  // Set only if CalleeArgInfo is set.
  std::optional<PassType> CallPassType;
  // Filled when hovering over the #include line. Contains the names of symbols
  // from a #include'd file that are used in the main file, sorted in
  // alphabetical order.
  std::vector<std::string> UsedSymbolNames;

  /// Produce a user-readable information.
  markup::Document present() const;
};

inline bool operator==(const HoverInfo::PrintedType &LHS,
                       const HoverInfo::PrintedType &RHS) {
  return std::tie(LHS.Type, LHS.AKA) == std::tie(RHS.Type, RHS.AKA);
}

inline bool operator==(const HoverInfo::PassType &LHS,
                       const HoverInfo::PassType &RHS) {
  return std::tie(LHS.PassBy, LHS.Converted) ==
         std::tie(RHS.PassBy, RHS.Converted);
}

// Try to infer structure of a documentation comment (e.g. line breaks).
// FIXME: move to another file so CodeComplete doesn't depend on Hover.
void parseDocumentation(llvm::StringRef Input, markup::Document &Output);

llvm::raw_ostream &operator<<(llvm::raw_ostream &,
                              const HoverInfo::PrintedType &);
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const HoverInfo::Param &);
inline bool operator==(const HoverInfo::Param &LHS,
                       const HoverInfo::Param &RHS) {
  return std::tie(LHS.Type, LHS.Name, LHS.Default) ==
         std::tie(RHS.Type, RHS.Name, RHS.Default);
}

/// Get the hover information when hovering at \p Pos.
std::optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
                                  const format::FormatStyle &Style,
                                  const SymbolIndex *Index);

} // namespace clangd
} // namespace clang

#endif