From 13728a0fae062e6d5e13f6c06bdb812399128b97 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 14 Jan 2018 17:16:24 -0800 Subject: [PATCH] Add is_end to Get{Buffer,Index}PosFrom{Index,Buffer}Pos to get better column alignment --- src/messages/text_document_document_link.cc | 2 +- src/query_utils.cc | 10 ++++---- src/working_files.cc | 27 ++++++++++++--------- src/working_files.h | 6 +++-- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/messages/text_document_document_link.cc b/src/messages/text_document_document_link.cc index cb51a159..bbe8cbde 100644 --- a/src/messages/text_document_document_link.cc +++ b/src/messages/text_document_document_link.cc @@ -62,7 +62,7 @@ struct TextDocumentDocumentLinkHandler } for (const IndexInclude& include : file->def->includes) { optional buffer_line = - working_file->GetBufferPosFromIndexPos(include.line, nullptr); + working_file->GetBufferPosFromIndexPos(include.line, nullptr, false); if (!buffer_line) continue; diff --git a/src/query_utils.cc b/src/query_utils.cc index 90d62b74..e3d28b55 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -319,7 +319,7 @@ optional GetLsPosition(WorkingFile* working_file, return lsPosition(position.line, position.column); int column = position.column; - optional start = working_file->GetBufferPosFromIndexPos(position.line, &column); + optional start = working_file->GetBufferPosFromIndexPos(position.line, &column, false); if (!start) return nullopt; @@ -335,9 +335,9 @@ optional GetLsRange(WorkingFile* working_file, const Range& location) { int start_column = location.start.column, end_column = location.end.column; optional start = - working_file->GetBufferPosFromIndexPos(location.start.line, &start_column); + working_file->GetBufferPosFromIndexPos(location.start.line, &start_column, false); optional end = - working_file->GetBufferPosFromIndexPos(location.end.line, &end_column); + working_file->GetBufferPosFromIndexPos(location.end.line, &end_column, true); if (!start || !end) return nullopt; @@ -483,8 +483,8 @@ std::vector FindSymbolsAtLocation(WorkingFile* working_file, int target_line = position.line; int target_column = position.character; if (working_file) { - optional index_line = - working_file->GetIndexPosFromBufferPos(target_line, &target_column); + optional index_line = working_file->GetIndexPosFromBufferPos( + target_line, &target_column, false); if (index_line) target_line = *index_line; } diff --git a/src/working_files.cc b/src/working_files.cc index 8a9f0f21..9b98b44f 100644 --- a/src/working_files.cc +++ b/src/working_files.cc @@ -97,7 +97,7 @@ std::vector EditDistanceVector(std::string a, std::string b) { // Find matching position of |a[column]| in |b|. // This is actually a single step of Hirschberg's sequence alignment algorithm. -int AlignColumn(const std::string& a, int column, std::string b) { +int AlignColumn(const std::string& a, int column, std::string b, bool is_end) { int head = 0, tail = 0; while (head < (int)a.size() && head < (int)b.size() && a[head] == b[head]) head++; @@ -106,12 +106,12 @@ int AlignColumn(const std::string& a, int column, std::string b) { tail++; if (column < head) return column; - if ((int)a.size() - tail <= column) + if ((int)a.size() - tail < column) return column + b.size() - a.size(); if (std::max(a.size(), b.size()) - head - tail >= kMaxColumnAlignSize) return std::min(column, (int)b.size()); - // b[head, tail) + // b[head, b.size() - tail) b = b.substr(head, b.size() - tail - head); // left[i] = cost of aligning a[head, column) to b[head, head + i) @@ -128,7 +128,7 @@ int AlignColumn(const std::string& a, int column, std::string b) { int best = 0, best_cost = INT_MAX; for (size_t i = 0; i < left.size(); i++) { int cost = left[i] + right[i]; - if (cost < best_cost) { + if (is_end ? cost < best_cost : cost <= best_cost) { best_cost = cost; best = i; } @@ -143,12 +143,14 @@ optional FindMatchingLine(const std::vector& index_lines, const std::vector& index_to_buffer, int line, int* column, - const std::vector& buffer_lines) { + const std::vector& buffer_lines, + bool is_end) { // If this is a confident mapping, returns. if (index_to_buffer[line] >= 0) { int ret = index_to_buffer[line]; if (column) - *column = AlignColumn(index_lines[line], *column, buffer_lines[ret]); + *column = + AlignColumn(index_lines[line], *column, buffer_lines[ret], is_end); return ret; } @@ -174,7 +176,8 @@ optional FindMatchingLine(const std::vector& index_lines, } } if (column) - *column = AlignColumn(index_lines[line], *column, buffer_lines[best]); + *column = + AlignColumn(index_lines[line], *column, buffer_lines[best], is_end); return best; } @@ -300,7 +303,7 @@ void WorkingFile::ComputeLineMapping() { buffer_to_index[index_to_buffer[i]] = i; } -optional WorkingFile::GetBufferPosFromIndexPos(int line, int* column) { +optional WorkingFile::GetBufferPosFromIndexPos(int line, int* column, bool is_end) { // The implementation is simple but works pretty well for most cases. We // lookup the line contents in the indexed file contents, and try to find the // most similar line in the current buffer file. @@ -323,10 +326,11 @@ optional WorkingFile::GetBufferPosFromIndexPos(int line, int* column) { if (index_to_buffer.empty()) ComputeLineMapping(); - return FindMatchingLine(index_lines, index_to_buffer, line, column, buffer_lines); + return FindMatchingLine(index_lines, index_to_buffer, line, column, + buffer_lines, is_end); } -optional WorkingFile::GetIndexPosFromBufferPos(int line, int* column) { +optional WorkingFile::GetIndexPosFromBufferPos(int line, int* column, bool is_end) { // See GetBufferLineFromIndexLine for additional comments. // Note: |index_line| and |buffer_line| are 1-based. @@ -340,7 +344,8 @@ optional WorkingFile::GetIndexPosFromBufferPos(int line, int* column) { if (buffer_to_index.empty()) ComputeLineMapping(); - return FindMatchingLine(buffer_lines, buffer_to_index, line, column, index_lines); + return FindMatchingLine(buffer_lines, buffer_to_index, line, column, + index_lines, is_end); } std::string WorkingFile::FindClosestCallNameInBuffer( diff --git a/src/working_files.h b/src/working_files.h index ab115db0..b1554e3f 100644 --- a/src/working_files.h +++ b/src/working_files.h @@ -40,10 +40,12 @@ struct WorkingFile { // Finds the buffer line number which maps to index line number |line|. // Also resolves |column| if not NULL. - optional GetBufferPosFromIndexPos(int line, int* column); + // When resolving a range, use is_end = false for begin() and is_end = + // true for end() to get a better alignment of |column|. + optional GetBufferPosFromIndexPos(int line, int* column, bool is_end); // Finds the index line number which maps to buffer line number |line|. // Also resolves |column| if not NULL. - optional GetIndexPosFromBufferPos(int line, int* column); + optional GetIndexPosFromBufferPos(int line, int* column, bool is_end); // TODO: Move FindClosestCallNameInBuffer and FindStableCompletionSource into // lex_utils.h/cc