diff --git a/CMakeLists.txt b/CMakeLists.txt index d0f9a177..bdb168dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,12 @@ if (CXX_ENABLE_FLATBUFFERS) set_target_properties(flatbuffers::header-only PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${flatbuffers_SOURCE_DIR}/include") endif() + +if (CXX_BUILD_TESTS) + enable_testing() +endif() + + if (NOT KWGEN_EXECUTABLE AND CMAKE_SYSTEM_NAME STREQUAL "WASI") ExternalProject_Add( diff --git a/packages/cxx-gen-lsp/src/gen_fwd_h.ts b/packages/cxx-gen-lsp/src/gen_fwd_h.ts index 0a744323..06fab69b 100644 --- a/packages/cxx-gen-lsp/src/gen_fwd_h.ts +++ b/packages/cxx-gen-lsp/src/gen_fwd_h.ts @@ -51,6 +51,9 @@ public: [[nodiscard]] auto size() const -> std::size_t { return repr_->size(); } [[nodiscard]] auto empty() const -> bool { return repr_->empty(); } [[nodiscard]] auto at(int index) const -> const T& { return repr_->at(index); } + + template + void emplace_back(Args&&... args) { repr_->emplace_back(std::forward(args)...); } }; namespace details { @@ -161,6 +164,22 @@ struct TryEmplace { } // namespace details +template <> +class Vector final : public LSPObject { + public: + using LSPObject::LSPObject; + + [[nodiscard]] explicit operator bool() const { return repr_ && repr_->is_array(); } + [[nodiscard]] auto size() const -> std::size_t { return repr_->size(); } + [[nodiscard]] auto empty() const -> bool { return repr_->empty(); } + [[nodiscard]] auto at(int index) const -> std::string { + return repr_->at(index); + } + + template + void emplace_back(Args&&... args) { repr_->emplace_back(std::forward(args)...); } +}; + template class Vector> final : public LSPObject { public: @@ -174,6 +193,18 @@ class Vector> final : public LSPObject { details::try_emplace(result, repr_->at(index)); return result; } + + template + [[nodiscard]] auto emplace_back() -> std::variant { + std::variant result; + details::TryEmplace{}(result, repr_->emplace_back()); + return result; + } + + template T> + [[nodiscard]] auto emplace_back() -> T { + return T(repr_->emplace_back()); + } }; template @@ -253,6 +284,7 @@ export function gen_fwd_h({ model, outputDirectory }: { model: MetaModel; output emit(`#pragma once`); emit(); emit(`#include `); + emit(`#include `); emit(`#include `); emit(); emit(`namespace cxx::lsp {`); diff --git a/src/lsp/cxx/lsp/fwd.h b/src/lsp/cxx/lsp/fwd.h index 62b047a8..3569bfa6 100644 --- a/src/lsp/cxx/lsp/fwd.h +++ b/src/lsp/cxx/lsp/fwd.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include @@ -487,6 +488,11 @@ class Vector final : public LSPObject { [[nodiscard]] auto at(int index) const -> const T& { return repr_->at(index); } + + template + void emplace_back(Args&&... args) { + repr_->emplace_back(std::forward(args)...); + } }; namespace details { @@ -597,6 +603,26 @@ struct TryEmplace { } // namespace details +template <> +class Vector final : public LSPObject { + public: + using LSPObject::LSPObject; + + [[nodiscard]] explicit operator bool() const { + return repr_ && repr_->is_array(); + } + [[nodiscard]] auto size() const -> std::size_t { return repr_->size(); } + [[nodiscard]] auto empty() const -> bool { return repr_->empty(); } + [[nodiscard]] auto at(int index) const -> std::string { + return repr_->at(index); + } + + template + void emplace_back(Args&&... args) { + repr_->emplace_back(std::forward(args)...); + } +}; + template class Vector> final : public LSPObject { public: @@ -612,6 +638,18 @@ class Vector> final : public LSPObject { details::try_emplace(result, repr_->at(index)); return result; } + + template + [[nodiscard]] auto emplace_back() -> std::variant { + std::variant result; + details::TryEmplace{}(result, repr_->emplace_back()); + return result; + } + + template T> + [[nodiscard]] auto emplace_back() -> T { + return T(repr_->emplace_back()); + } }; template diff --git a/src/lsp/tests/test_types.cc b/src/lsp/tests/test_types.cc index cf7b4532..5a904d13 100644 --- a/src/lsp/tests/test_types.cc +++ b/src/lsp/tests/test_types.cc @@ -88,5 +88,58 @@ TEST(LSP, StringProperty) { ASSERT_EQ(range.start().line(), 0); ASSERT_EQ(range.start().character(), 0); + range.start().line(1); + range.start().character(2); + range.end().line(3); + range.end().character(4); + + ASSERT_EQ(range.start().line(), 1); + ASSERT_EQ(range.start().character(), 2); + ASSERT_EQ(range.end().line(), 3); + ASSERT_EQ(range.end().character(), 4); + ASSERT_TRUE(location); +} + +TEST(LSP, StringArrayProperty) { + json storage = json::object(); + + auto textDocumentContentRegistrationOptions = + TextDocumentContentRegistrationOptions{storage}; + + auto schemas = textDocumentContentRegistrationOptions.schemes(); + ASSERT_TRUE(schemas.empty()); + + schemas.emplace_back("file"); + schemas.emplace_back("http"); + + ASSERT_EQ(schemas.at(0), "file"); + ASSERT_EQ(schemas.at(1), "http"); + + ASSERT_EQ(textDocumentContentRegistrationOptions.schemes().at(0), "file"); + ASSERT_EQ(textDocumentContentRegistrationOptions.schemes().at(1), "http"); +} + +TEST(LSP, VariantArrayProperty) { + auto storage = json::object(); + + NotebookDocumentSyncRegistrationOptions + notebookDocumentSyncRegistrationOptions{storage}; + + auto notebookSelector = + notebookDocumentSyncRegistrationOptions.notebookSelector(); + + ASSERT_TRUE(notebookSelector.empty()); + + auto item = notebookSelector.emplace_back(); + + ASSERT_FALSE(item.notebook().has_value()); + + item.notebook("a_notebook"); + + ASSERT_TRUE(item.notebook().has_value()); + + ASSERT_EQ(std::get(*item.notebook()), "a_notebook"); + + ASSERT_EQ(notebookSelector.size(), 1); } \ No newline at end of file