Compare commits
4 Commits
feat/compl
...
bench/pch-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f19e75e2fb | ||
|
|
ba191943b6 | ||
|
|
90f3d34768 | ||
|
|
5b24dac6c3 |
@@ -200,6 +200,14 @@ if(CLICE_ENABLE_BENCHMARK)
|
||||
"${PROJECT_SOURCE_DIR}/src"
|
||||
)
|
||||
target_link_libraries(scan_benchmark PRIVATE clice::core kota::deco)
|
||||
|
||||
add_executable(pch_chain_benchmark
|
||||
"${PROJECT_SOURCE_DIR}/benchmarks/pch_chain/pch_chain_benchmark.cpp"
|
||||
)
|
||||
target_include_directories(pch_chain_benchmark PRIVATE
|
||||
"${PROJECT_SOURCE_DIR}/src"
|
||||
)
|
||||
target_link_libraries(pch_chain_benchmark PRIVATE clice::core)
|
||||
endif()
|
||||
|
||||
if(CLICE_RELEASE)
|
||||
|
||||
1056
benchmarks/pch_chain/pch_chain_benchmark.cpp
Normal file
1056
benchmarks/pch_chain/pch_chain_benchmark.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -158,28 +158,12 @@ auto extract_signature(const clang::CodeCompletionString& ccs) -> std::string {
|
||||
return signature;
|
||||
}
|
||||
|
||||
/// Find the first non-whitespace character after the given offset in content.
|
||||
/// Returns '\0' if none found (end of content).
|
||||
auto next_token_char(llvm::StringRef content, std::uint32_t offset) -> char {
|
||||
for(auto i = offset; i < content.size(); ++i) {
|
||||
char c = content[i];
|
||||
if(c != ' ' && c != '\t' && c != '\n' && c != '\r') {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return '\0';
|
||||
}
|
||||
|
||||
/// Build a snippet string from a CodeCompletionString.
|
||||
/// Produces e.g. "funcName(${1:int x}, ${2:float y})" for functions,
|
||||
/// or "ClassName<${1:T}>" for class templates.
|
||||
/// If skip_parens is true, omits everything from '(' onward (when the next
|
||||
/// token after the cursor is already '(').
|
||||
auto build_snippet(const clang::CodeCompletionString& ccs, bool skip_parens = false)
|
||||
-> std::string {
|
||||
auto build_snippet(const clang::CodeCompletionString& ccs) -> std::string {
|
||||
std::string snippet;
|
||||
unsigned placeholder_index = 0;
|
||||
bool in_parens = false;
|
||||
|
||||
for(const auto& chunk: ccs) {
|
||||
using CK = clang::CodeCompletionString::ChunkKind;
|
||||
@@ -190,47 +174,33 @@ auto build_snippet(const clang::CodeCompletionString& ccs, bool skip_parens = fa
|
||||
}
|
||||
break;
|
||||
case CK::CK_Placeholder:
|
||||
if(in_parens && skip_parens) {
|
||||
break;
|
||||
}
|
||||
if(chunk.Text) {
|
||||
snippet += std::format("${{{0}:{1}}}", ++placeholder_index, chunk.Text);
|
||||
}
|
||||
break;
|
||||
case CK::CK_LeftParen:
|
||||
in_parens = true;
|
||||
if(!skip_parens) {
|
||||
snippet += '(';
|
||||
}
|
||||
break;
|
||||
case CK::CK_RightParen:
|
||||
in_parens = false;
|
||||
if(!skip_parens) {
|
||||
snippet += ')';
|
||||
}
|
||||
break;
|
||||
case CK::CK_LeftParen: snippet += '('; break;
|
||||
case CK::CK_RightParen: snippet += ')'; break;
|
||||
case CK::CK_LeftAngle: snippet += '<'; break;
|
||||
case CK::CK_RightAngle: snippet += '>'; break;
|
||||
case CK::CK_Comma:
|
||||
if(!(in_parens && skip_parens)) {
|
||||
snippet += ", ";
|
||||
}
|
||||
break;
|
||||
case CK::CK_Comma: snippet += ", "; break;
|
||||
case CK::CK_Text:
|
||||
if(!(in_parens && skip_parens) && chunk.Text) {
|
||||
if(chunk.Text) {
|
||||
snippet += chunk.Text;
|
||||
}
|
||||
break;
|
||||
case CK::CK_Optional: break;
|
||||
case CK::CK_Optional:
|
||||
// Optional chunks contain default arguments — skip for snippet.
|
||||
break;
|
||||
case CK::CK_Informative:
|
||||
case CK::CK_ResultType:
|
||||
case CK::CK_CurrentParameter: break;
|
||||
case CK::CK_CurrentParameter:
|
||||
// Display-only chunks, not part of insertion.
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no placeholders were generated and parens were skipped,
|
||||
// return empty to signal plain text.
|
||||
// If no placeholders were generated, return empty to signal plain text.
|
||||
if(placeholder_index == 0) {
|
||||
return {};
|
||||
}
|
||||
@@ -259,11 +229,9 @@ public:
|
||||
CodeCompletionCollector(std::uint32_t offset,
|
||||
PositionEncoding encoding,
|
||||
std::vector<protocol::CompletionItem>& output,
|
||||
const CodeCompletionOptions& options,
|
||||
llvm::StringRef original_content) :
|
||||
const CodeCompletionOptions& options) :
|
||||
clang::CodeCompleteConsumer({}), offset(offset), encoding(encoding), output(output),
|
||||
options(options), original_content(original_content),
|
||||
info(std::make_shared<clang::GlobalCodeCompletionAllocator>()) {}
|
||||
options(options), info(std::make_shared<clang::GlobalCodeCompletionAllocator>()) {}
|
||||
|
||||
clang::CodeCompletionAllocator& getAllocator() final {
|
||||
return info.getAllocator();
|
||||
@@ -457,8 +425,7 @@ public:
|
||||
// Generate snippet for non-bundled callables.
|
||||
if(is_callable && !options.bundle_overloads &&
|
||||
options.enable_function_arguments_snippet) {
|
||||
bool next_is_paren = next_token_char(original_content, offset) == '(';
|
||||
snippet = build_snippet(*ccs, /*skip_parens=*/next_is_paren);
|
||||
snippet = build_snippet(*ccs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,7 +495,6 @@ private:
|
||||
std::uint32_t offset;
|
||||
PositionEncoding encoding;
|
||||
std::vector<protocol::CompletionItem>& output;
|
||||
llvm::StringRef original_content;
|
||||
const CodeCompletionOptions& options;
|
||||
clang::CodeCompletionTUInfo info;
|
||||
};
|
||||
@@ -543,15 +509,7 @@ auto code_complete(CompilationParams& params,
|
||||
auto& [file, offset] = params.completion;
|
||||
(void)file;
|
||||
|
||||
// Get the original file content for lookahead (smart parens detection).
|
||||
llvm::StringRef original_content;
|
||||
auto buf_it = params.buffers.find(file);
|
||||
if(buf_it != params.buffers.end()) {
|
||||
original_content = buf_it->second->getBuffer();
|
||||
}
|
||||
|
||||
auto* consumer =
|
||||
new CodeCompletionCollector(offset, encoding, items, options, original_content);
|
||||
auto* consumer = new CodeCompletionCollector(offset, encoding, items, options);
|
||||
auto unit = complete(params, consumer);
|
||||
(void)unit;
|
||||
|
||||
|
||||
@@ -335,44 +335,6 @@ int z = fo$(pos)
|
||||
*it->insert_text_format == protocol::InsertTextFormat::PlainText);
|
||||
}
|
||||
|
||||
TEST_CASE(SmartParensSkip) {
|
||||
// When next token after cursor is '(', snippet should not insert parens.
|
||||
feature::CodeCompletionOptions opts;
|
||||
opts.bundle_overloads = false;
|
||||
opts.enable_function_arguments_snippet = true;
|
||||
code_complete(R"cpp(
|
||||
int foooo(int x, float y);
|
||||
int z = fo$(pos)(1, 2.0f);
|
||||
)cpp",
|
||||
opts);
|
||||
|
||||
auto it = find_item("foooo");
|
||||
ASSERT_TRUE(it != items.end());
|
||||
// With parens already present, snippet should degrade to plain text
|
||||
// (no placeholders → build_snippet returns empty → label used).
|
||||
auto& edit = std::get<protocol::TextEdit>(*it->text_edit);
|
||||
ASSERT_TRUE(edit.new_text.find("(") == std::string::npos);
|
||||
}
|
||||
|
||||
TEST_CASE(SmartParensInsert) {
|
||||
// When next token is NOT '(', snippet should include parens normally.
|
||||
feature::CodeCompletionOptions opts;
|
||||
opts.bundle_overloads = false;
|
||||
opts.enable_function_arguments_snippet = true;
|
||||
code_complete(R"cpp(
|
||||
int foooo(int x, float y);
|
||||
int z = fo$(pos);
|
||||
)cpp",
|
||||
opts);
|
||||
|
||||
auto it = find_item("foooo");
|
||||
ASSERT_TRUE(it != items.end());
|
||||
auto& edit = std::get<protocol::TextEdit>(*it->text_edit);
|
||||
// Should contain '(' since there's no existing paren.
|
||||
ASSERT_TRUE(edit.new_text.find("(") != std::string::npos);
|
||||
ASSERT_TRUE(edit.new_text.find("${1:") != std::string::npos);
|
||||
}
|
||||
|
||||
TEST_CASE(SnippetBundleMode) {
|
||||
// In bundle mode, snippets should NOT be generated even if enabled.
|
||||
feature::CodeCompletionOptions opts;
|
||||
|
||||
Reference in New Issue
Block a user