Rename Get{Buffer,Index}LineFrom{Index,Buffer}Line in preparation for column alignment.

This commit is contained in:
Fangrui Song 2018-01-14 14:24:47 -08:00
parent ed96b807dd
commit 2c4783c904
4 changed files with 43 additions and 18 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->GetBufferLineFromIndexLine(include.line); working_file->GetBufferPosFromIndexPos(include.line, nullptr);
if (!buffer_line) if (!buffer_line)
continue; continue;

View File

@ -318,11 +318,12 @@ optional<lsPosition> GetLsPosition(WorkingFile* working_file,
if (!working_file) if (!working_file)
return lsPosition(position.line, position.column); return lsPosition(position.line, position.column);
optional<int> start = working_file->GetBufferLineFromIndexLine(position.line); int column = position.column;
optional<int> start = working_file->GetBufferPosFromIndexPos(position.line, &column);
if (!start) if (!start)
return nullopt; return nullopt;
return lsPosition(*start, position.column); return lsPosition(*start, column);
} }
optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) { optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
@ -332,10 +333,11 @@ optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
lsPosition(location.end.line, location.end.column)); lsPosition(location.end.line, location.end.column));
} }
int start_column = location.start.column, end_column = location.end.column;
optional<int> start = optional<int> start =
working_file->GetBufferLineFromIndexLine(location.start.line); working_file->GetBufferPosFromIndexPos(location.start.line, &start_column);
optional<int> end = optional<int> end =
working_file->GetBufferLineFromIndexLine(location.end.line); working_file->GetBufferPosFromIndexPos(location.end.line, &end_column);
if (!start || !end) if (!start || !end)
return nullopt; return nullopt;
@ -348,8 +350,8 @@ optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
if (*end < *start) if (*end < *start)
*end = *start + (location.end.line - location.start.line); *end = *start + (location.end.line - location.start.line);
return lsRange(lsPosition(*start, location.start.column), return lsRange(lsPosition(*start, start_column),
lsPosition(*end, location.end.column)); lsPosition(*end, end_column));
} }
lsDocumentUri GetLsDocumentUri(QueryDatabase* db, lsDocumentUri GetLsDocumentUri(QueryDatabase* db,
@ -482,7 +484,7 @@ std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
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->GetIndexLineFromBufferLine(target_line); working_file->GetIndexPosFromBufferPos(target_line, &target_column);
if (index_line) if (index_line)
target_line = *index_line; target_line = *index_line;
} }

View File

@ -8,6 +8,7 @@
#include <algorithm> #include <algorithm>
#include <climits> #include <climits>
#include <numeric>
namespace { namespace {
@ -68,12 +69,34 @@ int MyersDiff(const std::string& a, const std::string& b, int threshold) {
return MyersDiff(a.data(), a.size(), b.data(), b.size(), threshold); return MyersDiff(a.data(), a.size(), b.data(), b.size(), threshold);
} }
// Computes Levenshtein edit distance with O(N*M) Needleman-Wunsch algorithm
// and returns a distance vector where d[i] = cost of aligning a to b[0,i).
//
// Myers' diff algorithm is used to find best matching line while this one is
// used to align a single column because Myers' needs some twiddling to return
// distance vector.
std::vector<int> LevenshteinDistance(std::string a, std::string b) {
std::vector<int> d(b.size() + 1);
std::iota(d.begin(), d.end(), 0);
for (int i = 0; i < (int)a.size(); i++) {
int ul = d[0];
d[0] = i + 1;
for (int j = 0; j < (int)b.size(); j++) {
int t = d[j + 1];
d[j + 1] = a[i] == b[j] ? ul : std::min(ul, std::min(d[j], d[j + 1])) + 1;
ul = t;
}
}
return d;
}
// Find matching buffer line of index_lines[line]. // Find matching buffer line of index_lines[line].
// By symmetry, this can also be used to find matching index line of a buffer // By symmetry, this can also be used to find matching index line of a buffer
// line. // line.
optional<int> FindMatchingLine(const std::vector<std::string>& index_lines, 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,
const std::vector<std::string>& buffer_lines) { const std::vector<std::string>& buffer_lines) {
// 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)
@ -225,7 +248,7 @@ void WorkingFile::ComputeLineMapping() {
buffer_to_index[index_to_buffer[i]] = i; buffer_to_index[index_to_buffer[i]] = i;
} }
optional<int> WorkingFile::GetBufferLineFromIndexLine(int line) { optional<int> WorkingFile::GetBufferPosFromIndexPos(int line, int* column) {
// 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.
@ -248,10 +271,10 @@ optional<int> WorkingFile::GetBufferLineFromIndexLine(int line) {
if (index_to_buffer.empty()) if (index_to_buffer.empty())
ComputeLineMapping(); ComputeLineMapping();
return FindMatchingLine(index_lines, index_to_buffer, line, buffer_lines); return FindMatchingLine(index_lines, index_to_buffer, line, column, buffer_lines);
} }
optional<int> WorkingFile::GetIndexLineFromBufferLine(int line) { optional<int> WorkingFile::GetIndexPosFromBufferPos(int line, int* column) {
// 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.
@ -265,7 +288,7 @@ optional<int> WorkingFile::GetIndexLineFromBufferLine(int line) {
if (buffer_to_index.empty()) if (buffer_to_index.empty())
ComputeLineMapping(); ComputeLineMapping();
return FindMatchingLine(buffer_lines, buffer_to_index, line, index_lines); return FindMatchingLine(buffer_lines, buffer_to_index, line, column, index_lines);
} }
std::string WorkingFile::FindClosestCallNameInBuffer( std::string WorkingFile::FindClosestCallNameInBuffer(

View File

@ -38,12 +38,12 @@ struct WorkingFile {
// This should be called whenever |buffer_content| has changed. // This should be called whenever |buffer_content| has changed.
void OnBufferContentUpdated(); void OnBufferContentUpdated();
// Find the buffer-line which should be shown for |indexed_line|. This // Finds the buffer line number which maps to index line number |line|.
// accepts and returns 1-based lines. // Also resolves |column| if not NULL.
optional<int> GetBufferLineFromIndexLine(int indexed_line); optional<int> GetBufferPosFromIndexPos(int line, int* column);
// Find the indexed-line which should be shown for |buffer_line|. This // Finds the index line number which maps to buffer line number |line|.
// accepts and returns 1-based lines. // Also resolves |column| if not NULL.
optional<int> GetIndexLineFromBufferLine(int buffer_line); optional<int> GetIndexPosFromBufferPos(int line, int* column);
// TODO: Move FindClosestCallNameInBuffer and FindStableCompletionSource into // TODO: Move FindClosestCallNameInBuffer and FindStableCompletionSource into
// lex_utils.h/cc // lex_utils.h/cc