[clang-tools-extra] r337681 - [clangd] Penalize non-instance members when accessed via class instances.
Eric Liu via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 23 03:56:37 PDT 2018
Author: ioeric
Date: Mon Jul 23 03:56:37 2018
New Revision: 337681
URL: http://llvm.org/viewvc/llvm-project?rev=337681&view=rev
Log:
[clangd] Penalize non-instance members when accessed via class instances.
Summary:
The following are metrics for explicit member access completions. There is no
noticeable impact on other completion types.
Before:
EXPLICIT_MEMBER_ACCESS
Total measurements: 24382
All measurements: MRR: 62.27 Top10: 80.21% Top-100: 94.48%
Full identifiers: MRR: 98.81 Top10: 99.89% Top-100: 99.95%
0-5 filter len:
MRR: 13.25 46.31 62.47 67.77 70.40 81.91
Top-10: 29% 74% 84% 91% 91% 97%
Top-100: 67% 99% 99% 99% 99% 100%
After:
EXPLICIT_MEMBER_ACCESS
Total measurements: 24382
All measurements: MRR: 63.18 Top10: 80.58% Top-100: 95.07%
Full identifiers: MRR: 98.79 Top10: 99.89% Top-100: 99.95%
0-5 filter len:
MRR: 13.84 48.39 63.55 68.83 71.28 82.64
Top-10: 30% 75% 84% 91% 91% 97%
Top-100: 70% 99% 99% 99% 99% 100%
* Top-N: wanted result is found in the first N completion results.
* MRR: Mean reciprocal rank.
Remark: the change seems to have minor positive impact. Although the improvement
is relatively small, down-ranking non-instance members in instance member access
should reduce noise in the completion results.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D49543
Modified:
clang-tools-extra/trunk/clangd/CodeComplete.cpp
clang-tools-extra/trunk/clangd/CodeComplete.h
clang-tools-extra/trunk/clangd/Quality.cpp
clang-tools-extra/trunk/clangd/Quality.h
clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
clang-tools-extra/trunk/unittests/clangd/QualityTests.cpp
Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=337681&r1=337680&r2=337681&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original)
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Mon Jul 23 03:56:37 2018
@@ -1062,6 +1062,7 @@ private:
Output.Completions.back().Score = C.second;
}
Output.HasMore = Incomplete;
+ Output.Context = Recorder->CCContext.getKind();
return Output;
}
@@ -1156,6 +1157,7 @@ private:
CompletionCandidate::Bundle Bundle) {
SymbolQualitySignals Quality;
SymbolRelevanceSignals Relevance;
+ Relevance.Context = Recorder->CCContext.getKind();
Relevance.Query = SymbolRelevanceSignals::CodeComplete;
Relevance.FileProximityMatch = FileProximity.getPointer();
auto &First = Bundle.front();
@@ -1290,6 +1292,7 @@ raw_ostream &operator<<(raw_ostream &OS,
raw_ostream &operator<<(raw_ostream &OS, const CodeCompleteResult &R) {
OS << "CodeCompleteResult: " << R.Completions.size() << (R.HasMore ? "+" : "")
+ << " (" << getCompletionKindString(R.Context) << ")"
<< " items:\n";
for (const auto &C : R.Completions)
OS << C << "\n";
Modified: clang-tools-extra/trunk/clangd/CodeComplete.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.h?rev=337681&r1=337680&r2=337681&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.h (original)
+++ clang-tools-extra/trunk/clangd/CodeComplete.h Mon Jul 23 03:56:37 2018
@@ -21,6 +21,7 @@
#include "Protocol.h"
#include "index/Index.h"
#include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Tooling/CompilationDatabase.h"
@@ -144,6 +145,7 @@ raw_ostream &operator<<(raw_ostream &, c
struct CodeCompleteResult {
std::vector<CodeCompletion> Completions;
bool HasMore = false;
+ CodeCompletionContext::Kind Context = CodeCompletionContext::CCC_Other;
};
raw_ostream &operator<<(raw_ostream &, const CodeCompleteResult &);
Modified: clang-tools-extra/trunk/clangd/Quality.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Quality.cpp?rev=337681&r1=337680&r2=337681&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Quality.cpp (original)
+++ clang-tools-extra/trunk/clangd/Quality.cpp Mon Jul 23 03:56:37 2018
@@ -11,7 +11,9 @@
#include "URI.h"
#include "index/Index.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
@@ -139,6 +141,27 @@ categorize(const index::SymbolInfo &D) {
llvm_unreachable("Unknown index::SymbolKind");
}
+static bool isInstanceMember(const NamedDecl *ND) {
+ if (!ND)
+ return false;
+ if (const auto *TP = dyn_cast<FunctionTemplateDecl>(ND))
+ ND = TP->TemplateDecl::getTemplatedDecl();
+ if (const auto *CM = dyn_cast<CXXMethodDecl>(ND))
+ return !CM->isStatic();
+ return isa<FieldDecl>(ND); // Note that static fields are VarDecl.
+}
+
+static bool isInstanceMember(const index::SymbolInfo &D) {
+ switch (D.Kind) {
+ case index::SymbolKind::InstanceMethod:
+ case index::SymbolKind::InstanceProperty:
+ case index::SymbolKind::Field:
+ return true;
+ default:
+ return false;
+ }
+}
+
void SymbolQualitySignals::merge(const CodeCompletionResult &SemaCCResult) {
if (SemaCCResult.Availability == CXAvailability_Deprecated)
Deprecated = true;
@@ -231,6 +254,7 @@ void SymbolRelevanceSignals::merge(const
// relevant to non-completion requests, we should recognize class members etc.
SymbolURI = IndexResult.CanonicalDeclaration.FileURI;
+ IsInstanceMember |= isInstanceMember(IndexResult.SymInfo);
}
void SymbolRelevanceSignals::merge(const CodeCompletionResult &SemaCCResult) {
@@ -247,6 +271,7 @@ void SymbolRelevanceSignals::merge(const
? 1.0
: 0.6;
SemaProximityScore = std::max(DeclProximity, SemaProximityScore);
+ IsInstanceMember |= isInstanceMember(SemaCCResult.Declaration);
}
// Declarations are scoped, others (like macros) are assumed global.
@@ -296,6 +321,13 @@ float SymbolRelevanceSignals::evaluate()
}
}
+ // Penalize non-instance members when they are accessed via a class instance.
+ if (!IsInstanceMember &&
+ (Context == CodeCompletionContext::CCC_DotMemberAccess ||
+ Context == CodeCompletionContext::CCC_ArrowMemberAccess)) {
+ Score *= 0.5;
+ }
+
return Score;
}
@@ -303,6 +335,8 @@ raw_ostream &operator<<(raw_ostream &OS,
OS << formatv("=== Symbol relevance: {0}\n", S.evaluate());
OS << formatv("\tName match: {0}\n", S.NameMatch);
OS << formatv("\tForbidden: {0}\n", S.Forbidden);
+ OS << formatv("\tIsInstanceMember: {0}\n", S.IsInstanceMember);
+ OS << formatv("\tContext: {0}\n", getCompletionKindString(S.Context));
OS << formatv("\tSymbol URI: {0}\n", S.SymbolURI);
if (S.FileProximityMatch) {
auto Score = proximityScore(S.SymbolURI, S.FileProximityMatch);
Modified: clang-tools-extra/trunk/clangd/Quality.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Quality.h?rev=337681&r1=337680&r2=337681&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Quality.h (original)
+++ clang-tools-extra/trunk/clangd/Quality.h Mon Jul 23 03:56:37 2018
@@ -26,6 +26,7 @@
//===---------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_QUALITY_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_QUALITY_H
+#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include <algorithm>
@@ -98,6 +99,11 @@ struct SymbolRelevanceSignals {
Generic,
} Query = Generic;
+ CodeCompletionContext::Kind Context = CodeCompletionContext::CCC_Other;
+
+ // Whether symbol is an instance member of a class.
+ bool IsInstanceMember = false;
+
void merge(const CodeCompletionResult &SemaResult);
void merge(const Symbol &IndexResult);
Modified: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp?rev=337681&r1=337680&r2=337681&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp Mon Jul 23 03:56:37 2018
@@ -18,6 +18,7 @@
#include "SyncAPI.h"
#include "TestFS.h"
#include "index/MemIndex.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/Support/Error.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
@@ -1321,6 +1322,21 @@ TEST(CompletionTest, ScopeOfClassFieldIn
UnorderedElementsAre(AllOf(Scope("ns::X::"), Named("x_"))));
}
+TEST(CompletionTest, CodeCompletionContext) {
+ auto Results = completions(
+ R"cpp(
+ namespace ns {
+ class X { public: X(); int x_; };
+ void f() {
+ X x;
+ x.^;
+ }
+ }
+ )cpp");
+
+ EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
+}
+
} // namespace
} // namespace clangd
} // namespace clang
Modified: clang-tools-extra/trunk/unittests/clangd/QualityTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/QualityTests.cpp?rev=337681&r1=337680&r2=337681&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/QualityTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/QualityTests.cpp Mon Jul 23 03:56:37 2018
@@ -23,6 +23,7 @@
#include "TestTU.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/Support/Casting.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -227,6 +228,14 @@ TEST(QualityTests, SymbolRelevanceSignal
EXPECT_EQ(Scoped.evaluate(), Default.evaluate());
Scoped.Query = SymbolRelevanceSignals::CodeComplete;
EXPECT_GT(Scoped.evaluate(), Default.evaluate());
+
+ SymbolRelevanceSignals Instance;
+ Instance.IsInstanceMember = false;
+ EXPECT_EQ(Instance.evaluate(), Default.evaluate());
+ Instance.Context = CodeCompletionContext::CCC_DotMemberAccess;
+ EXPECT_LT(Instance.evaluate(), Default.evaluate());
+ Instance.IsInstanceMember = true;
+ EXPECT_EQ(Instance.evaluate(), Default.evaluate());
}
TEST(QualityTests, SortText) {
@@ -267,6 +276,47 @@ TEST(QualityTests, NoBoostForClassConstr
EXPECT_EQ(Ctor.Scope, SymbolRelevanceSignals::GlobalScope);
}
+TEST(QualityTests, IsInstanceMember) {
+ auto Header = TestTU::withHeaderCode(R"cpp(
+ class Foo {
+ public:
+ static void foo() {}
+
+ template <typename T> void tpl(T *t) {}
+
+ void bar() {}
+ };
+ )cpp");
+ auto Symbols = Header.headerSymbols();
+
+ SymbolRelevanceSignals Rel;
+ const Symbol &FooSym = findSymbol(Symbols, "Foo::foo");
+ Rel.merge(FooSym);
+ EXPECT_FALSE(Rel.IsInstanceMember);
+ const Symbol &BarSym = findSymbol(Symbols, "Foo::bar");
+ Rel.merge(BarSym);
+ EXPECT_TRUE(Rel.IsInstanceMember);
+
+ Rel.IsInstanceMember =false;
+ const Symbol &TplSym = findSymbol(Symbols, "Foo::tpl");
+ Rel.merge(TplSym);
+ EXPECT_TRUE(Rel.IsInstanceMember);
+
+ auto AST = Header.build();
+ const NamedDecl *Foo = &findDecl(AST, "Foo::foo");
+ const NamedDecl *Bar = &findDecl(AST, "Foo::bar");
+ const NamedDecl *Tpl = &findDecl(AST, "Foo::tpl");
+
+ Rel.IsInstanceMember = false;
+ Rel.merge(CodeCompletionResult(Foo, /*Priority=*/0));
+ EXPECT_FALSE(Rel.IsInstanceMember);
+ Rel.merge(CodeCompletionResult(Bar, /*Priority=*/0));
+ EXPECT_TRUE(Rel.IsInstanceMember);
+ Rel.IsInstanceMember = false;
+ Rel.merge(CodeCompletionResult(Tpl, /*Priority=*/0));
+ EXPECT_TRUE(Rel.IsInstanceMember);
+}
+
} // namespace
} // namespace clangd
} // namespace clang
More information about the cfe-commits
mailing list