Refactor Support.

This commit is contained in:
ykiko
2024-12-04 01:12:40 +08:00
parent ac7ce3aa6a
commit 2baea3800a
26 changed files with 1173 additions and 600 deletions

View File

@@ -7,44 +7,92 @@ namespace clice::feature {
namespace {
struct CompletionPrefix {
// The unqualified partial name.
// If there is none, begin() == end() == completion position.
llvm::StringRef name;
// The spelled scope qualifier, such as Foo::.
// If there is none, begin() == end() == name.begin().
llvm::StringRef qualifier;
static CompletionPrefix from(llvm::StringRef content, std::size_t offset) {
assert(offset <= content.size());
CompletionPrefix result;
llvm::StringRef rest = content.take_front(offset);
// Consume the unqualified name. We only handle ASCII characters.
// isAsciiIdentifierContinue will let us match "0invalid", but we don't mind.
while(!rest.empty() && clang::isAsciiIdentifierContinue(rest.back())) {
rest = rest.drop_back();
}
result.name = content.slice(rest.size(), offset);
// Consume qualifiers.
while(rest.consume_back("::") && !rest.ends_with(":")) {
// reject ::::
while(!rest.empty() && clang::isAsciiIdentifierContinue(rest.back())) {
rest = rest.drop_back();
}
}
result.qualifier = content.slice(rest.size(), result.name.begin() - content.begin());
return result;
}
};
proto::CompletionItemKind kindForDecl(const clang::NamedDecl* decl){
}
class CodeCompletionCollector final : public clang::CodeCompleteConsumer {
public:
CodeCompletionCollector(proto::CompletionResult& completions, uint32_t line, uint32_t column) :
CodeCompletionCollector(proto::CompletionResult& completions,
uint32_t line,
uint32_t column,
llvm::StringRef content) :
clang::CodeCompleteConsumer({}), completions(completions),
allocator(new clang::GlobalCodeCompletionAllocator()), info(allocator), line(line),
column(column) {}
column(column), content(content) {}
void ProcessCodeCompleteResults(clang::Sema& sema,
clang::CodeCompletionContext context,
clang::CodeCompletionResult* results,
unsigned count) final {
auto loc = sema.getPreprocessor().getCodeCompletionLoc();
auto offset = sema.getSourceManager().getFileOffset(loc);
auto prefix = CompletionPrefix::from(content, offset);
for(auto& result: llvm::make_range(results, results + count)) {
auto& completion = completions.emplace_back();
auto& item = completions.emplace_back();
item.kind = proto::CompletionItemKind::Text;
switch(result.Kind) {
case clang::CodeCompletionResult::RK_Declaration: {
completion.label = result.Declaration->getDeclName().getAsString();
item.label = result.Declaration->getName();
break;
}
case clang::CodeCompletionResult::RK_Keyword: {
completion.label = result.Keyword;
item.label = result.Keyword;
item.kind = proto::CompletionItemKind::Keyword;
break;
}
case clang::CodeCompletionResult::RK_Macro: {
completion.label = result.Macro->getName();
item.label = result.Macro->getName();
break;
}
case clang::CodeCompletionResult::RK_Pattern: {
completion.label = result.Pattern->getTypedText();
item.kind = proto::CompletionItemKind::Snippet;
item.label = result.Pattern->getTypedText();
break;
}
}
completion.textEdit.newText = completion.label;
completion.textEdit.range = {
.start = {line - 1, column - 1 },
.end = {line - 1, static_cast<uint32_t>(column + completion.label.size()) - 1},
item.textEdit.newText = item.label;
item.textEdit.range = {
.start = {line - 1, static_cast<uint32_t>(column - 1 - prefix.name.size())},
.end = {line - 1, static_cast<uint32_t>(column + item.label.size()) - 1 },
};
completion.kind = proto::CompletionItemKind::Text;
}
}
@@ -57,11 +105,12 @@ public:
}
private:
uint32_t line;
uint32_t column;
llvm::StringRef content;
std::shared_ptr<clang::GlobalCodeCompletionAllocator> allocator;
clang::CodeCompletionTUInfo info;
proto::CompletionResult& completions;
uint32_t line;
uint32_t column;
};
} // namespace
@@ -79,15 +128,15 @@ json::Value capability(json::Value clientCapabilities) {
};
}
proto::CompletionResult codeCompletion(CompliationParams& compliation,
proto::CompletionResult codeCompletion(CompliationParams& params,
uint32_t line,
uint32_t column,
llvm::StringRef file,
const config::CodeCompletionOption& option) {
proto::CompletionResult completions;
auto consumer = new CodeCompletionCollector(completions, line, column);
auto consumer = new CodeCompletionCollector(completions, line, column, params.content);
auto info = codeCompleteAt(compliation, line, column, file, consumer);
auto info = codeCompleteAt(params, line, column, file, consumer);
if(info) {
return completions;
} else {