Add is_end to Get{Buffer,Index}PosFrom{Index,Buffer}Pos to get better column alignment

This commit is contained in:
Fangrui Song 2018-01-14 17:16:24 -08:00
parent e04245f185
commit 13728a0fae
4 changed files with 26 additions and 19 deletions

View File

@ -62,7 +62,7 @@ struct TextDocumentDocumentLinkHandler
} }
for (const IndexInclude& include : file->def->includes) { for (const IndexInclude& include : file->def->includes) {
optional<int> buffer_line = optional<int> buffer_line =
working_file->GetBufferPosFromIndexPos(include.line, nullptr); working_file->GetBufferPosFromIndexPos(include.line, nullptr, false);
if (!buffer_line) if (!buffer_line)
continue; continue;

View File

@ -319,7 +319,7 @@ optional<lsPosition> GetLsPosition(WorkingFile* working_file,
return lsPosition(position.line, position.column); return lsPosition(position.line, position.column);
int column = position.column; int column = position.column;
optional<int> start = working_file->GetBufferPosFromIndexPos(position.line, &column); optional<int> start = working_file->GetBufferPosFromIndexPos(position.line, &column, false);
if (!start) if (!start)
return nullopt; return nullopt;
@ -335,9 +335,9 @@ optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
int start_column = location.start.column, end_column = location.end.column; int start_column = location.start.column, end_column = location.end.column;
optional<int> start = optional<int> start =
working_file->GetBufferPosFromIndexPos(location.start.line, &start_column); working_file->GetBufferPosFromIndexPos(location.start.line, &start_column, false);
optional<int> end = optional<int> end =
working_file->GetBufferPosFromIndexPos(location.end.line, &end_column); working_file->GetBufferPosFromIndexPos(location.end.line, &end_column, true);
if (!start || !end) if (!start || !end)
return nullopt; return nullopt;
@ -483,8 +483,8 @@ std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
int target_line = position.line; int target_line = position.line;
int target_column = position.character; int target_column = position.character;
if (working_file) { if (working_file) {
optional<int> index_line = optional<int> index_line = working_file->GetIndexPosFromBufferPos(
working_file->GetIndexPosFromBufferPos(target_line, &target_column); target_line, &target_column, false);
if (index_line) if (index_line)
target_line = *index_line; target_line = *index_line;
} }

View File

@ -97,7 +97,7 @@ std::vector<int> EditDistanceVector(std::string a, std::string b) {
// Find matching position of |a[column]| in |b|. // Find matching position of |a[column]| in |b|.
// This is actually a single step of Hirschberg's sequence alignment algorithm. // 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; int head = 0, tail = 0;
while (head < (int)a.size() && head < (int)b.size() && a[head] == b[head]) while (head < (int)a.size() && head < (int)b.size() && a[head] == b[head])
head++; head++;
@ -106,12 +106,12 @@ int AlignColumn(const std::string& a, int column, std::string b) {
tail++; tail++;
if (column < head) if (column < head)
return column; return column;
if ((int)a.size() - tail <= column) if ((int)a.size() - tail < column)
return column + b.size() - a.size(); return column + b.size() - a.size();
if (std::max(a.size(), b.size()) - head - tail >= kMaxColumnAlignSize) if (std::max(a.size(), b.size()) - head - tail >= kMaxColumnAlignSize)
return std::min(column, (int)b.size()); return std::min(column, (int)b.size());
// b[head, tail) // b[head, b.size() - tail)
b = b.substr(head, b.size() - tail - head); b = b.substr(head, b.size() - tail - head);
// left[i] = cost of aligning a[head, column) to b[head, head + i) // 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; int best = 0, best_cost = INT_MAX;
for (size_t i = 0; i < left.size(); i++) { for (size_t i = 0; i < left.size(); i++) {
int cost = left[i] + right[i]; int cost = left[i] + right[i];
if (cost < best_cost) { if (is_end ? cost < best_cost : cost <= best_cost) {
best_cost = cost; best_cost = cost;
best = i; best = i;
} }
@ -143,12 +143,14 @@ optional<int> FindMatchingLine(const std::vector<std::string>& index_lines,
const std::vector<int>& index_to_buffer, const std::vector<int>& index_to_buffer,
int line, int line,
int* column, int* column,
const std::vector<std::string>& buffer_lines) { const std::vector<std::string>& buffer_lines,
bool is_end) {
// If this is a confident mapping, returns. // If this is a confident mapping, returns.
if (index_to_buffer[line] >= 0) { if (index_to_buffer[line] >= 0) {
int ret = index_to_buffer[line]; int ret = index_to_buffer[line];
if (column) if (column)
*column = AlignColumn(index_lines[line], *column, buffer_lines[ret]); *column =
AlignColumn(index_lines[line], *column, buffer_lines[ret], is_end);
return ret; return ret;
} }
@ -174,7 +176,8 @@ optional<int> FindMatchingLine(const std::vector<std::string>& index_lines,
} }
} }
if (column) if (column)
*column = AlignColumn(index_lines[line], *column, buffer_lines[best]); *column =
AlignColumn(index_lines[line], *column, buffer_lines[best], is_end);
return best; return best;
} }
@ -300,7 +303,7 @@ void WorkingFile::ComputeLineMapping() {
buffer_to_index[index_to_buffer[i]] = i; buffer_to_index[index_to_buffer[i]] = i;
} }
optional<int> WorkingFile::GetBufferPosFromIndexPos(int line, int* column) { optional<int> WorkingFile::GetBufferPosFromIndexPos(int line, int* column, bool is_end) {
// The implementation is simple but works pretty well for most cases. We // 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 // lookup the line contents in the indexed file contents, and try to find the
// most similar line in the current buffer file. // most similar line in the current buffer file.
@ -323,10 +326,11 @@ optional<int> WorkingFile::GetBufferPosFromIndexPos(int line, int* column) {
if (index_to_buffer.empty()) if (index_to_buffer.empty())
ComputeLineMapping(); 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<int> WorkingFile::GetIndexPosFromBufferPos(int line, int* column) { optional<int> WorkingFile::GetIndexPosFromBufferPos(int line, int* column, bool is_end) {
// See GetBufferLineFromIndexLine for additional comments. // See GetBufferLineFromIndexLine for additional comments.
// Note: |index_line| and |buffer_line| are 1-based. // Note: |index_line| and |buffer_line| are 1-based.
@ -340,7 +344,8 @@ optional<int> WorkingFile::GetIndexPosFromBufferPos(int line, int* column) {
if (buffer_to_index.empty()) if (buffer_to_index.empty())
ComputeLineMapping(); 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( std::string WorkingFile::FindClosestCallNameInBuffer(

View File

@ -40,10 +40,12 @@ struct WorkingFile {
// Finds the buffer line number which maps to index line number |line|. // Finds the buffer line number which maps to index line number |line|.
// Also resolves |column| if not NULL. // Also resolves |column| if not NULL.
optional<int> 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<int> GetBufferPosFromIndexPos(int line, int* column, bool is_end);
// Finds the index line number which maps to buffer line number |line|. // Finds the index line number which maps to buffer line number |line|.
// Also resolves |column| if not NULL. // Also resolves |column| if not NULL.
optional<int> GetIndexPosFromBufferPos(int line, int* column); optional<int> GetIndexPosFromBufferPos(int line, int* column, bool is_end);
// TODO: Move FindClosestCallNameInBuffer and FindStableCompletionSource into // TODO: Move FindClosestCallNameInBuffer and FindStableCompletionSource into
// lex_utils.h/cc // lex_utils.h/cc