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 index = GetOffsetForPosition(position, content);
int start = index; 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) { while (start > 0) {
char c = content[start - 1]; char c = content[start - 1];
if (isalnum(c) || c == '_') { if (isalnum(c) || c == '_' || c == ':') {
--start; --start;
} else { } else {
break; break;
} }
} }
while ((end + 1) < content.size()) { while (end < (int)content.size()) {
char c = content[end + 1]; char c = content[end];
if (isalnum(c) || c == '_') { if (isalnum(c) || c == '_') {
++end; ++end;
} else { } 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) { 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. // Find the best match of the identifier at point.
if (!has_symbol && db->symbols.size()) { if (!has_symbol && db->symbols.size()) {
const std::string& buffer = working_file->buffer_content; const std::string& buffer = working_file->buffer_content;
int start = GetOffsetForPosition(request->params.position, buffer); std::string query = LexWordAroundPos(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);
int best_score = kMinScore; int best_score = kMinScore;
int best_i = 0; int best_i = 0;
std::vector<int> score, dp; std::vector<int> score, dp;
for (int i = 0; i < (int)db->symbols.size(); ++i) { for (int i = 0; i < (int)db->symbols.size(); ++i) {
std::string_view short_name = db->GetSymbolShortName(i); std::string_view detailed_name = db->GetSymbolDetailedName(i);
if (short_name.size() > score.size()) { if (detailed_name.size() > score.size()) {
score.resize(short_name.size()); score.resize(detailed_name.size());
dp.resize(short_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) { if (t > best_score) {
best_score = t; best_score = t;
best_i = i; best_i = i;

View File

@ -79,12 +79,7 @@ struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
inserted_results.reserve(config->maxWorkspaceSearchResults); inserted_results.reserve(config->maxWorkspaceSearchResults);
result_indices.reserve(config->maxWorkspaceSearchResults); result_indices.reserve(config->maxWorkspaceSearchResults);
// We use detailed_names for exact matches and short_names for fuzzy matches // We use detailed_names without parameters for matching.
// 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.
// Find exact substring matches. // Find exact substring matches.
for (int i = 0; i < db->symbols.size(); ++i) { for (int i = 0; i < db->symbols.size(); ++i) {
@ -112,9 +107,10 @@ struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
query_without_space += c; query_without_space += c;
for (int i = 0; i < db->symbols.size(); ++i) { 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. // 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; continue;
if (InsertSymbolIntoResult(db, working_files, db->symbols[i], if (InsertSymbolIntoResult(db, working_files, db->symbols[i],
@ -131,7 +127,7 @@ struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
// Sort results with a fuzzy matching algorithm. // Sort results with a fuzzy matching algorithm.
int longest = 0; int longest = 0;
for (int i : result_indices) 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> score(longest); // score for each position
std::vector<int> dp( std::vector<int> dp(
@ -139,7 +135,7 @@ struct WorkspaceSymbolHandler : BaseMessageHandler<Ipc_WorkspaceSymbol> {
std::vector<std::pair<int, int>> permutation(result_indices.size()); std::vector<std::pair<int, int>> permutation(result_indices.size());
for (int i = 0; i < int(result_indices.size()); i++) { for (int i = 0; i < int(result_indices.size()); i++) {
permutation[i] = { permutation[i] = {
FuzzyEvaluate(query, db->GetSymbolShortName(result_indices[i]), score, dp), FuzzyEvaluate(query, db->GetSymbolDetailedName(result_indices[i]), score, dp),
i}; i};
} }
std::sort(permutation.begin(), permutation.end(), 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 { std::string_view QueryDatabase::GetSymbolDetailedName(RawId symbol_idx) const {
RawId idx = symbols[symbol_idx].id.id; RawId idx = symbols[symbol_idx].id.id;
switch (symbols[symbol_idx].kind) { switch (symbols[symbol_idx].kind) {
@ -926,8 +927,11 @@ std::string_view QueryDatabase::GetSymbolDetailedName(RawId symbol_idx) const {
return files[idx].def->path; return files[idx].def->path;
break; break;
case SymbolKind::Func: case SymbolKind::Func:
if (funcs[idx].def) if (funcs[idx].def) {
return funcs[idx].def->detailed_name; auto& def = funcs[idx].def;
return std::string_view(def->detailed_name)
.substr(0, def->short_name_offset + def->short_name_size);
}
break; break;
case SymbolKind::Type: case SymbolKind::Type:
if (types[idx].def) if (types[idx].def)

View File

@ -565,7 +565,7 @@ std::string GetDefaultResourceDirectory() {
resource_directory = resource_directory =
resource_directory.substr(1, resource_directory.size() - 2); 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(); std::string executable_path = GetExecutablePath();
size_t pos = executable_path.find_last_of('/'); size_t pos = executable_path.find_last_of('/');
result = executable_path.substr(0, pos + 1); result = executable_path.substr(0, pos + 1);

View File

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