Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions include/Feature/Definition.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#pragma once

#include <vector>
#include <cstdint>

#include "AST/SourceCode.h"
#include "llvm/ADT/StringRef.h"

namespace clice {

struct CompilationParams;

namespace config {

struct DefinitionOption {
/// Insert placeholder for keywords? function call parameters? template arguments?
bool enable_keyword_snippet = false;

/// Also apply for lambda ...
bool enable_function_arguments_snippet = false;
bool enable_template_arguments_snippet = false;

bool insert_paren_in_function_call = false;
/// TODO: Add more detailed option, see
/// https://github.com/llvm/llvm-project/issues/63565

bool bundle_overloads = true;

/// The limits of code completion, 0 is non limit.
std::uint32_t limit = 0;
};

}; // namespace config

namespace feature {

enum class CompletionItemKind {
None = 0,
Text,
Method,
Function,
Constructor,
Field,
Variable,
Class,
Interface,
Module,
Property,
Unit,
Value,
Enum,
Keyword,
Snippet,
Color,
File,
Reference,
Folder,
EnumMember,
Constant,
Struct,
Event,
Operator,
TypeParameter
};

/// Represents a single code completion item to be presented to the user.
struct CompletionItem {
/// The primary label displayed in the completion list.
std::string label;

/// Additional details, like a function signature, shown next to the label.
std::string detail;

/// A short description of the item, typically its type or namespace.
std::string description;

/// Full documentation for the item, shown on selection or hover.
std::string document;

/// The kind of item (function, class, etc.), used for an icon.
CompletionItemKind kind;

/// A score for ranking this item against others. Higher is better.
float score;

/// Whether this item is deprecated (often rendered with a strikethrough).
bool deprecated;

/// The text edit to be applied when this item is accepted.
struct Edit {
/// The new text to insert, which may be a snippet.
std::string text;

/// The source range to be replaced by the new text.
LocalSourceRange range;
} edit;
};

using CodeCompletionResult = std::vector<CompletionItem>;

std::vector<CompletionItem> definition(CompilationParams& params,
const config::DefinitionOption& option);

} // namespace feature

} // namespace clice

2 changes: 2 additions & 0 deletions src/Feature/Definition.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

namespace clice::feature {}
96 changes: 96 additions & 0 deletions tests/unit/Feature/Definition.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "Test/Tester.h"
#include "Feature/Definition.h"

namespace clice::testing {

namespace {

suite<"Definition"> goto_definition = [] {
std::vector<feature::CompletionItem> items;

auto definition = [&](llvm::StringRef code) {
CompilationParams params;
auto annotation = AnnotatedSource::from(code);
params.arguments = {"clang++", "-std=c++20", "main.cpp"};
params.completion = {"main.cpp", annotation.offsets["pos"]};
params.add_remapped_file("main.cpp", annotation.content);

config::DefinitionOption options = {};
items = feature::definition(params, options);
};

using enum feature::CompletionItemKind;

test("Score") = [&] {
definition(R"cpp(
int foooo(int x);
int x = fo$(pos)
)cpp");
expect(that % items.size() == 1);
expect(items.front().label == "foooo");
expect(items.front().kind == Function);
};

test("Snippet") = [&] {
definition(R"cpp(
int x = tru$(pos)
)cpp");
};

test("Overload") = [&] {
definition(R"cpp(
int foooo(int x);
int foooo(int x, int y);
int x = fooo$(pos)
)cpp");
};

test("Unqualified") = [&] {
definition(R"cpp(
namespace A {
void fooooo();
}

void bar() {
fo$(pos)
}
)cpp");

/// EXPECT: "A::fooooo"
/// To implement this we need to search code completion result from index
/// or traverse AST to collect interesting names.
};

test("Functor") = [&] {
definition(R"cpp(
struct X {
void operator() () {}
};

void bar() {
X foo;
fo$(pos);
}
)cpp");

/// TODO:
/// complete lambda as it is a variable.
};

test("Lambda") = [&] {
definition(R"cpp(
void bar() {
auto foo = [](int x){ };
fo$(pos);
}
)cpp");

/// TODO:
/// complete lambda as it is a function.
};
};

} // namespace

} // namespace clice::testing

Loading