diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -1375,7 +1375,7 @@ /// descendants. If not defined, the children have not been resolved. llvm::Optional> children; - /// An optional 'data' filed, which can be used to identify a type hierarchy + /// An optional 'data' field, which can be used to identify a type hierarchy /// item in a resolve request. llvm::Optional data; }; @@ -1397,6 +1397,83 @@ bool fromJSON(const llvm::json::Value &, ResolveTypeHierarchyItemParams &, llvm::json::Path); +enum class SymbolTag { Deprecated = 1 }; +llvm::json::Value toJSON(SymbolTag); + +/// The parameter of a `textDocument/prepareCallHierarchy` request. +struct CallHierarchyPrepareParams : public TextDocumentPositionParams {}; + +/// Represents programming constructs like functions or constructors +/// in the context of call hierarchy. +struct CallHierarchyItem { + /// The name of this item. + std::string name; + + /// The kind of this item. + SymbolKind kind; + + /// Tags for this item. + std::vector tags; + + /// More detaill for this item, e.g. the signature of a function. + std::string detail; + + /// The resource identifier of this item. + URIForFile uri; + + /// The range enclosing this symbol not including leading / trailing + /// whitespace but everything else, e.g. comments and code. + Range range; + + /// The range that should be selected and revealed when this symbol + /// is being picked, e.g. the name of a function. + /// Must be contained by `Rng`. + Range selectionRange; + + /// An optional 'data' field, which can be used to identify a call + /// hierarchy item in an incomingCalls or outgoingCalls request. + std::string data; +}; +llvm::json::Value toJSON(const CallHierarchyItem &); +bool fromJSON(const llvm::json::Value &, CallHierarchyItem &, llvm::json::Path); + +/// The parameter of a `callHierarchy/incomingCalls` request. +struct CallHierarchyIncomingCallsParams { + CallHierarchyItem item; +}; +bool fromJSON(const llvm::json::Value &, CallHierarchyIncomingCallsParams &, + llvm::json::Path); + +/// Represents an incoming call, e.g. a caller of a method or constructor. +struct CallHierarchyIncomingCall { + /// The item that makes the call. + CallHierarchyItem from; + + /// The range at which the calls appear. + /// This is relative to the caller denoted by `From`. + std::vector fromRanges; +}; +llvm::json::Value toJSON(const CallHierarchyIncomingCall &); + +/// The parameter of a `callHierarchy/outgoingCalls` request. +struct CallHierarchyOutgoingCallsParams { + CallHierarchyItem item; +}; +bool fromJSON(const llvm::json::Value &, CallHierarchyOutgoingCallsParams &, + llvm::json::Path); + +/// Represents an outgoing call, e.g. calling a getter from a method or +/// a method from a constructor etc. +struct CallHierarchyOutgoingCall { + /// The item that is called. + CallHierarchyItem to; + + /// The range at which this item is called. + /// This is the range relative to the caller, and not `To`. + std::vector fromRanges; +}; +llvm::json::Value toJSON(const CallHierarchyOutgoingCall &); + struct ReferenceParams : public TextDocumentPositionParams { // For now, no options like context.includeDeclaration are supported. }; diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -1209,6 +1209,58 @@ return fromJSON(Params, Base, P); } +llvm::json::Value toJSON(SymbolTag Tag) { + return llvm::json::Value{static_cast(Tag)}; +} + +llvm::json::Value toJSON(const CallHierarchyItem &I) { + llvm::json::Object Result{{"name", I.name}, + {"kind", static_cast(I.kind)}, + {"range", I.range}, + {"selectionRange", I.selectionRange}, + {"uri", I.uri}}; + if (!I.tags.empty()) + Result["tags"] = I.tags; + if (!I.detail.empty()) + Result["detail"] = I.detail; + if (!I.data.empty()) + Result["data"] = I.data; + return std::move(Result); +} + +bool fromJSON(const llvm::json::Value &Params, CallHierarchyItem &I, + llvm::json::Path P) { + llvm::json::ObjectMapper O(Params, P); + + // Populate the required fields only. We don't care about the + // optional fields `Tags` and `Detail` for the purpose of + // client --> server communication. + return O && O.map("name", I.name) && O.map("kind", I.kind) && + O.map("uri", I.uri) && O.map("range", I.range) && + O.map("selectionRange", I.selectionRange) && + O.mapOptional("data", I.data); +} + +bool fromJSON(const llvm::json::Value &Params, + CallHierarchyIncomingCallsParams &C, llvm::json::Path P) { + llvm::json::ObjectMapper O(Params, P); + return O.map("item", C.item); +} + +llvm::json::Value toJSON(const CallHierarchyIncomingCall &C) { + return llvm::json::Object{{"from", C.from}, {"fromRanges", C.fromRanges}}; +} + +bool fromJSON(const llvm::json::Value &Params, + CallHierarchyOutgoingCallsParams &C, llvm::json::Path P) { + llvm::json::ObjectMapper O(Params, P); + return O.map("item", C.item); +} + +llvm::json::Value toJSON(const CallHierarchyOutgoingCall &C) { + return llvm::json::Object{{"to", C.to}, {"fromRanges", C.fromRanges}}; +} + static const char *toString(OffsetEncoding OE) { switch (OE) { case OffsetEncoding::UTF8: