Skip to content

Commit c9b3250

Browse files
committed
[clangd] Allow to build Clangd without decision forest
Make it possible to disable building the decision forest ranking model for clangd. To unbreak build of Clangd on PPC32 in gentoo, see https://bugs.gentoo.org/829602 Based on D138520. Reviewed By: sammccall Differential Revision: https://reviews.llvm.org/D139107
1 parent 88594d1 commit c9b3250

File tree

10 files changed

+141
-65
lines changed

10 files changed

+141
-65
lines changed

Diff for: clang-tools-extra/clangd/CMakeLists.txt

+11-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ if (NOT DEFINED CLANGD_BUILD_XPC)
1818
unset(CLANGD_BUILD_XPC_DEFAULT)
1919
endif ()
2020

21+
# This involves generating and compiling large source files, which can run into toolchain limitations.
22+
option(CLANGD_DECISION_FOREST "Enable decision forest model for ranking code completion items" ON)
2123
option(CLANGD_MALLOC_TRIM "Call malloc_trim(3) periodically in Clangd. (only takes effect when using glibc)" ON)
2224
# -DCLANG_TIDY_CHECKS=Off avoids a dependency on clang-tidy, reducing rebuilds.
2325
option(CLANGD_TIDY_CHECKS "Link all clang-tidy checks into clangd" ON)
@@ -29,6 +31,7 @@ llvm_canonicalize_cmake_booleans(
2931
CLANGD_MALLOC_TRIM
3032
CLANGD_TIDY_CHECKS
3133
LLVM_ENABLE_ZLIB
34+
CLANGD_DECISION_FOREST
3235
)
3336

3437
configure_file(
@@ -43,8 +46,12 @@ set(LLVM_LINK_COMPONENTS
4346
Option
4447
)
4548

46-
include(${CMAKE_CURRENT_SOURCE_DIR}/quality/CompletionModel.cmake)
47-
gen_decision_forest(${CMAKE_CURRENT_SOURCE_DIR}/quality/model CompletionModel clang::clangd::Example)
49+
set(COMPLETIONMODEL_SOURCES)
50+
if(CLANGD_DECISION_FOREST)
51+
include(${CMAKE_CURRENT_SOURCE_DIR}/quality/CompletionModel.cmake)
52+
gen_decision_forest(${CMAKE_CURRENT_SOURCE_DIR}/quality/model CompletionModel clang::clangd::Example)
53+
list(APPEND COMPLETIONMODEL_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/CompletionModel.cpp)
54+
endif()
4855

4956
if(MSVC AND NOT CLANG_CL)
5057
set_source_files_properties(CompileCommands.cpp PROPERTIES COMPILE_FLAGS -wd4130) # disables C4130: logical operation on address of string constant
@@ -66,6 +73,7 @@ add_clang_library(clangDaemon
6673
ConfigCompile.cpp
6774
ConfigProvider.cpp
6875
ConfigYAML.cpp
76+
DecisionForest.cpp
6977
Diagnostics.cpp
7078
DraftStore.cpp
7179
DumpAST.cpp
@@ -102,7 +110,7 @@ add_clang_library(clangDaemon
102110
TUScheduler.cpp
103111
URI.cpp
104112
XRefs.cpp
105-
${CMAKE_CURRENT_BINARY_DIR}/CompletionModel.cpp
113+
${COMPLETIONMODEL_SOURCES}
106114

107115
index/Background.cpp
108116
index/BackgroundIndexLoader.cpp

Diff for: clang-tools-extra/clangd/CodeComplete.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "CodeCompletionStrings.h"
2323
#include "Compiler.h"
2424
#include "ExpectedTypes.h"
25+
#include "Feature.h"
2526
#include "FileDistance.h"
2627
#include "FuzzyMatch.h"
2728
#include "Headers.h"
@@ -76,6 +77,16 @@
7677

7778
namespace clang {
7879
namespace clangd {
80+
81+
#if CLANGD_DECISION_FOREST
82+
const CodeCompleteOptions::CodeCompletionRankingModel
83+
CodeCompleteOptions::DefaultRankingModel =
84+
CodeCompleteOptions::DecisionForest;
85+
#else
86+
const CodeCompleteOptions::CodeCompletionRankingModel
87+
CodeCompleteOptions::DefaultRankingModel = CodeCompleteOptions::Heuristics;
88+
#endif
89+
7990
namespace {
8091

8192
CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {

Diff for: clang-tools-extra/clangd/CodeComplete.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ struct CodeCompleteOptions {
130130
enum CodeCompletionRankingModel {
131131
Heuristics,
132132
DecisionForest,
133-
} RankingModel = DecisionForest;
133+
};
134+
static const CodeCompletionRankingModel DefaultRankingModel;
135+
CodeCompletionRankingModel RankingModel = DefaultRankingModel;
134136

135137
/// Callback used to score a CompletionCandidate if DecisionForest ranking
136138
/// model is enabled.

Diff for: clang-tools-extra/clangd/DecisionForest.cpp

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//===--- DecisionForest.cpp --------------------------------------*- C++-*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "Features.inc"
10+
11+
#if !CLANGD_DECISION_FOREST
12+
#include "Quality.h"
13+
#include <cstdlib>
14+
15+
namespace clang {
16+
namespace clangd {
17+
DecisionForestScores
18+
evaluateDecisionForest(const SymbolQualitySignals &Quality,
19+
const SymbolRelevanceSignals &Relevance, float Base) {
20+
llvm::errs() << "Clangd was compiled without decision forest support.\n";
21+
std::abort();
22+
}
23+
24+
} // namespace clangd
25+
} // namespace clang
26+
27+
#else // !CLANGD_DECISION_FOREST
28+
29+
#include "CompletionModel.h"
30+
#include "Quality.h"
31+
#include <cmath>
32+
33+
namespace clang {
34+
namespace clangd {
35+
36+
DecisionForestScores
37+
evaluateDecisionForest(const SymbolQualitySignals &Quality,
38+
const SymbolRelevanceSignals &Relevance, float Base) {
39+
Example E;
40+
E.setIsDeprecated(Quality.Deprecated);
41+
E.setIsReservedName(Quality.ReservedName);
42+
E.setIsImplementationDetail(Quality.ImplementationDetail);
43+
E.setNumReferences(Quality.References);
44+
E.setSymbolCategory(Quality.Category);
45+
46+
SymbolRelevanceSignals::DerivedSignals Derived =
47+
Relevance.calculateDerivedSignals();
48+
int NumMatch = 0;
49+
if (Relevance.ContextWords) {
50+
for (const auto &Word : Relevance.ContextWords->keys()) {
51+
if (Relevance.Name.contains_insensitive(Word)) {
52+
++NumMatch;
53+
}
54+
}
55+
}
56+
E.setIsNameInContext(NumMatch > 0);
57+
E.setNumNameInContext(NumMatch);
58+
E.setFractionNameInContext(
59+
Relevance.ContextWords && !Relevance.ContextWords->empty()
60+
? NumMatch * 1.0 / Relevance.ContextWords->size()
61+
: 0);
62+
E.setIsInBaseClass(Relevance.InBaseClass);
63+
E.setFileProximityDistanceCost(Derived.FileProximityDistance);
64+
E.setSemaFileProximityScore(Relevance.SemaFileProximityScore);
65+
E.setSymbolScopeDistanceCost(Derived.ScopeProximityDistance);
66+
E.setSemaSaysInScope(Relevance.SemaSaysInScope);
67+
E.setScope(Relevance.Scope);
68+
E.setContextKind(Relevance.Context);
69+
E.setIsInstanceMember(Relevance.IsInstanceMember);
70+
E.setHadContextType(Relevance.HadContextType);
71+
E.setHadSymbolType(Relevance.HadSymbolType);
72+
E.setTypeMatchesPreferred(Relevance.TypeMatchesPreferred);
73+
74+
DecisionForestScores Scores;
75+
// Exponentiating DecisionForest prediction makes the score of each tree a
76+
// multiplciative boost (like NameMatch). This allows us to weigh the
77+
// prediction score and NameMatch appropriately.
78+
Scores.ExcludingName = pow(Base, Evaluate(E));
79+
// Following cases are not part of the generated training dataset:
80+
// - Symbols with `NeedsFixIts`.
81+
// - Forbidden symbols.
82+
// - Keywords: Dataset contains only macros and decls.
83+
if (Relevance.NeedsFixIts)
84+
Scores.ExcludingName *= 0.5;
85+
if (Relevance.Forbidden)
86+
Scores.ExcludingName *= 0;
87+
if (Quality.Category == SymbolQualitySignals::Keyword)
88+
Scores.ExcludingName *= 4;
89+
90+
// NameMatch should be a multiplier on total score to support rescoring.
91+
Scores.Total = Relevance.NameMatch * Scores.ExcludingName;
92+
return Scores;
93+
}
94+
95+
} // namespace clangd
96+
} // namespace clang
97+
98+
#endif // !CLANGD_DECISION_FOREST

Diff for: clang-tools-extra/clangd/Feature.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ std::string featureString() {
6666
#if !CLANGD_TIDY_CHECKS
6767
"-tidy"
6868
#endif
69+
70+
#if !CLANGD_DECISION_FOREST
71+
"-decision_forest"
72+
#endif
6973
;
7074
}
7175

Diff for: clang-tools-extra/clangd/Features.inc.in

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
#define ENABLE_GRPC_REFLECTION @ENABLE_GRPC_REFLECTION@
55
#define CLANGD_MALLOC_TRIM @CLANGD_MALLOC_TRIM@
66
#define CLANGD_TIDY_CHECKS @CLANGD_TIDY_CHECKS@
7+
#define CLANGD_DECISION_FOREST @CLANGD_DECISION_FOREST@

Diff for: clang-tools-extra/clangd/Quality.cpp

-60
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include "Quality.h"
1010
#include "AST.h"
1111
#include "ASTSignals.h"
12-
#include "CompletionModel.h"
1312
#include "FileDistance.h"
1413
#include "SourceCode.h"
1514
#include "index/Symbol.h"
@@ -529,65 +528,6 @@ float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance) {
529528
return SymbolQuality * SymbolRelevance;
530529
}
531530

532-
DecisionForestScores
533-
evaluateDecisionForest(const SymbolQualitySignals &Quality,
534-
const SymbolRelevanceSignals &Relevance, float Base) {
535-
Example E;
536-
E.setIsDeprecated(Quality.Deprecated);
537-
E.setIsReservedName(Quality.ReservedName);
538-
E.setIsImplementationDetail(Quality.ImplementationDetail);
539-
E.setNumReferences(Quality.References);
540-
E.setSymbolCategory(Quality.Category);
541-
542-
SymbolRelevanceSignals::DerivedSignals Derived =
543-
Relevance.calculateDerivedSignals();
544-
int NumMatch = 0;
545-
if (Relevance.ContextWords) {
546-
for (const auto &Word : Relevance.ContextWords->keys()) {
547-
if (Relevance.Name.contains_insensitive(Word)) {
548-
++NumMatch;
549-
}
550-
}
551-
}
552-
E.setIsNameInContext(NumMatch > 0);
553-
E.setNumNameInContext(NumMatch);
554-
E.setFractionNameInContext(
555-
Relevance.ContextWords && !Relevance.ContextWords->empty()
556-
? NumMatch * 1.0 / Relevance.ContextWords->size()
557-
: 0);
558-
E.setIsInBaseClass(Relevance.InBaseClass);
559-
E.setFileProximityDistanceCost(Derived.FileProximityDistance);
560-
E.setSemaFileProximityScore(Relevance.SemaFileProximityScore);
561-
E.setSymbolScopeDistanceCost(Derived.ScopeProximityDistance);
562-
E.setSemaSaysInScope(Relevance.SemaSaysInScope);
563-
E.setScope(Relevance.Scope);
564-
E.setContextKind(Relevance.Context);
565-
E.setIsInstanceMember(Relevance.IsInstanceMember);
566-
E.setHadContextType(Relevance.HadContextType);
567-
E.setHadSymbolType(Relevance.HadSymbolType);
568-
E.setTypeMatchesPreferred(Relevance.TypeMatchesPreferred);
569-
570-
DecisionForestScores Scores;
571-
// Exponentiating DecisionForest prediction makes the score of each tree a
572-
// multiplciative boost (like NameMatch). This allows us to weigh the
573-
// prediction score and NameMatch appropriately.
574-
Scores.ExcludingName = pow(Base, Evaluate(E));
575-
// Following cases are not part of the generated training dataset:
576-
// - Symbols with `NeedsFixIts`.
577-
// - Forbidden symbols.
578-
// - Keywords: Dataset contains only macros and decls.
579-
if (Relevance.NeedsFixIts)
580-
Scores.ExcludingName *= 0.5;
581-
if (Relevance.Forbidden)
582-
Scores.ExcludingName *= 0;
583-
if (Quality.Category == SymbolQualitySignals::Keyword)
584-
Scores.ExcludingName *= 4;
585-
586-
// NameMatch should be a multiplier on total score to support rescoring.
587-
Scores.Total = Relevance.NameMatch * Scores.ExcludingName;
588-
return Scores;
589-
}
590-
591531
// Produces an integer that sorts in the same order as F.
592532
// That is: a < b <==> encodeFloat(a) < encodeFloat(b).
593533
static uint32_t encodeFloat(float F) {

Diff for: clang-tools-extra/clangd/benchmarks/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
add_subdirectory(CompletionModel)
1+
if(CLANGD_DECISION_FOREST)
2+
add_subdirectory(CompletionModel)
3+
endif()
24

35
add_benchmark(IndexBenchmark IndexBenchmark.cpp)
46

Diff for: clang-tools-extra/clangd/tool/ClangdMain.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,13 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
797797
}
798798
}
799799

800+
#if !CLANGD_DECISION_FOREST
801+
if (RankingModel == clangd::CodeCompleteOptions::DecisionForest) {
802+
llvm::errs() << "Clangd was compiled without decision forest support.\n";
803+
return 1;
804+
}
805+
#endif
806+
800807
// Setup tracing facilities if CLANGD_TRACE is set. In practice enabling a
801808
// trace flag in your editor's config is annoying, launching with
802809
// `CLANGD_TRACE=trace.json vim` is easier.

Diff for: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "ClangdServer.h"
1212
#include "CodeComplete.h"
1313
#include "Compiler.h"
14+
#include "Feature.h"
1415
#include "Matchers.h"
1516
#include "Protocol.h"
1617
#include "Quality.h"
@@ -174,6 +175,7 @@ Symbol withReferences(int N, Symbol S) {
174175
return S;
175176
}
176177

178+
#if CLANGD_DECISION_FOREST
177179
TEST(DecisionForestRankingModel, NameMatchSanityTest) {
178180
clangd::CodeCompleteOptions Opts;
179181
Opts.RankingModel = CodeCompleteOptions::DecisionForest;
@@ -207,6 +209,7 @@ TEST(DecisionForestRankingModel, ReferencesAffectRanking) {
207209
.Completions,
208210
ElementsAre(named("clangA"), named("clangD")));
209211
}
212+
#endif // CLANGD_DECISION_FOREST
210213

211214
TEST(DecisionForestRankingModel, DecisionForestScorerCallbackTest) {
212215
clangd::CodeCompleteOptions Opts;

0 commit comments

Comments
 (0)