mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-16 21:58:08 +00:00
Unify {all,raw}_buffer_lines
Also remove GetBufferLineContentFromIndexLine
This commit is contained in:
parent
865d567c10
commit
f78d87ded3
@ -35,14 +35,15 @@ optional<int> FindIncludeLine(const std::vector<std::string>& lines,
|
||||
int last_line_compare = 1;
|
||||
|
||||
for (int line = 0; line < (int)lines.size(); ++line) {
|
||||
if (!StartsWith(lines[line], "#include")) {
|
||||
std::string text = Trim(lines[line]);
|
||||
if (!StartsWith(text, "#include")) {
|
||||
last_line_compare = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
last_include_line = line;
|
||||
|
||||
int current_line_compare = full_include_line.compare(lines[line]);
|
||||
int current_line_compare = full_include_line.compare(text);
|
||||
if (current_line_compare == 0)
|
||||
return nullopt;
|
||||
|
||||
@ -332,7 +333,7 @@ struct TextDocumentCodeActionHandler
|
||||
|
||||
// TODO: auto-insert namespace?
|
||||
|
||||
int default_line = (int)working_file->all_buffer_lines.size();
|
||||
int default_line = (int)working_file->buffer_lines.size();
|
||||
|
||||
// Make sure to call EnsureImplFile before using these. We lazy load
|
||||
// them because computing the values could involve an entire project
|
||||
@ -497,7 +498,7 @@ struct TextDocumentCodeActionHandler
|
||||
include_insert_strings) {
|
||||
lsTextEdit edit;
|
||||
optional<int> include_line = FindIncludeLine(
|
||||
working_file->all_buffer_lines, include_insert_string);
|
||||
working_file->buffer_lines, include_insert_string);
|
||||
if (!include_line)
|
||||
continue;
|
||||
|
||||
|
@ -226,8 +226,8 @@ struct TextDocumentCompletionHandler : MessageHandler {
|
||||
// of order, ie, we get completion request before buffer content update.
|
||||
std::string buffer_line;
|
||||
if (request->params.position.line >= 0 &&
|
||||
request->params.position.line < file->raw_buffer_lines.size()) {
|
||||
buffer_line = file->raw_buffer_lines[request->params.position.line];
|
||||
request->params.position.line < file->buffer_lines.size()) {
|
||||
buffer_line = file->buffer_lines[request->params.position.line];
|
||||
}
|
||||
|
||||
// Check for - and : before completing -> or ::, since vscode does not
|
||||
|
@ -61,17 +61,15 @@ struct TextDocumentDocumentLinkHandler
|
||||
return;
|
||||
}
|
||||
for (const IndexInclude& include : file->def->includes) {
|
||||
optional<int> buffer_line;
|
||||
optional<std::string> buffer_line_content =
|
||||
working_file->GetBufferLineContentFromIndexLine(include.line,
|
||||
&buffer_line);
|
||||
if (!buffer_line || !buffer_line_content)
|
||||
optional<int> buffer_line =
|
||||
working_file->GetBufferLineFromIndexLine(include.line);
|
||||
if (!buffer_line)
|
||||
continue;
|
||||
|
||||
// Subtract 1 from line because querydb stores 1-based lines but
|
||||
// vscode expects 0-based lines.
|
||||
optional<lsRange> between_quotes =
|
||||
ExtractQuotedRange(*buffer_line - 1, *buffer_line_content);
|
||||
optional<lsRange> between_quotes = ExtractQuotedRange(
|
||||
*buffer_line - 1, working_file->buffer_lines[*buffer_line - 1]);
|
||||
if (!between_quotes)
|
||||
continue;
|
||||
|
||||
|
@ -64,6 +64,34 @@ int MyersDiff(const std::string& a, const std::string& b, int threshold) {
|
||||
return MyersDiff(a.data(), a.size(), b.data(), b.size(), threshold);
|
||||
}
|
||||
|
||||
// Find matching buffer line with index line and the converse.
|
||||
optional<int> FindMatchingLine(const std::vector<std::string>& index_lines,
|
||||
const std::vector<int>& index_to_buffer,
|
||||
int line,
|
||||
const std::vector<std::string>& buffer_lines) {
|
||||
line--;
|
||||
if (index_to_buffer[line] >= 0)
|
||||
return index_to_buffer[line] + 1;
|
||||
int up = line, down = line;
|
||||
while (--up >= 0 && index_to_buffer[up] < 0) {}
|
||||
while (++down < int(index_to_buffer.size()) && index_to_buffer[down] < 0) {}
|
||||
up = up < 0 ? 0 : index_to_buffer[up];
|
||||
down = down >= int(index_to_buffer.size()) ? int(buffer_lines.size()) - 1
|
||||
: index_to_buffer[down];
|
||||
if (up > down)
|
||||
return nullopt;
|
||||
int best = up, best_dist = kMaxDiff + 1;
|
||||
const std::string& needle = index_lines[line];
|
||||
for (int i = up; i <= down; i++) {
|
||||
int dist = MyersDiff(needle, buffer_lines[i], kMaxDiff);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
return best + 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<CXUnsavedFile> WorkingFiles::Snapshot::AsUnsavedFiles() const {
|
||||
@ -96,8 +124,7 @@ void WorkingFile::SetIndexContent(const std::string& index_content) {
|
||||
}
|
||||
|
||||
void WorkingFile::OnBufferContentUpdated() {
|
||||
all_buffer_lines = ToLines(buffer_content, true /*trim_whitespace*/);
|
||||
raw_buffer_lines = ToLines(buffer_content, false /*trim_whitespace*/);
|
||||
buffer_lines = ToLines(buffer_content, false /*trim_whitespace*/);
|
||||
|
||||
index_to_buffer.clear();
|
||||
buffer_to_index.clear();
|
||||
@ -107,11 +134,11 @@ void WorkingFile::OnBufferContentUpdated() {
|
||||
void WorkingFile::ComputeLineMapping() {
|
||||
std::unordered_map<uint64_t, int> hash_to_unique;
|
||||
std::vector<uint64_t> index_hashes(index_lines.size()),
|
||||
buffer_hashes(all_buffer_lines.size());
|
||||
buffer_hashes(buffer_lines.size());
|
||||
std::vector<int>& from_index = index_to_buffer;
|
||||
std::vector<int>& from_buffer = buffer_to_index;
|
||||
from_index.resize(index_lines.size());
|
||||
from_buffer.resize(all_buffer_lines.size());
|
||||
from_buffer.resize(buffer_lines.size());
|
||||
hash_to_unique.reserve(std::max(from_index.size(), from_buffer.size()));
|
||||
|
||||
// For index line i, set from_index[i] to -1 if line i is duplicated.
|
||||
@ -134,8 +161,9 @@ void WorkingFile::ComputeLineMapping() {
|
||||
// For buffer line i, set from_buffer[i] to -1 if line i is duplicated.
|
||||
i = 0;
|
||||
hash_to_unique.clear();
|
||||
for (auto& line : all_buffer_lines) {
|
||||
uint64_t h = HashUSR(line.data(), line.size());
|
||||
for (auto& line : buffer_lines) {
|
||||
std::string trimmed = Trim(line);
|
||||
uint64_t h = HashUSR(trimmed.data(), trimmed.size());
|
||||
auto it = hash_to_unique.find(h);
|
||||
if (it == hash_to_unique.end()) {
|
||||
hash_to_unique[h] = i;
|
||||
@ -148,17 +176,16 @@ void WorkingFile::ComputeLineMapping() {
|
||||
buffer_hashes[i++] = h;
|
||||
}
|
||||
|
||||
// Align unique lines of index and buffer by setting from_index[i] and
|
||||
// from_buffer[j] pointing to each other.
|
||||
// If index line i is the same as buffer line j, and they are both unique,
|
||||
// align them by pointing from_index[i] to j.
|
||||
i = 0;
|
||||
for (auto h : index_hashes) {
|
||||
if (from_index[i] >= 0) {
|
||||
auto it = hash_to_unique.find(h);
|
||||
if (it != hash_to_unique.end() && it->second >= 0 &&
|
||||
from_buffer[it->second] >= 0) {
|
||||
from_buffer[it->second] >= 0)
|
||||
from_index[i] = it->second;
|
||||
from_buffer[it->second] = i;
|
||||
} else
|
||||
else
|
||||
from_index[i] = -1;
|
||||
}
|
||||
i++;
|
||||
@ -183,7 +210,7 @@ void WorkingFile::ComputeLineMapping() {
|
||||
from_buffer[from_index[i]] = i;
|
||||
}
|
||||
|
||||
optional<int> WorkingFile::GetBufferLineFromIndexLine(int index_line) {
|
||||
optional<int> WorkingFile::GetBufferLineFromIndexLine(int line) {
|
||||
// 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.
|
||||
@ -196,9 +223,9 @@ optional<int> WorkingFile::GetBufferLineFromIndexLine(int index_line) {
|
||||
|
||||
// TODO: reenable this assert once we are using the real indexed file.
|
||||
// assert(index_line >= 1 && index_line <= index_lines.size());
|
||||
if (index_line < 1 || index_line > index_lines.size()) {
|
||||
if (line < 1 || line > index_lines.size()) {
|
||||
loguru::Text stack = loguru::stacktrace();
|
||||
LOG_S(WARNING) << "Bad index_line (got " << index_line << ", expected [1, "
|
||||
LOG_S(WARNING) << "Bad index_line (got " << line << ", expected [1, "
|
||||
<< index_lines.size() << "]) in " << filename
|
||||
<< stack.c_str();
|
||||
return nullopt;
|
||||
@ -206,82 +233,24 @@ optional<int> WorkingFile::GetBufferLineFromIndexLine(int index_line) {
|
||||
|
||||
if (index_to_buffer.empty())
|
||||
ComputeLineMapping();
|
||||
index_line--;
|
||||
if (index_to_buffer[index_line] >= 0)
|
||||
return index_to_buffer[index_line] + 1;
|
||||
int up = index_line, down = index_line;
|
||||
while (--up >= 0 && index_to_buffer[up] < 0) {}
|
||||
while (++down < int(index_to_buffer.size()) && index_to_buffer[down] < 0) {}
|
||||
up = up < 0 ? 0 : index_to_buffer[up];
|
||||
down = down >= int(index_to_buffer.size()) ? buffer_to_index.size() - 1
|
||||
: index_to_buffer[down];
|
||||
if (up > down)
|
||||
return nullopt;
|
||||
int best = up, best_dist = kMaxDiff + 1;
|
||||
const std::string& needle = Trim(index_lines[index_line]);
|
||||
for (int i = up; i <= down; i++) {
|
||||
int dist = MyersDiff(needle, all_buffer_lines[i], kMaxDiff);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
return best + 1;
|
||||
return FindMatchingLine(index_lines, index_to_buffer, line, buffer_lines);
|
||||
}
|
||||
|
||||
optional<int> WorkingFile::GetIndexLineFromBufferLine(int buffer_line) {
|
||||
optional<int> WorkingFile::GetIndexLineFromBufferLine(int line) {
|
||||
// See GetBufferLineFromIndexLine for additional comments.
|
||||
|
||||
// Note: |index_line| and |buffer_line| are 1-based.
|
||||
// assert(buffer_line >= 1 && buffer_line < all_buffer_lines.size());
|
||||
if (buffer_line < 1 || buffer_line > all_buffer_lines.size()) {
|
||||
if (line < 1 || line > buffer_lines.size()) {
|
||||
loguru::Text stack = loguru::stacktrace();
|
||||
LOG_S(WARNING) << "Bad buffer_line (got " << buffer_line
|
||||
<< ", expected [1, " << all_buffer_lines.size() << "]) in "
|
||||
LOG_S(WARNING) << "Bad buffer_line (got " << line
|
||||
<< ", expected [1, " << buffer_lines.size() << "]) in "
|
||||
<< filename << stack.c_str();
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
if (buffer_to_index.empty())
|
||||
ComputeLineMapping();
|
||||
buffer_line--;
|
||||
int up = buffer_line, down = buffer_line;
|
||||
while (--up >= 0 && buffer_to_index[up] < 0) {}
|
||||
while (++down < int(buffer_to_index.size()) && buffer_to_index[down] < 0) {}
|
||||
up = up < 0 ? 0 : buffer_to_index[up];
|
||||
down = down >= int(buffer_to_index.size()) ? index_to_buffer.size() - 1
|
||||
: buffer_to_index[down];
|
||||
if (up > down)
|
||||
return nullopt;
|
||||
int best = up, best_dist = kMaxDiff + 1;
|
||||
const std::string& needle = Trim(raw_buffer_lines[buffer_line]);
|
||||
for (int i = up; i <= down; i++) {
|
||||
int dist = MyersDiff(needle, index_lines[i], kMaxDiff);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
return best + 1;
|
||||
}
|
||||
|
||||
optional<std::string> WorkingFile::GetBufferLineContentFromIndexLine(
|
||||
int indexed_line,
|
||||
optional<int>* out_buffer_line) {
|
||||
optional<int> buffer_line = GetBufferLineFromIndexLine(indexed_line);
|
||||
if (out_buffer_line)
|
||||
*out_buffer_line = buffer_line;
|
||||
|
||||
if (!buffer_line)
|
||||
return nullopt;
|
||||
|
||||
if (*buffer_line < 1 || *buffer_line >= all_buffer_lines.size()) {
|
||||
LOG_S(WARNING) << "GetBufferLineContentFromIndexLine buffer line lookup not"
|
||||
<< " in all_buffer_lines";
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
return all_buffer_lines[*buffer_line - 1];
|
||||
return FindMatchingLine(buffer_lines, buffer_to_index, line, index_lines);
|
||||
}
|
||||
|
||||
std::string WorkingFile::FindClosestCallNameInBuffer(
|
||||
|
@ -17,10 +17,7 @@ struct WorkingFile {
|
||||
// Note: This assumes 0-based lines (1-based lines are normally assumed).
|
||||
std::vector<std::string> index_lines;
|
||||
// Note: This assumes 0-based lines (1-based lines are normally assumed).
|
||||
// Note: all_buffer_lines is whitespace stripped.
|
||||
std::vector<std::string> all_buffer_lines;
|
||||
// Note: This assumes 0-based lines (1-based lines are normally assumed).
|
||||
std::vector<std::string> raw_buffer_lines;
|
||||
std::vector<std::string> buffer_lines;
|
||||
// Mappings between index line number and buffer line number.
|
||||
// Empty indicates stale.
|
||||
std::vector<int> index_to_buffer;
|
||||
@ -44,10 +41,6 @@ struct WorkingFile {
|
||||
// accepts and returns 1-based lines.
|
||||
optional<int> GetIndexLineFromBufferLine(int buffer_line);
|
||||
|
||||
optional<std::string> GetBufferLineContentFromIndexLine(
|
||||
int indexed_line,
|
||||
optional<int>* out_buffer_line);
|
||||
|
||||
// TODO: Move FindClosestCallNameInBuffer and FindStableCompletionSource into
|
||||
// lex_utils.h/cc
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user