Skip to content

Commit c437020

Browse files
authored
Enable inlay hints (#183)
1 parent 41d5ac1 commit c437020

File tree

25 files changed

+2534
-861
lines changed

25 files changed

+2534
-861
lines changed

include/AST/Utility.h

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,71 +12,58 @@ bool is_definition(const clang::Decl* decl);
1212
/// we consider it as a template while clang does not.
1313
bool is_templated(const clang::Decl* decl);
1414

15+
/// Check whether the decl is anonymous.
16+
bool is_anonymous(const clang::NamedDecl* decl);
17+
1518
/// Return the decl where it is instantiated from. If could be a template decl
1619
/// or a member of a class template. If the decl is a full specialization, return
1720
/// itself.
1821
const clang::NamedDecl* instantiated_from(const clang::NamedDecl* decl);
1922

2023
const clang::NamedDecl* normalize(const clang::NamedDecl* decl);
2124

25+
llvm::StringRef identifier_of(const clang::NamedDecl& D);
26+
27+
llvm::StringRef identifier_of(clang::QualType T);
28+
2229
/// Get the name of the decl.
2330
std::string name_of(const clang::NamedDecl* decl);
2431

32+
std::string display_name_of(const clang::NamedDecl* decl);
33+
2534
/// To response go-to-type-definition request. Some decls actually have a type
2635
/// for example the result of `typeof(var)` is the type of `var`. This function
2736
/// returns the type for the decl if any.
2837
clang::QualType type_of(const clang::NamedDecl* decl);
2938

30-
const clang::NamedDecl* get_decl_for_type(const clang::Type* T);
31-
3239
/// Get the underlying decl for a type if any.
33-
const clang::NamedDecl* decl_of(clang::QualType type);
34-
35-
/// Check whether the decl is anonymous.
36-
bool is_anonymous(const clang::NamedDecl* decl);
37-
38-
clang::NestedNameSpecifierLoc get_qualifier_loc(const clang::NamedDecl* decl);
39-
40-
auto get_template_specialization_args(const clang::NamedDecl* decl)
41-
-> std::optional<llvm::ArrayRef<clang::TemplateArgumentLoc>>;
40+
auto decl_of(clang::QualType type) -> const clang::NamedDecl*;
4241

43-
std::string print_template_specialization_args(const clang::NamedDecl* decl);
42+
/// Recursively strips all pointers, references, and array extents from
43+
/// a TypeLoc. e.g., for "const int*(&)[3]", the result will be location
44+
/// "for int".
45+
auto unwrap_type(clang::TypeLoc type, bool unwrap_function_type = true) -> clang::TypeLoc;
4446

45-
std::string print_name(const clang::NamedDecl* decl);
47+
auto get_only_instantiation(clang::NamedDecl* templated_decl) -> clang::NamedDecl*;
4648

47-
clang::TemplateTypeParmTypeLoc get_contained_auto_param_type(clang::TypeLoc TL);
49+
auto get_only_instantiation(clang::ParmVarDecl* param) -> clang::ParmVarDecl*;
4850

49-
clang::NamedDecl* get_only_instantiation(clang::NamedDecl* TemplatedDecl);
50-
51-
/// getSimpleName() returns the plain identifier for an entity, if any.
52-
llvm::StringRef getSimpleName(const clang::DeclarationName& DN);
53-
llvm::StringRef getSimpleName(const clang::NamedDecl& D);
54-
llvm::StringRef getSimpleName(clang::QualType T);
55-
56-
std::string summarizeExpr(const clang::Expr* E);
57-
58-
// Returns the template parameter pack type from an instantiated function
59-
// template, if it exists, nullptr otherwise.
60-
const clang::TemplateTypeParmType* getFunctionPackType(const clang::FunctionDecl* Callee);
51+
std::string summarize_expr(const clang::Expr* E);
6152

6253
// Returns the template parameter pack type that this parameter was expanded
6354
// from (if in the Args... or Args&... or Args&&... form), if this is the case,
6455
// nullptr otherwise.
65-
const clang::TemplateTypeParmType* getUnderlyingPackType(const clang::ParmVarDecl* Param);
56+
const clang::TemplateTypeParmType* underlying_pack_type(const clang::ParmVarDecl* param);
6657

6758
// Returns the parameters that are forwarded from the template parameters.
6859
// For example, `template <typename... Args> void foo(Args... args)` will return
6960
// the `args` parameters.
70-
llvm::SmallVector<const clang::ParmVarDecl*>
71-
resolveForwardingParameters(const clang::FunctionDecl* D, unsigned MaxDepth = 10);
72-
73-
// Determines if any intermediate type in desugaring QualType QT is of
74-
// substituted template parameter type. Ignore pointer or reference wrappers.
75-
bool isSugaredTemplateParameter(clang::QualType QT);
61+
auto resolve_forwarding_params(const clang::FunctionDecl* decl, unsigned max_depth = 10)
62+
-> llvm::SmallVector<const clang::ParmVarDecl*>;
7663

7764
// A simple wrapper for `clang::desugarForDiagnostic` that provides optional
7865
// semantic.
79-
std::optional<clang::QualType> desugar(clang::ASTContext& AST, clang::QualType QT);
66+
std::optional<clang::QualType> desugar(clang::ASTContext& context, clang::QualType type);
8067

8168
// Apply a series of heuristic methods to determine whether or not a QualType QT
8269
// is suitable for desugaring (e.g. getting the real name behind the using-alias
@@ -85,12 +72,12 @@ std::optional<clang::QualType> desugar(clang::ASTContext& AST, clang::QualType Q
8572
//
8673
// This could be refined further. See
8774
// https://github.com/clangd/clangd/issues/1298.
88-
clang::QualType maybeDesugar(clang::ASTContext& AST, clang::QualType QT);
75+
clang::QualType maybe_desugar(clang::ASTContext& context, clang::QualType type);
8976

9077
// Given a callee expression `Fn`, if the call is through a function pointer,
9178
// try to find the declaration of the corresponding function pointer type,
9279
// so that we can recover argument names from it.
9380
// FIXME: This function is mostly duplicated in SemaCodeComplete.cpp; unify.
94-
clang::FunctionProtoTypeLoc getPrototypeLoc(clang::Expr* Fn);
81+
clang::FunctionProtoTypeLoc proto_type_loc(clang::Expr* expr);
9582

9683
} // namespace clice::ast

include/Async/Task.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,10 +317,10 @@ class Task {
317317
void stacktrace() {
318318
promise_base* handle = core;
319319
while(handle) {
320-
clice::println("{}:{}:{}",
321-
handle->location.file_name(),
322-
handle->location.line(),
323-
handle->location.function_name());
320+
std::println("{}:{}:{}",
321+
handle->location.file_name(),
322+
handle->location.line(),
323+
handle->location.function_name());
324324
handle = handle->continuation;
325325
}
326326
}

include/Compiler/CompilationUnit.h

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,21 +122,32 @@ class CompilationUnit {
122122
/// Create a file location with given file id and offset.
123123
auto create_location(clang::FileID fid, std::uint32_t offset) -> clang::SourceLocation;
124124

125+
using TokenRange = llvm::ArrayRef<clang::syntax::Token>;
126+
125127
/// Get the spelled tokens(raw token) of the file id.
126-
auto spelled_tokens(clang::FileID fid) -> llvm::ArrayRef<clang::syntax::Token>;
128+
auto spelled_tokens(clang::FileID fid) -> TokenRange;
129+
130+
/// Return the spelled tokens corresponding to the range.
131+
auto spelled_tokens(clang::SourceRange range) -> TokenRange;
127132

128133
/// The spelled tokens that overlap or touch a spelling location Loc.
129134
/// This always returns 0-2 tokens.
130-
auto spelled_tokens_touch(clang::SourceLocation location)
131-
-> llvm::ArrayRef<clang::syntax::Token>;
132-
133-
auto expanded_tokens() -> llvm::ArrayRef<clang::syntax::Token>;
134-
135-
/// Get the expanded tokens(after preprocessing) of the file id.
136-
auto expanded_tokens(clang::SourceRange range) -> llvm::ArrayRef<clang::syntax::Token>;
137-
138-
auto expansions_overlapping(llvm::ArrayRef<clang::syntax::Token>)
139-
-> std::vector<clang::syntax::TokenBuffer::Expansion>;
135+
auto spelled_tokens_touch(clang::SourceLocation location) -> TokenRange;
136+
137+
/// All tokens produced by the preprocessor after all macro replacements,
138+
/// directives, etc. Source locations found in the clang AST will always
139+
/// point to one of these tokens.
140+
/// Tokens are in TU order (per SourceManager::isBeforeInTranslationUnit()).
141+
/// FIXME: figure out how to handle token splitting, e.g. '>>' can be split
142+
/// into two '>' tokens by the parser. However, TokenBuffer currently
143+
/// keeps it as a single '>>' token.
144+
auto expanded_tokens() -> TokenRange;
145+
146+
/// Returns the subrange of expandedTokens() corresponding to the closed
147+
/// token range R.
148+
auto expanded_tokens(clang::SourceRange range) -> TokenRange;
149+
150+
auto expansions_overlapping(TokenRange) -> std::vector<clang::syntax::TokenBuffer::Expansion>;
140151

141152
/// Get the token length.
142153
auto token_length(clang::SourceLocation location) -> std::uint32_t;

include/Feature/InlayHint.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ struct InlayHint {
5050
std::vector<index::SymbolID> parts;
5151
};
5252

53-
using InlayHints = std::vector<InlayHint>;
54-
55-
InlayHints inlay_hints(CompilationUnit& unit, LocalSourceRange target);
53+
auto inlay_hint(CompilationUnit& unit,
54+
LocalSourceRange target,
55+
const config::InlayHintsOptions& options) -> std::vector<InlayHint>;
5656

5757
} // namespace clice::feature

include/Protocol/Feature/InlayHint.h

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,71 @@
44

55
namespace clice::proto {
66

7-
struct InlayHintClientCapabilities {};
7+
struct InlayHintClientCapabilities {
8+
/// Indicates which properties a client can resolve lazily on an inlay hint.
9+
struct {
10+
/// The properties that a client can resolve lazily.
11+
array<string> properties;
12+
} resolveSupport;
13+
};
814

915
struct InlayHintOptions {
1016
/// The server provides support to resolve additional
1117
/// information for an inlay hint item.
1218
bool resolveProvider;
1319
};
1420

21+
struct InlayHintParams {
22+
/// The text document.
23+
TextDocumentIdentifier textDocument;
24+
25+
/// The visible document range for which inlay hints should be computed.
26+
Range range;
27+
};
28+
29+
enum class InlayHintKind {
30+
/// An inlay hint that for a type annotation.
31+
Type = 1,
32+
33+
/// An inlay hint that is for a parameter.
34+
Parameter = 2,
35+
};
36+
37+
struct InlayHintLabelPart {
38+
/// The value of this label part.
39+
string value;
40+
41+
/// An optional source code location that represents this
42+
/// label part.
43+
///
44+
/// The editor will use this location for the hover and for code navigation
45+
/// features: This part will become a clickable link that resolves to the
46+
/// definition of the symbol at the given location (not necessarily the
47+
/// location itself), it shows the hover that shows at the given location,
48+
/// and it shows a context menu with further code navigation commands.
49+
///
50+
/// Depending on the client capability `inlayHint.resolveSupport` clients
51+
/// might resolve this property late using the resolve request.
52+
/// FIXME: Location location;
53+
};
54+
55+
struct InlayHint {
56+
/// The position of this hint.
57+
///
58+
/// If multiple hints have the same position, they will be shown in the order
59+
/// they appear in the response.
60+
Position position;
61+
62+
/// The label of this hint. A human readable string or an array of
63+
/// InlayHintLabelPart label parts.
64+
///
65+
/// *Note* that neither the string nor the label part can be empty.
66+
/// TODO: Use label
67+
array<InlayHintLabelPart> label;
68+
69+
/// The kind of this hint. Can be omitted in which case the client
70+
/// should fall back to a reasonable default.
71+
InlayHintKind kind;
72+
};
73+
1574
} // namespace clice::proto

include/Protocol/Lifecycle.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ struct ServerCapabilities {
163163
/// FIXME: InlineValueOptions inlineValueProvider;
164164

165165
/// The server provides inlay hints.
166-
/// FIXME: InlayHintOptions inlayHintProvider;
166+
InlayHintOptions inlayHintProvider;
167167

168168
/// The server has support for pull model diagnostics.
169169
/// FIXME: DiagnosticOptions diagnosticProvider;

include/Server/Server.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ class Server {
208208

209209
async::Task<json::Value> on_semantic_token(proto::SemanticTokensParams params);
210210

211+
async::Task<json::Value> on_inlay_hint(proto::InlayHintParams params);
212+
211213
private:
212214
/// The current request id.
213215
std::uint32_t id = 0;

include/Support/FileSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ inline std::string toPath(llvm::StringRef uri) {
146146

147147
llvm::SmallString<128> result;
148148
if(auto err = fs::real_path(decoded, result)) {
149-
clice::print("Failed to get real path: {}, Input is {}\n", err.message(), decoded);
149+
std::println("Failed to get real path: {}, Input is {}\n", err.message(), decoded);
150150
std::abort();
151151
}
152152

include/Support/Format.h

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,11 @@
11
#pragma once
22

33
#include <format>
4-
4+
#include <print>
55
#include "Support/JSON.h"
66
#include "Support/Ranges.h"
77
#include "llvm/Support/Error.h"
88

9-
namespace clice {
10-
11-
template <typename... Args>
12-
void print(std::format_string<Args...> fmt, Args&&... args) {
13-
llvm::outs() << std::vformat(fmt.get(), std::make_format_args(args...));
14-
}
15-
16-
template <typename... Args>
17-
void println(std::format_string<Args...> fmt, Args&&... args) {
18-
llvm::outs() << std::vformat(fmt.get(), std::make_format_args(args...)) << '\n';
19-
}
20-
21-
} // namespace clice
22-
239
template <>
2410
struct std::formatter<llvm::StringRef> : std::formatter<std::string_view> {
2511
using Base = std::formatter<std::string_view>;
@@ -171,7 +157,7 @@ std::string pretty_dump(const Object& object, std::size_t indent = 2) {
171157
std::string repr = dump(object);
172158
auto json = json::parse(repr);
173159
if(!json) {
174-
clice::println("{} {}", json.takeError(), repr);
160+
std::println("{} {}", json.takeError(), repr);
175161
std::abort();
176162
}
177163
llvm::SmallString<128> buffer = {std::format("{{0:{}}}", indent)};

include/Test/Test.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,22 @@ struct may_failure {
8484
bool fatal = false;
8585
std::string expression;
8686
std::source_location location;
87+
std::string message;
88+
89+
may_failure& operator<< (std::string message) {
90+
this->message += std::move(message);
91+
return *this;
92+
}
8793

8894
~may_failure() {
8995
Runner::instance().fail(*this);
9096
}
9197
};
9298

93-
inline struct {
99+
constexpr inline struct {
94100
template <typename TExpr>
95101
may_failure operator() (const TExpr& expr,
96-
std::source_location location = std::source_location::current()) {
102+
std::source_location location = std::source_location::current()) const {
97103
bool failed = false;
98104
std::string expression = "false";
99105

@@ -115,16 +121,18 @@ inline struct {
115121
}
116122
} expect;
117123

118-
inline struct {
119-
test&& operator/ (test&& test) {
124+
constexpr inline struct {
125+
test&& operator/ (test&& test) const {
120126
test.skipped = true;
121127
return std::move(test);
122128
}
123129
} skip;
124130

125-
inline struct {
126-
may_failure&& operator/ (may_failure&& failure) {
127-
failure.fatal = true;
131+
constexpr inline struct {
132+
may_failure&& operator/ (may_failure&& failure) const {
133+
if(failure.failed) {
134+
failure.fatal = true;
135+
}
128136
return std::move(failure);
129137
}
130138
} fatal;

0 commit comments

Comments
 (0)