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) {
optional<int> buffer_line =
working_file->GetBufferLineFromIndexLine(include.line);
working_file->GetBufferPosFromIndexPos(include.line, nullptr);
if (!buffer_line)
continue;

View File

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

View File

@ -8,6 +8,7 @@
#include <algorithm>
#include <climits>
#include <numeric>
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);
}
// 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].
// By symmetry, this can also be used to find matching index line of a buffer
// line.
optional<int> FindMatchingLine(const std::vector<std::string>& index_lines,
const std::vector<int>& index_to_buffer,
int line,
int* column,
const std::vector<std::string>& buffer_lines) {
// If this is a confident mapping, returns.
if (index_to_buffer[line] >= 0)
@ -225,7 +248,7 @@ void WorkingFile::ComputeLineMapping() {
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
// lookup the line contents in the indexed file contents, and try to find the
// most similar line in the current buffer file.
@ -248,10 +271,10 @@ optional<int> WorkingFile::GetBufferLineFromIndexLine(int line) {
if (index_to_buffer.empty())
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.
// Note: |index_line| and |buffer_line| are 1-based.
@ -265,7 +288,7 @@ optional<int> WorkingFile::GetIndexLineFromBufferLine(int line) {
if (buffer_to_index.empty())
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(

View File

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