mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 07:35:08 +00:00
Better textDocument/definition heuristic for T::name style dependent names
This commit is contained in:
parent
53138afabd
commit
39dfe052f5
@ -128,10 +128,15 @@ struct Handler_TextDocumentDefinition
|
|||||||
lsPosition position = request->params.position;
|
lsPosition position = request->params.position;
|
||||||
const std::string& buffer = working_file->buffer_content;
|
const std::string& buffer = working_file->buffer_content;
|
||||||
std::string_view query = LexIdentifierAroundPos(position, buffer);
|
std::string_view query = LexIdentifierAroundPos(position, buffer);
|
||||||
bool has_scope = query.find(':') != std::string::npos;
|
std::string_view short_query = query;
|
||||||
|
{
|
||||||
|
auto pos = query.rfind(':');
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
short_query = query.substr(pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
// For symbols whose short/detailed names contain |query| as a
|
// For symbols whose short/detailed names contain |query| as a
|
||||||
// substring, we use the tuple <length difference, matching position,
|
// substring, we use the tuple <length difference, negative position,
|
||||||
// not in the same file, line distance> to find the best match.
|
// not in the same file, line distance> to find the best match.
|
||||||
std::tuple<int, int, bool, int> best_score{INT_MAX, 0, true, 0};
|
std::tuple<int, int, bool, int> best_score{INT_MAX, 0, true, 0};
|
||||||
int best_i = -1;
|
int best_i = -1;
|
||||||
@ -139,23 +144,30 @@ struct Handler_TextDocumentDefinition
|
|||||||
if (db->symbols[i].kind == SymbolKind::Invalid)
|
if (db->symbols[i].kind == SymbolKind::Invalid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string_view name = has_scope ? db->GetSymbolDetailedName(i)
|
std::string_view name = short_query.size() < query.size()
|
||||||
|
? db->GetSymbolDetailedName(i)
|
||||||
: db->GetSymbolShortName(i);
|
: db->GetSymbolShortName(i);
|
||||||
auto pos = name.find(query);
|
auto pos = name.rfind(short_query);
|
||||||
if (pos == std::string::npos)
|
if (pos == std::string::npos)
|
||||||
continue;
|
continue;
|
||||||
Maybe<Use> use = GetDefinitionSpell(db, db->symbols[i]);
|
if (Maybe<Use> use = GetDefinitionSpell(db, db->symbols[i])) {
|
||||||
if (!use)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::tuple<int, int, bool, int> score{
|
std::tuple<int, int, bool, int> score{
|
||||||
int(name.size() - query.size()), int(pos), use->file != file_id,
|
int(name.size() - short_query.size()), -pos,
|
||||||
|
use->file != file_id,
|
||||||
std::abs(use->range.start.line - position.line)};
|
std::abs(use->range.start.line - position.line)};
|
||||||
|
// Update the score with qualified name if the qualified name
|
||||||
|
// occurs in |name|.
|
||||||
|
pos = name.rfind(query);
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
std::get<0>(score) = int(name.size() - query.size());
|
||||||
|
std::get<1>(score) = -pos;
|
||||||
|
}
|
||||||
if (score < best_score) {
|
if (score < best_score) {
|
||||||
best_score = score;
|
best_score = score;
|
||||||
best_i = i;
|
best_i = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (best_i != -1) {
|
if (best_i != -1) {
|
||||||
Maybe<Use> use = GetDefinitionSpell(db, db->symbols[best_i]);
|
Maybe<Use> use = GetDefinitionSpell(db, db->symbols[best_i]);
|
||||||
assert(use);
|
assert(use);
|
||||||
|
@ -77,13 +77,13 @@ uint64_t HashUsr(const char* s, size_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See http://stackoverflow.com/a/2072890
|
// See http://stackoverflow.com/a/2072890
|
||||||
bool EndsWith(const std::string& value, const std::string& ending) {
|
bool EndsWith(std::string_view value, std::string_view ending) {
|
||||||
if (ending.size() > value.size())
|
if (ending.size() > value.size())
|
||||||
return false;
|
return false;
|
||||||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartsWith(const std::string& value, const std::string& start) {
|
bool StartsWith(std::string_view value, std::string_view start) {
|
||||||
if (start.size() > value.size())
|
if (start.size() > value.size())
|
||||||
return false;
|
return false;
|
||||||
return std::equal(start.begin(), start.end(), value.begin());
|
return std::equal(start.begin(), start.end(), value.begin());
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <optional.h>
|
#include <optional.h>
|
||||||
|
#include <string_view.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -22,8 +23,8 @@ uint64_t HashUsr(const char* s);
|
|||||||
uint64_t HashUsr(const char* s, size_t n);
|
uint64_t HashUsr(const char* s, size_t n);
|
||||||
|
|
||||||
// Returns true if |value| starts/ends with |start| or |ending|.
|
// Returns true if |value| starts/ends with |start| or |ending|.
|
||||||
bool StartsWith(const std::string& value, const std::string& start);
|
bool StartsWith(std::string_view value, std::string_view start);
|
||||||
bool EndsWith(const std::string& value, const std::string& ending);
|
bool EndsWith(std::string_view value, std::string_view ending);
|
||||||
bool AnyStartsWith(const std::vector<std::string>& values,
|
bool AnyStartsWith(const std::vector<std::string>& values,
|
||||||
const std::string& start);
|
const std::string& start);
|
||||||
bool StartsWithAny(const std::string& value,
|
bool StartsWithAny(const std::string& value,
|
||||||
|
Loading…
Reference in New Issue
Block a user