<div dir="ltr">Hi Nathan,<div><br></div><div>I've reverted this to get the bot green(er).</div><div><br></div><div>Regards</div><div>Russ</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 12 Jul 2019 at 13:32, Russell Gallop <<a href="mailto:russell.gallop@gmail.com">russell.gallop@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hi Nathan,<br></div><div>This is causing a test failure on Windows: <a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/26909" target="_blank">http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/26909</a></div><div><br></div><div>Please can you take a look?</div><div><br></div><div>Thanks</div><div>Russ</div><div><br></div><div>[ RUN      ] Subtypes.LazyResolution<br>Preamble for file C:\clangd-test\TestTU.cpp cannot be reused. Attempting to rebuild it.<br>Built preamble of size 210988 for file C:\clangd-test\TestTU.cpp<br>Preamble for file C:\clangd-test\TestTU.cpp cannot be reused. Attempting to rebuild it.<br>Built preamble of size 210988 for file C:\clangd-test\TestTU.cpp<br>index AST for C:\clangd-test\TestTU.cpp (main=false): <br>  symbol slab: 4 symbols, 5152 bytes<br>  ref slab: 0 symbols, 0 refs, 136 bytes<br>  relations slab: 3 relations, 84 bytes<br>index AST for C:\clangd-test\TestTU.cpp (main=true): <br>  symbol slab: 4 symbols, 5152 bytes<br>  ref slab: 0 symbols, 0 refs, 136 bytes<br>  relations slab: 3 relations, 84 bytes<br>Expected<T> must be checked before access or destruction.<br>Unchecked Expected<T> contained error:<br>Hint path doesn't start with test root: /clangd-test/TestTU.cpp</div><div>0x00007FF7486D1B25 (0x0000000000000016 0x00007FF7486D1B20 0x00007FF700000006 0x00007FF748680AF4)<br>0x00007FFF3F0EE19D (0x000001CDE35AA701 0x000001CD00000000 0x000001CDE35AA7B0 0x000001CDE35AB111), raise() + 0x1DD bytes(s)<br>0x00007FFF3F0EF071 (0x0000000000000003 0x0000002900000003 0x000001CDE35AB111 0x000000294FD8E330), abort() + 0x31 bytes(s)<br>...<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 12 Jul 2019 at 04:26, Nathan Ridge via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: nridge<br>
Date: Thu Jul 11 20:26:32 2019<br>
New Revision: 365867<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=365867&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=365867&view=rev</a><br>
Log:<br>
[clangd] Implement typeHierarchy/resolve for subtypes<br>
<br>
Summary:<br>
This allows the client to resolve subtypes one level at a time.<br>
<br>
For supertypes, this is not necessary, because we eagerly compute<br>
supertypes and return all levels.<br>
<br>
Reviewers: sammccall<br>
<br>
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits<br>
<br>
Tags: #clang<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D64308" rel="noreferrer" target="_blank">https://reviews.llvm.org/D64308</a><br>
<br>
Modified:<br>
    clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp<br>
    clang-tools-extra/trunk/clangd/ClangdLSPServer.h<br>
    clang-tools-extra/trunk/clangd/ClangdServer.cpp<br>
    clang-tools-extra/trunk/clangd/ClangdServer.h<br>
    clang-tools-extra/trunk/clangd/Protocol.cpp<br>
    clang-tools-extra/trunk/clangd/Protocol.h<br>
    clang-tools-extra/trunk/clangd/XRefs.cpp<br>
    clang-tools-extra/trunk/clangd/XRefs.h<br>
    clang-tools-extra/trunk/clangd/test/type-hierarchy.test<br>
    clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp<br>
<br>
Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Thu Jul 11 20:26:32 2019<br>
@@ -926,6 +926,13 @@ void ClangdLSPServer::onTypeHierarchy(<br>
                         Params.resolve, Params.direction, std::move(Reply));<br>
 }<br>
<br>
+void ClangdLSPServer::onResolveTypeHierarchy(<br>
+    const ResolveTypeHierarchyItemParams &Params,<br>
+    Callback<Optional<TypeHierarchyItem>> Reply) {<br>
+  Server->resolveTypeHierarchy(Params.item, Params.resolve, Params.direction,<br>
+                               std::move(Reply));<br>
+}<br>
+<br>
 void ClangdLSPServer::applyConfiguration(<br>
     const ConfigurationSettings &Settings) {<br>
   // Per-file update to the compilation database.<br>
@@ -1021,6 +1028,7 @@ ClangdLSPServer::ClangdLSPServer(<br>
   MsgHandler->bind("workspace/didChangeConfiguration", &ClangdLSPServer::onChangeConfiguration);<br>
   MsgHandler->bind("textDocument/symbolInfo", &ClangdLSPServer::onSymbolInfo);<br>
   MsgHandler->bind("textDocument/typeHierarchy", &ClangdLSPServer::onTypeHierarchy);<br>
+  MsgHandler->bind("typeHierarchy/resolve", &ClangdLSPServer::onResolveTypeHierarchy);<br>
   // clang-format on<br>
 }<br>
<br>
<br>
Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.h?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.h?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.h (original)<br>
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.h Thu Jul 11 20:26:32 2019<br>
@@ -100,6 +100,8 @@ private:<br>
                Callback<llvm::Optional<Hover>>);<br>
   void onTypeHierarchy(const TypeHierarchyParams &,<br>
                        Callback<llvm::Optional<TypeHierarchyItem>>);<br>
+  void onResolveTypeHierarchy(const ResolveTypeHierarchyItemParams &,<br>
+                              Callback<llvm::Optional<TypeHierarchyItem>>);<br>
   void onChangeConfiguration(const DidChangeConfigurationParams &);<br>
   void onSymbolInfo(const TextDocumentPositionParams &,<br>
                     Callback<std::vector<SymbolDetails>>);<br>
<br>
Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Thu Jul 11 20:26:32 2019<br>
@@ -101,8 +101,7 @@ ClangdServer::ClangdServer(const GlobalC<br>
                      : nullptr),<br>
       GetClangTidyOptions(Opts.GetClangTidyOptions),<br>
       SuggestMissingIncludes(Opts.SuggestMissingIncludes),<br>
-      EnableHiddenFeatures(Opts.HiddenFeatures),<br>
-      TweakFilter(Opts.TweakFilter),<br>
+      EnableHiddenFeatures(Opts.HiddenFeatures), TweakFilter(Opts.TweakFilter),<br>
       WorkspaceRoot(Opts.WorkspaceRoot),<br>
       // Pass a callback into `WorkScheduler` to extract symbols from a newly<br>
       // parsed file and rebuild the file index synchronously each time an AST<br>
@@ -528,6 +527,13 @@ void ClangdServer::typeHierarchy(PathRef<br>
   WorkScheduler.runWithAST("Type Hierarchy", File, Bind(Action, std::move(CB)));<br>
 }<br>
<br>
+void ClangdServer::resolveTypeHierarchy(<br>
+    TypeHierarchyItem Item, int Resolve, TypeHierarchyDirection Direction,<br>
+    Callback<llvm::Optional<TypeHierarchyItem>> CB) {<br>
+  clangd::resolveTypeHierarchy(Item, Resolve, Direction, Index);<br>
+  CB(Item);<br>
+}<br>
+<br>
 void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) {<br>
   // FIXME: Do nothing for now. This will be used for indexing and potentially<br>
   // invalidating other caches.<br>
<br>
Modified: clang-tools-extra/trunk/clangd/ClangdServer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/ClangdServer.h (original)<br>
+++ clang-tools-extra/trunk/clangd/ClangdServer.h Thu Jul 11 20:26:32 2019<br>
@@ -138,7 +138,8 @@ public:<br>
     bool SemanticHighlighting = false;<br>
<br>
     /// Returns true if the StringRef is a tweak that should be enabled<br>
-    std::function<bool(llvm::StringRef)> TweakFilter = [](llvm::StringRef TweakToSearch) {return true;};<br>
+    std::function<bool(llvm::StringRef)> TweakFilter =<br>
+        [](llvm::StringRef TweakToSearch) { return true; };<br>
   };<br>
   // Sensible default options for use in tests.<br>
   // Features like indexing must be enabled if desired.<br>
@@ -212,6 +213,11 @@ public:<br>
                      TypeHierarchyDirection Direction,<br>
                      Callback<llvm::Optional<TypeHierarchyItem>> CB);<br>
<br>
+  /// Resolve type hierarchy item in the given direction.<br>
+  void resolveTypeHierarchy(TypeHierarchyItem Item, int Resolve,<br>
+                            TypeHierarchyDirection Direction,<br>
+                            Callback<llvm::Optional<TypeHierarchyItem>> CB);<br>
+<br>
   /// Retrieve the top symbols from the workspace matching a query.<br>
   void workspaceSymbols(StringRef Query, int Limit,<br>
                         Callback<std::vector<SymbolInformation>> CB);<br>
@@ -315,7 +321,7 @@ private:<br>
   // can be caused by missing includes (e.g. member access in incomplete type).<br>
   bool SuggestMissingIncludes = false;<br>
   bool EnableHiddenFeatures = false;<br>
-   <br>
+<br>
   std::function<bool(llvm::StringRef)> TweakFilter;<br>
<br>
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)<br>
<br>
Modified: clang-tools-extra/trunk/clangd/Protocol.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/Protocol.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd/Protocol.cpp Thu Jul 11 20:26:32 2019<br>
@@ -422,8 +422,7 @@ bool fromJSON(const llvm::json::Value &P<br>
 bool fromJSON(const llvm::json::Value &Params,<br>
               DocumentRangeFormattingParams &R) {<br>
   llvm::json::ObjectMapper O(Params);<br>
-  return O && O.map("textDocument", R.textDocument) &&<br>
-         O.map("range", R.range);<br>
+  return O && O.map("textDocument", R.textDocument) && O.map("range", R.range);<br>
 }<br>
<br>
 bool fromJSON(const llvm::json::Value &Params,<br>
@@ -445,8 +444,8 @@ bool fromJSON(const llvm::json::Value &P<br>
<br>
 llvm::json::Value toJSON(const DiagnosticRelatedInformation &DRI) {<br>
   return llvm::json::Object{<br>
-    {"location", DRI.location},<br>
-    {"message", DRI.message},<br>
+      {"location", DRI.location},<br>
+      {"message", DRI.message},<br>
   };<br>
 }<br>
<br>
@@ -978,6 +977,8 @@ llvm::json::Value toJSON(const TypeHiera<br>
     Result["parents"] = I.parents;<br>
   if (I.children)<br>
     Result["children"] = I.children;<br>
+  if (I.data)<br>
+    Result["data"] = I.data;<br>
   return std::move(Result);<br>
 }<br>
<br>
@@ -996,10 +997,18 @@ bool fromJSON(const llvm::json::Value &P<br>
   O.map("deprecated", I.deprecated);<br>
   O.map("parents", I.parents);<br>
   O.map("children", I.children);<br>
+  O.map("data", I.data);<br>
<br>
   return true;<br>
 }<br>
<br>
+bool fromJSON(const llvm::json::Value &Params,<br>
+              ResolveTypeHierarchyItemParams &P) {<br>
+  llvm::json::ObjectMapper O(Params);<br>
+  return O && O.map("item", P.item) && O.map("resolve", P.resolve) &&<br>
+         O.map("direction", P.direction);<br>
+}<br>
+<br>
 bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R) {<br>
   TextDocumentPositionParams &Base = R;<br>
   return fromJSON(Params, Base);<br>
<br>
Modified: clang-tools-extra/trunk/clangd/Protocol.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/Protocol.h (original)<br>
+++ clang-tools-extra/trunk/clangd/Protocol.h Thu Jul 11 20:26:32 2019<br>
@@ -1127,7 +1127,7 @@ struct TypeHierarchyItem {<br>
   SymbolKind kind;<br>
<br>
   /// `true` if the hierarchy item is deprecated. Otherwise, `false`.<br>
-  bool deprecated;<br>
+  bool deprecated = false;<br>
<br>
   /// The URI of the text document where this type hierarchy item belongs to.<br>
   URIForFile uri;<br>
@@ -1153,13 +1153,26 @@ struct TypeHierarchyItem {<br>
   /// descendants. If not defined, the children have not been resolved.<br>
   llvm::Optional<std::vector<TypeHierarchyItem>> children;<br>
<br>
-  /// The protocol has a slot here for an optional 'data' filed, which can<br>
-  /// be used to identify a type hierarchy item in a resolve request. We don't<br>
-  /// need this (the item itself is sufficient to identify what to resolve)<br>
-  /// so don't declare it.<br>
+  /// An optional 'data' filed, which can be used to identify a type hierarchy<br>
+  /// item in a resolve request.<br>
+  llvm::Optional<std::string> data;<br>
 };<br>
 llvm::json::Value toJSON(const TypeHierarchyItem &);<br>
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TypeHierarchyItem &);<br>
+bool fromJSON(const llvm::json::Value &, TypeHierarchyItem &);<br>
+<br>
+/// Parameters for the `typeHierarchy/resolve` request.<br>
+struct ResolveTypeHierarchyItemParams {<br>
+  /// The item to resolve.<br>
+  TypeHierarchyItem item;<br>
+<br>
+  /// The hierarchy levels to resolve. `0` indicates no level.<br>
+  int resolve;<br>
+<br>
+  /// The direction of the hierarchy levels to resolve.<br>
+  TypeHierarchyDirection direction;<br>
+};<br>
+bool fromJSON(const llvm::json::Value &, ResolveTypeHierarchyItemParams &);<br>
<br>
 struct ReferenceParams : public TextDocumentPositionParams {<br>
   // For now, no options like context.includeDeclaration are supported.<br>
<br>
Modified: clang-tools-extra/trunk/clangd/XRefs.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.cpp?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.cpp?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/XRefs.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd/XRefs.cpp Thu Jul 11 20:26:32 2019<br>
@@ -893,7 +893,7 @@ llvm::Optional<QualType> getDeducedType(<br>
<br>
 /// Retrieves the deduced type at a given location (auto, decltype).<br>
 bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg) {<br>
-  return (bool) getDeducedType(AST, SourceLocationBeg);<br>
+  return (bool)getDeducedType(AST, SourceLocationBeg);<br>
 }<br>
<br>
 llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,<br>
@@ -1104,6 +1104,10 @@ symbolToTypeHierarchyItem(const Symbol &<br>
   // (<a href="https://github.com/clangd/clangd/issues/59" rel="noreferrer" target="_blank">https://github.com/clangd/clangd/issues/59</a>).<br>
   THI.range = THI.selectionRange;<br>
   THI.uri = Loc->uri;<br>
+  // Store the SymbolID in the 'data' field. The client will<br>
+  // send this back in typeHierarchy/resolve, allowing us to<br>
+  // continue resolving additional levels of the type hierarchy.<br>
+  THI.data = S.ID.str();<br>
<br>
   return std::move(THI);<br>
 }<br>
@@ -1247,6 +1251,25 @@ getTypeHierarchy(ParsedAST &AST, Positio<br>
   return Result;<br>
 }<br>
<br>
+void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels,<br>
+                          TypeHierarchyDirection Direction,<br>
+                          const SymbolIndex *Index) {<br>
+  // We only support typeHierarchy/resolve for children, because for parents<br>
+  // we ignore ResolveLevels and return all levels of parents eagerly.<br>
+  if (Direction == TypeHierarchyDirection::Parents || ResolveLevels == 0)<br>
+    return;<br>
+<br>
+  Item.children.emplace();<br>
+<br>
+  if (Index && Item.data) {<br>
+    // We store the item's SymbolID in the 'data' field, and the client<br>
+    // passes it back to us in typeHierarchy/resolve.<br>
+    if (Expected<SymbolID> ID = SymbolID::fromStr(*Item.data)) {<br>
+      fillSubTypes(*ID, *Item.children, Index, ResolveLevels, Item.uri.file());<br>
+    }<br>
+  }<br>
+}<br>
+<br>
 FormattedString HoverInfo::present() const {<br>
   FormattedString Output;<br>
   if (NamespaceScope) {<br>
<br>
Modified: clang-tools-extra/trunk/clangd/XRefs.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.h?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.h?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/XRefs.h (original)<br>
+++ clang-tools-extra/trunk/clangd/XRefs.h Thu Jul 11 20:26:32 2019<br>
@@ -141,6 +141,10 @@ llvm::Optional<TypeHierarchyItem> getTyp<br>
     ParsedAST &AST, Position Pos, int Resolve, TypeHierarchyDirection Direction,<br>
     const SymbolIndex *Index = nullptr, PathRef TUPath = PathRef{});<br>
<br>
+void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels,<br>
+                          TypeHierarchyDirection Direction,<br>
+                          const SymbolIndex *Index);<br>
+<br>
 /// Retrieves the deduced type at a given location (auto, decltype).<br>
 /// Retuns None unless SourceLocationBeg starts an auto/decltype token.<br>
 /// It will return the underlying type.<br>
<br>
Modified: clang-tools-extra/trunk/clangd/test/type-hierarchy.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/test/type-hierarchy.test?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/test/type-hierarchy.test?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/test/type-hierarchy.test (original)<br>
+++ clang-tools-extra/trunk/clangd/test/type-hierarchy.test Thu Jul 11 20:26:32 2019<br>
@@ -1,7 +1,7 @@<br>
 # RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s<br>
 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}<br>
 ---<br>
-{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct Parent {};\nstruct Child1 : Parent {};\nstruct Child2 : Child1 {};\nstruct Child3 : Child2 {};"}}}<br>
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct Parent {};\nstruct Child1 : Parent {};\nstruct Child2 : Child1 {};\nstruct Child3 : Child2 {};\nstruct Child4 : Child3 {};"}}}<br>
 ---<br>
 {"jsonrpc":"2.0","id":1,"method":"textDocument/typeHierarchy","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":11},"direction":2,"resolve":1}}<br>
 #      CHECK:  "id": 1<br>
@@ -9,6 +9,7 @@<br>
 # CHECK-NEXT:  "result": {<br>
 # CHECK-NEXT:    "children": [<br>
 # CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "data": "A6576FE083F2949A",<br>
 # CHECK-NEXT:        "kind": 23,<br>
 # CHECK-NEXT:        "name": "Child3",<br>
 # CHECK-NEXT:        "range": {<br>
@@ -114,6 +115,64 @@<br>
 # CHECK-NEXT:    "uri": "file:///clangd-test/main.cpp"<br>
 # CHECK-NEXT:  }<br>
 ---<br>
-{"jsonrpc":"2.0","id":2,"method":"shutdown"}<br>
+{"jsonrpc":"2.0","id":2,"method":"typeHierarchy/resolve","params":{"item":{"uri":"test:///main.cpp","data":"A6576FE083F2949A","name":"Child3","kind":23,"range":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}},"selectionRange":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}}},"direction":0,"resolve":1}}<br>
+#      CHECK:  "id": 2<br>
+# CHECK-NEXT:  "jsonrpc": "2.0",<br>
+# CHECK-NEXT:  "result": {<br>
+# CHECK-NEXT:    "children": [<br>
+# CHECK-NEXT:      {<br>
+# CHECK-NEXT:        "data": "5705B382DFC77CBC",<br>
+# CHECK-NEXT:        "kind": 23,<br>
+# CHECK-NEXT:        "name": "Child4",<br>
+# CHECK-NEXT:        "range": {<br>
+# CHECK-NEXT:          "end": {<br>
+# CHECK-NEXT:            "character": 13,<br>
+# CHECK-NEXT:            "line": 4<br>
+# CHECK-NEXT:          },<br>
+# CHECK-NEXT:          "start": {<br>
+# CHECK-NEXT:            "character": 7,<br>
+# CHECK-NEXT:            "line": 4<br>
+# CHECK-NEXT:          }<br>
+# CHECK-NEXT:        },<br>
+# CHECK-NEXT:        "selectionRange": {<br>
+# CHECK-NEXT:          "end": {<br>
+# CHECK-NEXT:            "character": 13,<br>
+# CHECK-NEXT:            "line": 4<br>
+# CHECK-NEXT:          },<br>
+# CHECK-NEXT:          "start": {<br>
+# CHECK-NEXT:            "character": 7,<br>
+# CHECK-NEXT:            "line": 4<br>
+# CHECK-NEXT:          }<br>
+# CHECK-NEXT:        },<br>
+# CHECK-NEXT:        "uri": "file:///clangd-test/main.cpp"<br>
+# CHECK-NEXT:      }<br>
+# CHECK-NEXT:    ],<br>
+# CHECK-NEXT:    "data": "A6576FE083F2949A",<br>
+# CHECK-NEXT:    "kind": 23,<br>
+# CHECK-NEXT:    "name": "Child3",<br>
+# CHECK-NEXT:    "range": {<br>
+# CHECK-NEXT:      "end": {<br>
+# CHECK-NEXT:        "character": 13,<br>
+# CHECK-NEXT:        "line": 3<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      "start": {<br>
+# CHECK-NEXT:        "character": 7,<br>
+# CHECK-NEXT:        "line": 3<br>
+# CHECK-NEXT:      }<br>
+# CHECK-NEXT:    },<br>
+# CHECK-NEXT:    "selectionRange": {<br>
+# CHECK-NEXT:      "end": {<br>
+# CHECK-NEXT:        "character": 13,<br>
+# CHECK-NEXT:        "line": 3<br>
+# CHECK-NEXT:      },<br>
+# CHECK-NEXT:      "start": {<br>
+# CHECK-NEXT:        "character": 7,<br>
+# CHECK-NEXT:        "line": 3<br>
+# CHECK-NEXT:      }<br>
+# CHECK-NEXT:    },<br>
+# CHECK-NEXT:    "uri": "file:///clangd-test/main.cpp"<br>
+# CHECK-NEXT:  }<br>
+---<br>
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}<br>
 ---<br>
 {"jsonrpc":"2.0","method":"exit"}<br>
<br>
Modified: clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp?rev=365867&r1=365866&r2=365867&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp?rev=365867&r1=365866&r2=365867&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd/unittests/TypeHierarchyTests.cpp Thu Jul 11 20:26:32 2019<br>
@@ -42,8 +42,17 @@ MATCHER_P(WithKind, Kind, "") { return a<br>
 MATCHER_P(SelectionRangeIs, R, "") { return arg.selectionRange == R; }<br>
 template <class... ParentMatchers><br>
 ::testing::Matcher<TypeHierarchyItem> Parents(ParentMatchers... ParentsM) {<br>
-  return Field(&TypeHierarchyItem::parents, HasValue(ElementsAre(ParentsM...)));<br>
+  return Field(&TypeHierarchyItem::parents,<br>
+               HasValue(UnorderedElementsAre(ParentsM...)));<br>
 }<br>
+template <class... ChildMatchers><br>
+::testing::Matcher<TypeHierarchyItem> Children(ChildMatchers... ChildrenM) {<br>
+  return Field(&TypeHierarchyItem::children,<br>
+               HasValue(UnorderedElementsAre(ChildrenM...)));<br>
+}<br>
+// Note: "not resolved" is differnt from "resolved but empty"!<br>
+MATCHER(ParentsNotResolved, "") { return !arg.parents; }<br>
+MATCHER(ChildrenNotResolved, "") { return !arg.children; }<br>
<br>
 TEST(FindRecordTypeAt, TypeOrVariable) {<br>
   Annotations Source(R"cpp(<br>
@@ -603,6 +612,41 @@ struct Child : Parent<T> {};<br>
   EXPECT_THAT(collectSubtypes(Parent, Index.get()), ElementsAre(Child));<br>
 }<br>
<br>
+TEST(Subtypes, LazyResolution) {<br>
+  Annotations Source(R"cpp(<br>
+struct P^arent {};<br>
+struct Child1 : Parent {};<br>
+struct Child2a : Child1 {};<br>
+struct Child2b : Child1 {};<br>
+)cpp");<br>
+<br>
+  TestTU TU = TestTU::withCode(Source.code());<br>
+  auto AST = TU.build();<br>
+  auto Index = TU.index();<br>
+<br>
+  llvm::Optional<TypeHierarchyItem> Result = getTypeHierarchy(<br>
+      AST, Source.point(), /*ResolveLevels=*/1,<br>
+      TypeHierarchyDirection::Children, Index.get(), "/clangd-test/TestTU.cpp");<br>
+  ASSERT_TRUE(bool(Result));<br>
+  EXPECT_THAT(<br>
+      *Result,<br>
+      AllOf(WithName("Parent"), WithKind(SymbolKind::Struct), Parents(),<br>
+            Children(AllOf(WithName("Child1"), WithKind(SymbolKind::Struct),<br>
+                           ParentsNotResolved(), ChildrenNotResolved()))));<br>
+<br>
+  resolveTypeHierarchy((*Result->children)[0], /*ResolveLevels=*/1,<br>
+                       TypeHierarchyDirection::Children, Index.get());<br>
+<br>
+  EXPECT_THAT(<br>
+      (*Result->children)[0],<br>
+      AllOf(WithName("Child1"), WithKind(SymbolKind::Struct),<br>
+            ParentsNotResolved(),<br>
+            Children(AllOf(WithName("Child2a"), WithKind(SymbolKind::Struct),<br>
+                           ParentsNotResolved(), ChildrenNotResolved()),<br>
+                     AllOf(WithName("Child2b"), WithKind(SymbolKind::Struct),<br>
+                           ParentsNotResolved(), ChildrenNotResolved()))));<br>
+}<br>
+<br>
 } // namespace<br>
 } // namespace clangd<br>
 } // namespace clang<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>
</blockquote></div>