mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-21 23:25:07 +00:00
Add caseSensitivity to config->{completion,workspaceSymbol}
This commit is contained in:
parent
e522ce8179
commit
73bd987b1a
@ -33,7 +33,8 @@ if(NOT CYGWIN)
|
||||
set_property(TARGET ccls PROPERTY CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL Windows)
|
||||
# CMake sets MSVC for both MSVC and Clang(Windows)
|
||||
if(MSVC)
|
||||
# Common MSVC/Clang(Windows) options
|
||||
target_compile_options(ccls PRIVATE
|
||||
/nologo
|
||||
@ -87,7 +88,7 @@ endif()
|
||||
### Libraries
|
||||
|
||||
# See cmake/FindClang.cmake
|
||||
find_package(Clang ${CLANG_VERSION} REQUIRED)
|
||||
find_package(Clang ${LIBCLANG_VERSION} REQUIRED)
|
||||
target_link_libraries(ccls PRIVATE Clang::Clang)
|
||||
|
||||
# Enable threading support
|
||||
@ -97,7 +98,7 @@ target_link_libraries(ccls PRIVATE Threads::Threads)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin)
|
||||
target_link_libraries(ccls PRIVATE -lc++experimental)
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL Windows)
|
||||
elseif(MSVC)
|
||||
else()
|
||||
target_link_libraries(ccls PRIVATE -lstdc++fs)
|
||||
endif()
|
||||
|
@ -15,9 +15,6 @@
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
|
||||
// TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on
|
||||
// |Foobar| in DISALLOW_COPY(Foobar)
|
||||
|
||||
#if CINDEX_VERSION >= 47
|
||||
#define CINDEX_HAVE_PRETTY 1
|
||||
#endif
|
||||
|
@ -89,6 +89,11 @@ struct Config {
|
||||
} codeLens;
|
||||
|
||||
struct Completion {
|
||||
// 0: case-insensitive
|
||||
// 1: case-folded, i.e. insensitive if no input character is uppercase.
|
||||
// 2: case-sensitive
|
||||
int caseSensitivity = 2;
|
||||
|
||||
// Some completion UI, such as Emacs' completion-at-point and company-lsp,
|
||||
// display completion item label and detail side by side.
|
||||
// This does not look right, when you see things like:
|
||||
@ -209,6 +214,7 @@ struct Config {
|
||||
} index;
|
||||
|
||||
struct WorkspaceSymbol {
|
||||
int caseSensitivity = 1;
|
||||
// Maximum workspace search results.
|
||||
int maxNum = 1000;
|
||||
// If true, workspace search results will be dynamically rescored/reordered
|
||||
@ -227,6 +233,7 @@ struct Config {
|
||||
MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport);
|
||||
MAKE_REFLECT_STRUCT(Config::CodeLens, localVariables);
|
||||
MAKE_REFLECT_STRUCT(Config::Completion,
|
||||
caseSensitivity,
|
||||
detailedLabel,
|
||||
filterAndSort,
|
||||
includeBlacklist,
|
||||
@ -248,7 +255,7 @@ MAKE_REFLECT_STRUCT(Config::Index,
|
||||
onDidChange,
|
||||
threads,
|
||||
whitelist);
|
||||
MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, maxNum, sort);
|
||||
MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort);
|
||||
MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum);
|
||||
MAKE_REFLECT_STRUCT(Config,
|
||||
compilationDatabaseCommand,
|
||||
|
@ -81,7 +81,11 @@ IndexFile* FileConsumer::TryConsumeFile(
|
||||
|
||||
CXFileUniqueID file_id;
|
||||
if (clang_getFileUniqueID(file, &file_id) != 0) {
|
||||
EmitError(file);
|
||||
std::string file_name = FileName(file);
|
||||
if (!file_name.empty()) {
|
||||
LOG_S(ERROR) << "Could not get unique file id for " << file_name
|
||||
<< " when parsing " << parse_file_;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -126,12 +130,3 @@ std::vector<std::unique_ptr<IndexFile>> FileConsumer::TakeLocalState() {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileConsumer::EmitError(CXFile file) const {
|
||||
std::string file_name = ToString(clang_getFileName(file));
|
||||
// TODO: Investigate this more, why can we get an empty file name?
|
||||
if (!file_name.empty()) {
|
||||
LOG_S(ERROR) << "Could not get unique file id for " << file_name
|
||||
<< " when parsing " << parse_file_;
|
||||
}
|
||||
}
|
||||
|
@ -68,8 +68,6 @@ struct FileConsumer {
|
||||
std::vector<std::unique_ptr<IndexFile>> TakeLocalState();
|
||||
|
||||
private:
|
||||
void EmitError(CXFile file) const;
|
||||
|
||||
std::unordered_map<CXFileUniqueID, std::unique_ptr<IndexFile>> local_;
|
||||
FileConsumerSharedState* shared_;
|
||||
std::string parse_file_;
|
||||
|
@ -78,8 +78,11 @@ int FuzzyMatcher::MatchScore(int i, int j, bool last) {
|
||||
return s;
|
||||
}
|
||||
|
||||
FuzzyMatcher::FuzzyMatcher(std::string_view pattern) {
|
||||
FuzzyMatcher::FuzzyMatcher(std::string_view pattern, int sensitivity) {
|
||||
CalculateRoles(pattern, pat_role, &pat_set);
|
||||
if (sensitivity == 1)
|
||||
sensitivity = pat_set & 1 << Upper ? 2 : 0;
|
||||
case_sensitivity = sensitivity;
|
||||
size_t n = 0;
|
||||
for (size_t i = 0; i < pattern.size(); i++)
|
||||
if (pattern[i] != ' ') {
|
||||
@ -112,12 +115,13 @@ int FuzzyMatcher::Match(std::string_view text) {
|
||||
cur[j][1] + MissScore(j, true));
|
||||
// For the first char of pattern, apply extra restriction to filter bad
|
||||
// candidates (e.g. |int| in |PRINT|)
|
||||
if (low_pat[i] == low_text[j] &&
|
||||
(i || text_role[j] != Tail || pat[i] == text[j])) {
|
||||
cur[j + 1][1] = std::max(pre[j][0] + MatchScore(i, j, false),
|
||||
pre[j][1] + MatchScore(i, j, true));
|
||||
} else
|
||||
cur[j + 1][1] = kMinScore * 2;
|
||||
cur[j + 1][1] = (case_sensitivity ? pat[i] == text[j]
|
||||
: low_pat[i] == low_text[j] &&
|
||||
(i || text_role[j] != Tail ||
|
||||
pat[i] == text[j]))
|
||||
? std::max(pre[j][0] + MatchScore(i, j, false),
|
||||
pre[j][1] + MatchScore(i, j, true))
|
||||
: cur[j + 1][1] = kMinScore * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +135,7 @@ int FuzzyMatcher::Match(std::string_view text) {
|
||||
|
||||
TEST_SUITE("fuzzy_match") {
|
||||
bool Ranks(std::string_view pat, std::vector<const char*> texts) {
|
||||
FuzzyMatcher fuzzy(pat);
|
||||
FuzzyMatcher fuzzy(pat, 0);
|
||||
std::vector<int> scores;
|
||||
for (auto text : texts)
|
||||
scores.push_back(fuzzy.Match(text));
|
||||
@ -150,7 +154,7 @@ TEST_SUITE("fuzzy_match") {
|
||||
}
|
||||
|
||||
TEST_CASE("test") {
|
||||
FuzzyMatcher fuzzy("");
|
||||
FuzzyMatcher fuzzy("", 0);
|
||||
CHECK(fuzzy.Match("") == 0);
|
||||
CHECK(fuzzy.Match("aaa") < 0);
|
||||
|
||||
|
@ -12,10 +12,11 @@ class FuzzyMatcher {
|
||||
// overflow.
|
||||
constexpr static int kMinScore = INT_MIN / 4;
|
||||
|
||||
FuzzyMatcher(std::string_view pattern);
|
||||
FuzzyMatcher(std::string_view pattern, int case_sensitivity);
|
||||
int Match(std::string_view text);
|
||||
|
||||
private:
|
||||
int case_sensitivity;
|
||||
std::string pat;
|
||||
std::string_view text;
|
||||
int pat_set, text_set;
|
||||
|
@ -188,9 +188,6 @@ struct TypeDef : NameMixin<TypeDef<F>> {
|
||||
types == o.types && funcs == o.funcs && vars == o.vars &&
|
||||
kind == o.kind && hover == o.hover && comments == o.comments;
|
||||
}
|
||||
bool operator!=(const TypeDef& o) const {
|
||||
return !(*this == o);
|
||||
}
|
||||
};
|
||||
template <typename TVisitor, typename Family>
|
||||
void Reflect(TVisitor& visitor, TypeDef<Family>& value) {
|
||||
@ -269,9 +266,6 @@ struct FuncDef : NameMixin<FuncDef<F>> {
|
||||
kind == o.kind && storage == o.storage && hover == o.hover &&
|
||||
comments == o.comments;
|
||||
}
|
||||
bool operator!=(const FuncDef& o) const {
|
||||
return !(*this == o);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TVisitor, typename Family>
|
||||
@ -359,7 +353,6 @@ struct VarDef : NameMixin<VarDef<F>> {
|
||||
extent == o.extent && type == o.type && kind == o.kind &&
|
||||
storage == o.storage && hover == o.hover && comments == o.comments;
|
||||
}
|
||||
bool operator!=(const VarDef& o) const { return !(*this == o); }
|
||||
};
|
||||
|
||||
template <typename TVisitor, typename Family>
|
||||
|
@ -49,7 +49,7 @@ std::optional<std::string> ReadJsonRpcContentFrom(
|
||||
return opt_c && *opt_c == expected;
|
||||
};
|
||||
if (!expect_char('\r') || !expect_char('\n')) {
|
||||
LOG_S(INFO) << "Unexpected token (expected \r\n sequence)";
|
||||
LOG_S(INFO) << "Unexpected token (expected \\r\\n sequence)";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ void FilterAndSortCompletionResponse(
|
||||
}
|
||||
|
||||
// Fuzzy match and remove awful candidates.
|
||||
FuzzyMatcher fuzzy(complete_text);
|
||||
FuzzyMatcher fuzzy(complete_text, g_config->completion.caseSensitivity);
|
||||
for (auto& item : items) {
|
||||
item.score_ =
|
||||
CaseFoldingSubsequenceMatch(complete_text, *item.filterText).first
|
||||
|
@ -129,7 +129,7 @@ struct Handler_WorkspaceSymbol : BaseMessageHandler<In_WorkspaceSymbol> {
|
||||
int longest = 0;
|
||||
for (int i : result_indices)
|
||||
longest = std::max(longest, int(db->GetSymbolName(i, true).size()));
|
||||
FuzzyMatcher fuzzy(query);
|
||||
FuzzyMatcher fuzzy(query, g_config->workspaceSymbol.caseSensitivity);
|
||||
std::vector<std::pair<int, int>> permutation(result_indices.size());
|
||||
for (int i = 0; i < int(result_indices.size()); i++) {
|
||||
permutation[i] = {
|
||||
|
37
src/query.cc
37
src/query.cc
@ -625,15 +625,15 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
|
||||
/*onFound:*/
|
||||
[this, &previous_id_map, ¤t_id_map](IndexType* previous,
|
||||
IndexType* current) {
|
||||
std::optional<QueryType::Def> previous_remapped_def =
|
||||
std::optional<QueryType::Def> prev_remapped =
|
||||
ToQuery(previous_id_map, previous->def);
|
||||
std::optional<QueryType::Def> current_remapped_def =
|
||||
std::optional<QueryType::Def> current_remapped =
|
||||
ToQuery(current_id_map, current->def);
|
||||
if (current_remapped_def &&
|
||||
previous_remapped_def != current_remapped_def &&
|
||||
!current_remapped_def->detailed_name.empty()) {
|
||||
if (current_remapped &&
|
||||
!(prev_remapped == current_remapped) &&
|
||||
!current_remapped->detailed_name.empty()) {
|
||||
types_def_update.push_back(QueryType::DefUpdate(
|
||||
current->usr, std::move(*current_remapped_def)));
|
||||
current->usr, std::move(*current_remapped)));
|
||||
}
|
||||
|
||||
PROCESS_UPDATE_DIFF(QueryTypeId, types_declarations, declarations, Use);
|
||||
@ -686,15 +686,15 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
|
||||
/*onFound:*/
|
||||
[this, &previous_id_map, ¤t_id_map](IndexFunc* previous,
|
||||
IndexFunc* current) {
|
||||
std::optional<QueryFunc::Def> previous_remapped_def =
|
||||
std::optional<QueryFunc::Def> prev_remapped =
|
||||
ToQuery(previous_id_map, previous->def);
|
||||
std::optional<QueryFunc::Def> current_remapped_def =
|
||||
std::optional<QueryFunc::Def> current_remapped =
|
||||
ToQuery(current_id_map, current->def);
|
||||
if (current_remapped_def &&
|
||||
previous_remapped_def != current_remapped_def &&
|
||||
!current_remapped_def->detailed_name.empty()) {
|
||||
if (current_remapped &&
|
||||
!(prev_remapped == current_remapped) &&
|
||||
!current_remapped->detailed_name.empty()) {
|
||||
funcs_def_update.push_back(QueryFunc::DefUpdate(
|
||||
current->usr, std::move(*current_remapped_def)));
|
||||
current->usr, std::move(*current_remapped)));
|
||||
}
|
||||
|
||||
PROCESS_UPDATE_DIFF(QueryFuncId, funcs_declarations, declarations, Use);
|
||||
@ -736,15 +736,14 @@ IndexUpdate::IndexUpdate(const IdMap& previous_id_map,
|
||||
/*onFound:*/
|
||||
[this, &previous_id_map, ¤t_id_map](IndexVar* previous,
|
||||
IndexVar* current) {
|
||||
std::optional<QueryVar::Def> previous_remapped_def =
|
||||
std::optional<QueryVar::Def> prev_remapped =
|
||||
ToQuery(previous_id_map, previous->def);
|
||||
std::optional<QueryVar::Def> current_remapped_def =
|
||||
std::optional<QueryVar::Def> current_remapped =
|
||||
ToQuery(current_id_map, current->def);
|
||||
if (current_remapped_def &&
|
||||
previous_remapped_def != current_remapped_def &&
|
||||
!current_remapped_def->detailed_name.empty())
|
||||
vars_def_update.push_back(QueryVar::DefUpdate(
|
||||
current->usr, std::move(*current_remapped_def)));
|
||||
if (current_remapped && !(prev_remapped == current_remapped) &&
|
||||
!current_remapped->detailed_name.empty())
|
||||
vars_def_update.push_back(
|
||||
QueryVar::DefUpdate(current->usr, std::move(*current_remapped)));
|
||||
|
||||
PROCESS_UPDATE_DIFF(QueryVarId, vars_declarations, declarations, Use);
|
||||
PROCESS_UPDATE_DIFF(QueryVarId, vars_uses, uses, Use);
|
||||
|
Loading…
Reference in New Issue
Block a user