Fix default -resource-dir when clang -print-resource-dir contains ..

Also makes textDocument/definition in comments takes scope resolution
into account, and use detailed names (for Func, without parameters) for workspace/symbol
This commit is contained in:
Fangrui Song 2018-02-12 23:20:08 -08:00
parent 10437aa642
commit 72e654ffed
6 changed files with 28 additions and 37 deletions

View File

@ -201,19 +201,20 @@ std::string LexWordAroundPos(lsPosition position, const std::string& content) {
int index = GetOffsetForPosition(position, content);
int start = index;
int end = index;
int end = index + 1;
// We search for : before the cursor but not after to get the qualifier.
while (start > 0) {
char c = content[start - 1];
if (isalnum(c) || c == '_') {
if (isalnum(c) || c == '_' || c == ':') {
--start;
} else {
break;
}
}
while ((end + 1) < content.size()) {
char c = content[end + 1];
while (end < (int)content.size()) {
char c = content[end];
if (isalnum(c) || c == '_') {
++end;
} else {
@ -221,7 +222,7 @@ std::string LexWordAroundPos(lsPosition position, const std::string& content) {
}
}
return content.substr(start, end - start + 1);
return content.substr(start, end - start);
}
bool SubsequenceMatch(std::string_view search, std::string_view content) {

View File

@ -131,24 +131,18 @@ struct TextDocumentDefinitionHandler
// Find the best match of the identifier at point.
if (!has_symbol && db->symbols.size()) {
const std::string& buffer = working_file->buffer_content;
int start = GetOffsetForPosition(request->params.position, buffer);
int end = start;
while (start > 0 && isalnum(buffer[start - 1]))
start--;
while (isalnum(buffer[end]))
end++;
auto query = std::string_view(buffer).substr(start, end - start);
std::string query = LexWordAroundPos(request->params.position, buffer);
int best_score = kMinScore;
int best_i = 0;
std::vector<int> score, dp;
for (int i = 0; i < (int)db->symbols.size(); ++i) {
std::string_view short_name = db->GetSymbolShortName(i);
if (short_name.size() > score.size()) {
score.resize(short_name.size());
dp.resize(short_name.size());
std::string_view detailed_name = db->GetSymbolDetailedName(i);
if (detailed_name.size() > score.size()) {
score.resize(detailed_name.size());
dp.resize(detailed_name.size());
}
int t = FuzzyEvaluate(query, short_name, score, dp);
int t = FuzzyEvaluate(query, detailed_name, score, dp);
if (t > best_score) {
best_score = t;
best_i = i;

View File

@ -79,12 +79,7 @@ struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
inserted_results.reserve(config->maxWorkspaceSearchResults);
result_indices.reserve(config->maxWorkspaceSearchResults);
// We use detailed_names for exact matches and short_names for fuzzy matches
// because otherwise the fuzzy match is likely to match on parameter names
// and the like.
// TODO: make detailed_names not include function parameter information (or
// introduce additional metadata) so that we can do fuzzy search with
// detailed_names.
// We use detailed_names without parameters for matching.
// Find exact substring matches.
for (int i = 0; i < db->symbols.size(); ++i) {
@ -112,9 +107,10 @@ struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
query_without_space += c;
for (int i = 0; i < db->symbols.size(); ++i) {
if (SubsequenceMatch(query_without_space, db->GetSymbolShortName(i))) {
std::string_view detailed_name = db->GetSymbolDetailedName(i);
if (SubsequenceMatch(query_without_space, detailed_name)) {
// Do not show the same entry twice.
if (!inserted_results.insert(std::string(db->GetSymbolDetailedName(i))).second)
if (!inserted_results.insert(std::string(detailed_name)).second)
continue;
if (InsertSymbolIntoResult(db, working_files, db->symbols[i],
@ -131,7 +127,7 @@ struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
// Sort results with a fuzzy matching algorithm.
int longest = 0;
for (int i : result_indices)
longest = std::max(longest, int(db->GetSymbolShortName(i).size()));
longest = std::max(longest, int(db->GetSymbolDetailedName(i).size()));
std::vector<int> score(longest); // score for each position
std::vector<int> dp(
@ -139,7 +135,7 @@ struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
std::vector<std::pair<int, int>> permutation(result_indices.size());
for (int i = 0; i < int(result_indices.size()); i++) {
permutation[i] = {
FuzzyEvaluate(query, db->GetSymbolShortName(result_indices[i]), score, dp),
FuzzyEvaluate(query, db->GetSymbolDetailedName(result_indices[i]), score, dp),
i};
}
std::sort(permutation.begin(), permutation.end(),

View File

@ -916,6 +916,7 @@ void QueryDatabase::UpdateSymbols(Maybe<Id<void>>* symbol_idx,
}
}
// For Func, the returned name does not include parameters.
std::string_view QueryDatabase::GetSymbolDetailedName(RawId symbol_idx) const {
RawId idx = symbols[symbol_idx].id.id;
switch (symbols[symbol_idx].kind) {
@ -926,8 +927,11 @@ std::string_view QueryDatabase::GetSymbolDetailedName(RawId symbol_idx) const {
return files[idx].def->path;
break;
case SymbolKind::Func:
if (funcs[idx].def)
return funcs[idx].def->detailed_name;
if (funcs[idx].def) {
auto& def = funcs[idx].def;
return std::string_view(def->detailed_name)
.substr(0, def->short_name_offset + def->short_name_size);
}
break;
case SymbolKind::Type:
if (types[idx].def)

View File

@ -565,7 +565,7 @@ std::string GetDefaultResourceDirectory() {
resource_directory =
resource_directory.substr(1, resource_directory.size() - 2);
}
if (resource_directory.find("..") != std::string::npos) {
if (resource_directory.compare(0, 2, "..") == 0) {
std::string executable_path = GetExecutablePath();
size_t pos = executable_path.find_last_of('/');
result = executable_path.substr(0, pos + 1);

View File

@ -216,13 +216,9 @@ def configure(ctx):
# Ask llvm-config for cflags and ldflags
ctx.find_program(ctx.options.llvm_config, msg='checking for llvm-config', var='LLVM_CONFIG', mandatory=False)
if len(ctx.options.llvm_config):
ctx.env.rpath = [str(subprocess.check_output(
[ctx.options.llvm_config, '--libdir'],
stderr=subprocess.STDOUT).decode()).strip()]
else:
# If `--llvm-config=` (empty)
ctx.env.rpath = []
if ctx.options.clang_prefix:
ctx.start_msg('Checking for clang prefix')