[PATCH] D58448: [clangd] Improve global code completion when scope specifier is unresolved.

2019-02-27 Thread Eric Liu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL354963: [clangd] Improve global code completion when scope 
specifier is unresolved. (authored by ioeric, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58448/new/

https://reviews.llvm.org/D58448

Files:
  clang-tools-extra/trunk/clangd/CodeComplete.cpp
  clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp


Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
@@ -1095,8 +1095,10 @@
   } // namespace ns
   )cpp");
 
-  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
-  UnorderedElementsAre("bar::";
+  EXPECT_THAT(Requests,
+  ElementsAre(Field(
+  &FuzzyFindRequest::Scopes,
+  UnorderedElementsAre("a::bar::", "ns::bar::", "bar::";
 }
 
 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
@@ -2335,6 +2337,35 @@
 Kind(CompletionItemKind::Reference;
 }
 
+TEST(CompletionTest, ScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+namespace a {
+void f() { b::X^ }
+}
+  )cpp",
+ {cls("a::b::XYZ")}, Opts);
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ";
+}
+
+TEST(CompletionTest, NestedScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+namespace a {
+namespace b {}
+void f() { b::c::X^ }
+}
+  )cpp",
+ {cls("a::b::c::XYZ")}, Opts);
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ";
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/trunk/clangd/CodeComplete.cpp
===
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp
@@ -48,6 +48,7 @@
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -526,7 +527,7 @@
 std::set Results;
 for (llvm::StringRef AS : AccessibleScopes)
   Results.insert(
-  ((UnresolvedQualifier ? *UnresolvedQualifier : "") + AS).str());
+  (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
 return {Results.begin(), Results.end()};
   }
 };
@@ -570,16 +571,15 @@
   }
 
   // Unresolved qualifier.
-  // FIXME: When Sema can resolve part of a scope chain (e.g.
-  // "known::unknown::id"), we should expand the known part ("known::") rather
-  // than treating the whole thing as unknown.
-  SpecifiedScope Info;
-  Info.AccessibleScopes.push_back(""); // global namespace
+  SpecifiedScope Info = GetAllAccessibleScopes(CCContext);
+  Info.AccessibleScopes.push_back(""); // Make sure global scope is included.
 
-  Info.UnresolvedQualifier =
+  llvm::StringRef SpelledSpecifier =
   Lexer::getSourceText(CharSourceRange::getCharRange((*SS)->getRange()),
-   CCSema.SourceMgr, clang::LangOptions())
-  .ltrim("::");
+   CCSema.SourceMgr, clang::LangOptions());
+  if (SpelledSpecifier.consume_front("::"))
+Info.AccessibleScopes = {""};
+  Info.UnresolvedQualifier = SpelledSpecifier;
   // Sema excludes the trailing "::".
   if (!Info.UnresolvedQualifier->empty())
 *Info.UnresolvedQualifier += "::";


Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
@@ -1095,8 +1095,10 @@
   } // namespace ns
   )cpp");
 
-  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
-  UnorderedElementsAre("bar::";
+  EXPECT_THAT(Requests,
+  ElementsAre(Field(
+  &FuzzyFindRequest::Scopes,
+  UnorderedElementsAre("a::bar::", "ns::bar::", "bar::";
 }
 
 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
@@ -2335,6 +2337,35 @@
 Kind(CompletionItemKind::Reference;
 }
 
+TEST(CompletionTest, ScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  au

[PATCH] D58448: [clangd] Improve global code completion when scope specifier is unresolved.

2019-02-27 Thread Eric Liu via Phabricator via cfe-commits
ioeric updated this revision to Diff 188512.
ioeric added a comment.

- Rebase and minor cleanup


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58448/new/

https://reviews.llvm.org/D58448

Files:
  clangd/CodeComplete.cpp
  unittests/clangd/CodeCompleteTests.cpp


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1095,8 +1095,10 @@
   } // namespace ns
   )cpp");
 
-  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
-  UnorderedElementsAre("bar::";
+  EXPECT_THAT(Requests,
+  ElementsAre(Field(
+  &FuzzyFindRequest::Scopes,
+  UnorderedElementsAre("a::bar::", "ns::bar::", "bar::";
 }
 
 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
@@ -2335,6 +2337,35 @@
 Kind(CompletionItemKind::Reference;
 }
 
+TEST(CompletionTest, ScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+namespace a {
+void f() { b::X^ }
+}
+  )cpp",
+ {cls("a::b::XYZ")}, Opts);
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ";
+}
+
+TEST(CompletionTest, NestedScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+namespace a {
+namespace b {}
+void f() { b::c::X^ }
+}
+  )cpp",
+ {cls("a::b::c::XYZ")}, Opts);
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ";
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -48,6 +48,7 @@
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -526,7 +527,7 @@
 std::set Results;
 for (llvm::StringRef AS : AccessibleScopes)
   Results.insert(
-  ((UnresolvedQualifier ? *UnresolvedQualifier : "") + AS).str());
+  (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
 return {Results.begin(), Results.end()};
   }
 };
@@ -570,16 +571,15 @@
   }
 
   // Unresolved qualifier.
-  // FIXME: When Sema can resolve part of a scope chain (e.g.
-  // "known::unknown::id"), we should expand the known part ("known::") rather
-  // than treating the whole thing as unknown.
-  SpecifiedScope Info;
-  Info.AccessibleScopes.push_back(""); // global namespace
+  SpecifiedScope Info = GetAllAccessibleScopes(CCContext);
+  Info.AccessibleScopes.push_back(""); // Make sure global scope is included.
 
-  Info.UnresolvedQualifier =
+  llvm::StringRef SpelledSpecifier =
   Lexer::getSourceText(CharSourceRange::getCharRange((*SS)->getRange()),
-   CCSema.SourceMgr, clang::LangOptions())
-  .ltrim("::");
+   CCSema.SourceMgr, clang::LangOptions());
+  if (SpelledSpecifier.consume_front("::"))
+Info.AccessibleScopes = {""};
+  Info.UnresolvedQualifier = SpelledSpecifier;
   // Sema excludes the trailing "::".
   if (!Info.UnresolvedQualifier->empty())
 *Info.UnresolvedQualifier += "::";


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1095,8 +1095,10 @@
   } // namespace ns
   )cpp");
 
-  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
-  UnorderedElementsAre("bar::";
+  EXPECT_THAT(Requests,
+  ElementsAre(Field(
+  &FuzzyFindRequest::Scopes,
+  UnorderedElementsAre("a::bar::", "ns::bar::", "bar::";
 }
 
 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
@@ -2335,6 +2337,35 @@
 Kind(CompletionItemKind::Reference;
 }
 
+TEST(CompletionTest, ScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+namespace a {
+void f() { b::X^ }
+}
+  )cpp",
+ {cls("a::b::XYZ")}, Opts);
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ";
+}
+
+TEST(CompletionTest, NestedScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+namespace a 

Re: [PATCH] D58448: [clangd] Improve global code completion when scope specifier is unresolved.

2019-02-26 Thread Ilya Biryukov via cfe-commits
Slightly offtopic.

It would be nice to add a way to collect quality during actual completion
sessions, rather than simulated ones.
I'm thinking about clients sending a message to the server mentioning the
completion item user ended up selecting in a completion list (would require
an LSP extension).
I believe this should be enough information to collect metrics for the use
of code completion in the wild.


On Tue, Feb 26, 2019 at 11:04 AM Eric Liu  wrote:

> Unfortunately, the evaluation tool I use only works on compilable code, so
> it doesn't capture the unsolved specifier case in this patch. I didn't try
> to collect the metrics because I think this is more of a bug fix than
> quality improvement.
>
> On Tue, Feb 26, 2019, 10:25 Kadir Cetinkaya via Phabricator <
> revi...@reviews.llvm.org> wrote:
>
>> kadircet added a comment.
>>
>> LG
>>
>> Do we have any metrics regarding change in completion quality?
>>
>>
>> Repository:
>>   rCTE Clang Tools Extra
>>
>> CHANGES SINCE LAST ACTION
>>   https://reviews.llvm.org/D58448/new/
>>
>> https://reviews.llvm.org/D58448
>>
>>
>>
>>

-- 
Regards,
Ilya Biryukov
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D58448: [clangd] Improve global code completion when scope specifier is unresolved.

2019-02-26 Thread Eric Liu via cfe-commits
Unfortunately, the evaluation tool I use only works on compilable code, so
it doesn't capture the unsolved specifier case in this patch. I didn't try
to collect the metrics because I think this is more of a bug fix than
quality improvement.

On Tue, Feb 26, 2019, 10:25 Kadir Cetinkaya via Phabricator <
revi...@reviews.llvm.org> wrote:

> kadircet added a comment.
>
> LG
>
> Do we have any metrics regarding change in completion quality?
>
>
> Repository:
>   rCTE Clang Tools Extra
>
> CHANGES SINCE LAST ACTION
>   https://reviews.llvm.org/D58448/new/
>
> https://reviews.llvm.org/D58448
>
>
>
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D58448: [clangd] Improve global code completion when scope specifier is unresolved.

2019-02-26 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added a comment.

LG

Do we have any metrics regarding change in completion quality?


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D58448/new/

https://reviews.llvm.org/D58448



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D58448: [clangd] Improve global code completion when scope specifier is unresolved.

2019-02-20 Thread Eric Liu via Phabricator via cfe-commits
ioeric created this revision.
ioeric added reviewers: ilya-biryukov, sammccall.
Herald added subscribers: cfe-commits, jdoerfert, kadircet, arphaman, jkorous, 
MaskRay.
Herald added a project: clang.

Suppose `clangd::` is unresolved in the following example. Currently,
we simply use "clangd::" as the query scope. We can do better by combining with
accessible scopes in the context. The query scopes can be `{clangd::, 
clang::clangd::}`.

  namespace clang { clangd::^ }


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D58448

Files:
  clangd/CodeComplete.cpp
  unittests/clangd/CodeCompleteTests.cpp


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1094,8 +1094,10 @@
   } // namespace ns
   )cpp");
 
-  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
-  UnorderedElementsAre("bar::";
+  EXPECT_THAT(Requests,
+  ElementsAre(Field(
+  &FuzzyFindRequest::Scopes,
+  UnorderedElementsAre("a::bar::", "ns::bar::", "bar::";
 }
 
 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
@@ -2314,6 +2316,35 @@
   EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar")));
 }
 
+TEST(CompletionTest, ScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+namespace a {
+void f() { b::X^ }
+}
+  )cpp",
+ {cls("a::b::XYZ")}, Opts);
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ";
+}
+
+TEST(CompletionTest, NestedScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+namespace a {
+namespace b {}
+void f() { b::c::X^ }
+}
+  )cpp",
+ {cls("a::b::c::XYZ")}, Opts);
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ";
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -48,6 +48,7 @@
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -526,7 +527,7 @@
 std::set Results;
 for (llvm::StringRef AS : AccessibleScopes)
   Results.insert(
-  ((UnresolvedQualifier ? *UnresolvedQualifier : "") + AS).str());
+  (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
 return {Results.begin(), Results.end()};
   }
 };
@@ -570,16 +571,16 @@
   }
 
   // Unresolved qualifier.
-  // FIXME: When Sema can resolve part of a scope chain (e.g.
-  // "known::unknown::id"), we should expand the known part ("known::") rather
-  // than treating the whole thing as unknown.
-  SpecifiedScope Info;
-  Info.AccessibleScopes.push_back(""); // global namespace
+  SpecifiedScope Info = GetAllAccessibleScopes(CCContext);
+  if (Info.AccessibleScopes.empty())
+Info.AccessibleScopes.push_back(""); // Fallback to global namespace.
 
-  Info.UnresolvedQualifier =
+  llvm::StringRef SpelledSpecifier =
   Lexer::getSourceText(CharSourceRange::getCharRange((*SS)->getRange()),
-   CCSema.SourceMgr, clang::LangOptions())
-  .ltrim("::");
+   CCSema.SourceMgr, clang::LangOptions());
+  if (SpelledSpecifier.consume_front("::"))
+Info.AccessibleScopes = {""};
+  Info.UnresolvedQualifier = SpelledSpecifier;
   // Sema excludes the trailing "::".
   if (!Info.UnresolvedQualifier->empty())
 *Info.UnresolvedQualifier += "::";


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1094,8 +1094,10 @@
   } // namespace ns
   )cpp");
 
-  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
-  UnorderedElementsAre("bar::";
+  EXPECT_THAT(Requests,
+  ElementsAre(Field(
+  &FuzzyFindRequest::Scopes,
+  UnorderedElementsAre("a::bar::", "ns::bar::", "bar::";
 }
 
 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
@@ -2314,6 +2316,35 @@
   EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar")));
 }
 
+TEST(CompletionTest, ScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+namespace a {
+void f() { b::X^ }
+}
+  )cpp",
+