diff options
author | Norbert Preining <norbert@preining.info> | 2022-02-06 03:01:17 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2022-02-06 03:01:17 +0000 |
commit | 350b3e35109171f0edd6fe9d697b91d5e76561f9 (patch) | |
tree | c6eac90d0b35dec36fa17ee58b736e55d6e42755 /graphics/asymptote/LspCpp/include | |
parent | 08ccf305ee79ab8e5ba9d1a8f3d22e74dccedd80 (diff) |
CTAN sync 202202060301
Diffstat (limited to 'graphics/asymptote/LspCpp/include')
148 files changed, 13686 insertions, 0 deletions
diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Cancellation.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Cancellation.h new file mode 100644 index 0000000000..b89f32f166 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Cancellation.h @@ -0,0 +1,23 @@ +#pragma once +#include <functional> +#include "lsRequestId.h" +#include <LibLsp/JsonRpc/NotificationInMessage.h> +using CancelMonitor = std::function<int()>; +namespace Cancellation +{ + + struct Params { + /** + * The request id to cancel. + */ + lsRequestId id; + + MAKE_SWAP_METHOD(Cancellation::Params, id); + }; + +}; +MAKE_REFLECT_STRUCT(Cancellation::Params, id); + +DEFINE_NOTIFICATION_TYPE(Notify_Cancellation, Cancellation::Params,"$/cancelRequest"); + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Condition.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Condition.h new file mode 100644 index 0000000000..a5f550041d --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Condition.h @@ -0,0 +1,48 @@ +#pragma once +#include <condition_variable> +template <class T> +class Condition +{ +public: + + std::mutex m_mutex; + std::condition_variable m_condition; + ~Condition() { + m_condition.notify_all(); + } + void notify(std::unique_ptr<T> data) noexcept + { + { + std::lock_guard<std::mutex> eventLock(m_mutex); + any.swap(data); + } + // wake up one waiter + m_condition.notify_one(); + }; + + + std::unique_ptr<T> wait(unsigned timeout=0) + { + std::unique_lock<std::mutex> ul(m_mutex); + if (!timeout) { + m_condition.wait(ul,[&]() { + if (!any) + return false; + return true; + }); + } + else{ + if(!any){ + std::cv_status status = m_condition.wait_for(ul, std::chrono::milliseconds(timeout)); + if (status == std::cv_status::timeout) + { + return {}; + } + } + } + return std::unique_ptr<T>(any.release()); + + } +private: + std::unique_ptr<T> any; +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Context.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Context.h new file mode 100644 index 0000000000..20edf71b1c --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Context.h @@ -0,0 +1,216 @@ +//===--- Context.h - Mechanism for passing implicit data --------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Context for storing and retrieving implicit data. Useful for passing implicit +// parameters on a per-request basis. +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include <memory> +#include <type_traits> + +namespace lsp { + + +/// Values in a Context are indexed by typed keys. +/// Key<T> serves two purposes: +/// - it provides a lookup key for the context (each Key is unique), +/// - it makes lookup type-safe: a Key<T> can only map to a T (or nothing). +/// +/// Example: +/// Key<int> RequestID; +/// Key<int> Version; +/// +/// Context Ctx = Context::empty().derive(RequestID, 10).derive(Version, 3); +/// assert(*Ctx.get(RequestID) == 10); +/// assert(*Ctx.get(Version) == 3); +/// +/// Keys are typically used across multiple functions, so most of the time you +/// would want to make them static class members or global variables. +template <class Type> class Key { +public: + static_assert(!std::is_reference<Type>::value, + "Reference arguments to Key<> are not allowed"); + + constexpr Key() = default; + + Key(Key const &) = delete; + Key &operator=(Key const &) = delete; + Key(Key &&) = delete; + Key &operator=(Key &&) = delete; +}; + +/// A context is an immutable container for per-request data that must be +/// propagated through layers that don't care about it. An example is a request +/// ID that we may want to use when logging. +/// +/// Conceptually, a context is a heterogeneous map<Key<T>, T>. Each key has +/// an associated value type, which allows the map to be typesafe. +/// +/// There is an "ambient" context for each thread, Context::current(). +/// Most functions should read from this, and use WithContextValue or +/// WithContext to extend or replace the context within a block scope. +/// Only code dealing with threads and extension points should need to use +/// other Context objects. +/// +/// You can't add data to an existing context, instead you create a new +/// immutable context derived from it with extra data added. When you retrieve +/// data, the context will walk up the parent chain until the key is found. +class Context { +public: + /// Returns an empty root context that contains no data. + static Context empty(); + /// Returns the context for the current thread, creating it if needed. + static const Context ¤t(); + // Sets the current() context to Replacement, and returns the old context. + // Prefer to use WithContext or WithContextValue to do this safely. + static Context swapCurrent(Context Replacement); + +private: + struct Data; + Context(std::shared_ptr<const Data> DataPtr); + +public: + /// Same as Context::empty(), please use Context::empty() instead. + Context() = default; + + /// Copy operations for this class are deleted, use an explicit clone() method + /// when you need a copy of the context instead. + Context(Context const &) = delete; + Context &operator=(const Context &) = delete; + + Context(Context &&) = default; + Context &operator=(Context &&) = default; + + /// Get data stored for a typed \p Key. If values are not found + /// \returns Pointer to the data associated with \p Key. If no data is + /// specified for \p Key, return null. + template <class Type> const Type *get(const Key<Type> &Key) const { + for (const Data *DataPtr = this->dataPtr.get(); DataPtr != nullptr; + DataPtr = DataPtr->parent.get()) { + if (DataPtr->KeyPtr == &Key) + return static_cast<const Type *>(DataPtr->value->getValuePtr()); + } + return nullptr; + } + + /// A helper to get a reference to a \p Key that must exist in the map. + /// Must not be called for keys that are not in the map. + template <class Type> const Type &getExisting(const Key<Type> &Key) const { + auto Val = get(Key); + assert(Val && "Key does not exist"); + return *Val; + } + + /// Derives a child context + /// It is safe to move or destroy a parent context after calling derive(). + /// The child will keep its parent alive, and its data remains accessible. + template <class Type> + Context derive(const Key<Type> &Key, + typename std::decay<Type>::type Value) const & { + return Context(std::make_shared<Data>( + Data{/*parent=*/dataPtr, &Key, + std::make_unique<TypedAnyStorage<typename std::decay<Type>::type>>( + std::move(Value))})); + } + + template <class Type> + Context + derive(const Key<Type> &Key, + typename std::decay<Type>::type Value) && /* takes ownership */ { + return Context(std::make_shared<Data>( + Data{/*parent=*/std::move(dataPtr), &Key, + std::make_unique<TypedAnyStorage<typename std::decay<Type>::type>>( + std::move(Value))})); + } + + /// Derives a child context, using an anonymous key. + /// Intended for objects stored only for their destructor's side-effect. + template <class Type> Context derive(Type &&Value) const & { + static Key<typename std::decay<Type>::type> Private; + return derive(Private, std::forward<Type>(Value)); + } + + template <class Type> Context derive(Type &&Value) && { + static Key<typename std::decay<Type>::type> Private; + return std::move(*this).derive(Private, std::forward<Type>(Value)); + } + + /// Clone this context object. + Context clone() const; + +private: + class AnyStorage { + public: + virtual ~AnyStorage() = default; + virtual void *getValuePtr() = 0; + }; + + template <class T> class TypedAnyStorage : public Context::AnyStorage { + static_assert(std::is_same<typename std::decay<T>::type, T>::value, + "Argument to TypedAnyStorage must be decayed"); + + public: + TypedAnyStorage(T &&Value) : value(std::move(Value)) {} + + void *getValuePtr() override { return &value; } + + private: + T value; + }; + + struct Data { + // We need to make sure parent outlives the value, so the order of members + // is important. We do that to allow classes stored in Context's child + // layers to store references to the data in the parent layers. + std::shared_ptr<const Data> parent; + const void *KeyPtr; + std::unique_ptr<AnyStorage> value; + }; + + std::shared_ptr<const Data> dataPtr; +}; + +/// WithContext replaces Context::current() with a provided scope. +/// When the WithContext is destroyed, the original scope is restored. +/// For extending the current context with new value, prefer WithContextValue. +class WithContext { +public: + WithContext(Context C) : restore(Context::swapCurrent(std::move(C))) {} + ~WithContext() { Context::swapCurrent(std::move(restore)); } + WithContext(const WithContext &) = delete; + WithContext &operator=(const WithContext &) = delete; + WithContext(WithContext &&) = delete; + WithContext &operator=(WithContext &&) = delete; + +private: + Context restore; +}; + +/// WithContextValue extends Context::current() with a single value. +/// When the WithContextValue is destroyed, the original scope is restored. +class WithContextValue { +public: + template <typename T> + WithContextValue(const Key<T> &K, typename std::decay<T>::type V) + : restore(Context::current().derive(K, std::move(V))) {} + + // Anonymous values can be used for the destructor side-effect. + template <typename T> + WithContextValue(T &&V) + : restore(Context::current().derive(std::forward<T>(V))) {} + +private: + WithContext restore; +}; + + +} // namespace lsp + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Endpoint.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Endpoint.h new file mode 100644 index 0000000000..01d8e8ca91 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/Endpoint.h @@ -0,0 +1,53 @@ +#pragma once +#include <map> +#include <functional> +#include <memory> +#include "MessageIssue.h" +struct LspMessage; +struct NotificationInMessage; +struct lsBaseOutMessage; +struct RequestInMessage; + +using GenericResponseHandler = std::function< bool(std::unique_ptr<LspMessage>) >; +using GenericRequestHandler = std::function< bool(std::unique_ptr<LspMessage>) >; +using GenericNotificationHandler = std::function< bool(std::unique_ptr<LspMessage>) >; + +class Endpoint +{ +public: + virtual ~Endpoint() = default; + virtual bool onRequest(std::unique_ptr<LspMessage>) = 0; + virtual bool notify(std::unique_ptr<LspMessage>) = 0; + + virtual bool onResponse(const std::string&, std::unique_ptr<LspMessage>) = 0; + virtual void registerRequestHandler(const std::string&, GenericResponseHandler ) = 0; + virtual void registerNotifyHandler(const std::string&, GenericNotificationHandler ) = 0; +}; + +class GenericEndpoint :public Endpoint +{ + +public: + GenericEndpoint(lsp::Log& l):log(l){} + bool notify(std::unique_ptr<LspMessage>) override; + bool onResponse(const std::string&, std::unique_ptr<LspMessage>) override; + + bool onRequest(std::unique_ptr<LspMessage>) override; + std::map< std::string, GenericRequestHandler > method2request; + std::map< std::string, GenericResponseHandler > method2response; + std::map< std::string, GenericNotificationHandler > method2notification; + + void registerRequestHandler(const std::string& method, GenericResponseHandler cb) override + { + method2request[method] = cb; + } + + void registerNotifyHandler(const std::string& method, GenericNotificationHandler cb) override + { + method2notification[method] = cb; + } + lsp::Log& log; + + + +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/GCThreadContext.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/GCThreadContext.h new file mode 100644 index 0000000000..a0f7db288d --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/GCThreadContext.h @@ -0,0 +1,19 @@ +#pragma once + +#if defined(USEGC) +#define GC_THREADS +#include <gc.h> +#endif + +class GCThreadContext +{ +public: + GCThreadContext(); + ~GCThreadContext(); + +private: +#if defined(USEGC) + GC_stack_base gsb; +#endif + +};
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageIssue.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageIssue.h new file mode 100644 index 0000000000..bda6e65d46 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageIssue.h @@ -0,0 +1,182 @@ +#pragma once +#include <string> +#include <functional> +#include <vector> +namespace lsp +{ + class Log + { + public: + virtual ~Log() = default; + + enum class Level + { + /** + * OFF is a special level that can be used to turn off logging. + + */ + OFF = 1, + + /** + * SEVERE is a message level indicating a serious failure. + * <p> + * In general SEVERE messages should describe events that are + * of considerable importance and which will prevent normal + * program execution. They should be reasonably intelligible + * to end users and to system administrators. + + */ + SEVERE = 2, + + /** + * WARNING is a message level indicating a potential problem. + * <p> + * In general WARNING messages should describe events that will + * be of interest to end users or system managers, or which + * indicate potential problems. + + * + */ + WARNING = 3, + /** + * INFO is a message level for informational messages. + * <p> + * Typically INFO messages will be written to the console + * or its equivalent. So the INFO level should only be + * used for reasonably significant messages that will + * make sense to end users and system administrators. + + */ + INFO = 3, + /** + * CONFIG is a message level for static configuration messages. + * <p> + * CONFIG messages are intended to provide a variety of static + * configuration information, to assist in debugging problems + * that may be associated with particular configurations. + * For example, CONFIG message might include the CPU type, + * the graphics depth, the GUI look-and-feel, etc. + * This level is initialized to <CODE>4</CODE>. + */ + + CONFIG = 4, + + + + /** + * FINE is a message level providing tracing information. + * <p> + * All of FINE, FINER, and FINEST are intended for relatively + * detailed tracing. The exact meaning of the three levels will + * vary between subsystems, but in general, FINEST should be used + * for the most voluminous detailed output, FINER for somewhat + * less detailed output, and FINE for the lowest volume (and + * most important) messages. + * <p> + * In general the FINE level should be used for information + * that will be broadly interesting to developers who do not have + * a specialized interest in the specific subsystem. + * <p> + * FINE messages might include things like minor (recoverable) + * failures. Issues indicating potential performance problems + * are also worth logging as FINE. + * This level is initialized to <CODE>5</CODE>. + */ + FINE = 5, + + /** + * FINER indicates a fairly detailed tracing message. + * By default logging calls for entering, returning, or throwing + * an exception are traced at this level. + * This level is initialized to <CODE>400</CODE>. + */ + FINER = 6, + + /** + * FINEST indicates a highly detailed tracing message. + * This level is initialized to <CODE>300</CODE>. + */ + FINEST = 7, + + /** + * ALL indicates that all messages should be logged. + * This level is initialized to <CODE>Integer.MIN_VALUE</CODE>. + */ + ALL, + }; + virtual void log(Level level, std::wstring&& msg) = 0; + virtual void log(Level level, const std::wstring& msg) = 0; + virtual void log(Level level, std::string&& msg) = 0; + virtual void log(Level level, const std::string& msg) = 0; + + void info(const std::string& msg) + { + log(Level::INFO, msg); + } + void info(const std::wstring& msg) + { + log(Level::INFO, msg); + } + void error(const std::string& msg) + { + log(Level::SEVERE, msg); + } + void error(const std::wstring& msg) + { + log(Level::SEVERE, msg); + } + void warning(const std::string& msg) + { + log(Level::WARNING, msg); + } + void warning(const std::wstring& msg) + { + log(Level::WARNING, msg); + } + }; +} + +class MessageIssue { + +public: + std::string text; + + lsp::Log::Level code; + + MessageIssue(const std::string& text, lsp::Log::Level code) :text(text), code(code) + { + + + } + MessageIssue(std::string&& text, lsp::Log::Level code) :text(text), code(code) + { + + + } + + + std::string getText() { + return text; + } + + lsp::Log::Level getIssueCode() { + return code; + } + + + std::string toString() { + return getText(); + } + +}; +class MessageIssueHandler +{ +public: + /** + * Handle issues found while parsing or validating a message. The list of issues must not be empty. + */ + virtual ~MessageIssueHandler() = default; + + virtual void handle(std::vector<MessageIssue>&&) = 0; + virtual void handle( MessageIssue&&) = 0; +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageJsonHandler.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageJsonHandler.h new file mode 100644 index 0000000000..7e238b0cf6 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageJsonHandler.h @@ -0,0 +1,61 @@ +#pragma once +#include <string> +#include <map> +#include <functional> +#include <LibLsp/JsonRpc/message.h> +class Reader; + + +using GenericRequestJsonHandler = std::function< std::unique_ptr<LspMessage>(Reader&) >; +using GenericResponseJsonHandler = std::function< std::unique_ptr<LspMessage>(Reader&) >; +using GenericNotificationJsonHandler = std::function< std::unique_ptr<LspMessage>(Reader&) >; + +class MessageJsonHandler +{ +public: + std::map< std::string, GenericRequestJsonHandler > method2request; + std::map< std::string, GenericResponseJsonHandler > method2response; + std::map< std::string, GenericNotificationJsonHandler > method2notification; + + + const GenericRequestJsonHandler* GetRequestJsonHandler(const char* methodInfo) const + { + const auto findIt = method2request.find(methodInfo); + return findIt == method2request.end() ? nullptr : &findIt->second; + } + + void SetRequestJsonHandler(const std::string& methodInfo, GenericRequestJsonHandler handler) + { + method2request[methodInfo] = handler; + } + + const GenericResponseJsonHandler* GetResponseJsonHandler(const char* methodInfo) const + { + const auto findIt = method2response.find(methodInfo); + return findIt == method2response.end() ? nullptr : &findIt->second; + } + + void SetResponseJsonHandler(const std::string& methodInfo,GenericResponseJsonHandler handler) + { + method2response[methodInfo] = handler; + } + + const GenericNotificationJsonHandler* GetNotificationJsonHandler(const char* methodInfo) const + { + const auto findIt = method2notification.find(methodInfo); + return findIt == method2notification.end() ? nullptr : &findIt->second; + } + + void SetNotificationJsonHandler(const std::string& methodInfo, GenericNotificationJsonHandler handler) + { + method2notification[methodInfo] = handler; + } + + + + std::unique_ptr<LspMessage> parseResponseMessage(const std::string&, Reader&); + std::unique_ptr<LspMessage> parseRequstMessage(const std::string&, Reader&); + bool resovleResponseMessage(Reader&, std::pair<std::string, std::unique_ptr<LspMessage>>& result); + std::unique_ptr<LspMessage> parseNotificationMessage(const std::string&, Reader&); +}; + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageProducer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageProducer.h new file mode 100644 index 0000000000..ab7a29a17f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/MessageProducer.h @@ -0,0 +1,13 @@ +#pragma once +#include <string> +#include <functional> + +class MessageProducer +{ +public: + + + typedef std::function< void(std::string&&) > MessageConsumer; + virtual ~MessageProducer() = default; + virtual void listen(MessageConsumer) = 0; +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/NotificationInMessage.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/NotificationInMessage.h new file mode 100644 index 0000000000..e4841b5703 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/NotificationInMessage.h @@ -0,0 +1,62 @@ +#pragma once + + +#include "lsRequestId.h" +#include "LibLsp/JsonRpc/message.h" + + + +// NotificationInMessage does not have |id|. +struct NotificationInMessage : public LspMessage { + + Kind GetKid() override + { + return NOTIFICATION_MESSAGE; + } + MethodType GetMethodType() const override + { + return method.c_str(); + } + void SetMethodType(MethodType _t) override + { + method = _t; + } + std::string method; +}; +template <class T, class TDerived > +struct lsNotificationInMessage : NotificationInMessage { + + void ReflectWriter(Writer& writer) override { + Reflect(writer, static_cast<TDerived&>(*this)); + } + lsNotificationInMessage(MethodType _method) + { + method = _method; + } + + static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) { + + TDerived* temp = new TDerived(); + + std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp); + // Reflect may throw and *message will be partially deserialized. + Reflect(visitor, static_cast<TDerived&>(*temp)); + return message; + + } + void swap(lsNotificationInMessage& arg) noexcept + { + method.swap(method); + std::swap(params, arg.params); + } + T params; +}; + +#define DEFINE_NOTIFICATION_TYPE(MSG,paramType,methodInfo)\ +namespace MSG {\ + struct notify : public lsNotificationInMessage< paramType , notify >{\ + static constexpr MethodType kMethodInfo = methodInfo;\ + notify():lsNotificationInMessage(kMethodInfo){} \ + };\ +};\ +MAKE_REFLECT_STRUCT(MSG::notify, jsonrpc,method, params) diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RemoteEndPoint.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RemoteEndPoint.h new file mode 100644 index 0000000000..3ae6b567a5 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RemoteEndPoint.h @@ -0,0 +1,340 @@ +#pragma once +#include "LibLsp/lsp/lsp_diagnostic.h" +#include "LibLsp/JsonRpc/Cancellation.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/NotificationInMessage.h" +#include "traits.h" +#include <future> +#include <string> +#include "threaded_queue.h" +#include <unordered_map> +#include "MessageIssue.h" +#include "LibLsp/JsonRpc/MessageJsonHandler.h" +#include "Endpoint.h" + + +class MessageJsonHandler; +class Endpoint; +struct LspMessage; +class RemoteEndPoint; +namespace lsp { + class ostream; + class istream; + + //////////////////////////////////////////////////////////////////////////////// + // ResponseOrError<T> + //////////////////////////////////////////////////////////////////////////////// + + // ResponseOrError holds either the response to a request or an error + // message. + template <typename T> + struct ResponseOrError { + using Request = T; + ResponseOrError(); + ResponseOrError(const T& response); + ResponseOrError(T&& response); + ResponseOrError(const Rsp_Error& error); + ResponseOrError(Rsp_Error&& error); + ResponseOrError(const ResponseOrError& other); + ResponseOrError(ResponseOrError&& other) noexcept; + + ResponseOrError& operator=(const ResponseOrError& other); + ResponseOrError& operator=(ResponseOrError&& other) noexcept; + bool IsError() const { return is_error; } + std::string ToJson() + { + if (is_error) return error.ToJson(); + return response.ToJson(); + } + T response; + Rsp_Error error; // empty represents success. + bool is_error; + }; + + template <typename T> + ResponseOrError<T>::ResponseOrError(): is_error(false) + { + } + + template <typename T> + ResponseOrError<T>::ResponseOrError(const T& resp) : response(resp), is_error(false) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(T&& resp) : response(std::move(resp)), is_error(false) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(const Rsp_Error& err) : error(err), is_error(true) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(Rsp_Error&& err) : error(std::move(err)), is_error(true) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(const ResponseOrError& other) + : response(other.response), error(other.error), is_error(other.is_error) {} + template <typename T> + ResponseOrError<T>::ResponseOrError(ResponseOrError&& other) noexcept + : response(std::move(other.response)), error(std::move(other.error)), is_error(other.is_error) {} + template <typename T> + ResponseOrError<T>& ResponseOrError<T>::operator=( + const ResponseOrError& other) { + response = other.response; + error = other.error; + is_error = other.is_error; + return *this; + } + template <typename T> + ResponseOrError<T>& ResponseOrError<T>::operator=(ResponseOrError&& other) noexcept + { + response = std::move(other.response); + error = std::move(other.error); + is_error = other.is_error; + return *this; + } + +} + + +class RemoteEndPoint :MessageIssueHandler +{ + + template <typename F, int N> + using ParamType = lsp::traits::ParameterType<F, N>; + + template <typename T> + using IsRequest = lsp::traits::EnableIfIsType<RequestInMessage, T>; + + template <typename T> + using IsResponse = lsp::traits::EnableIfIsType<ResponseInMessage, T>; + + template <typename T> + using IsNotify = lsp::traits::EnableIfIsType<NotificationInMessage, T>; + + + template <typename F, typename ReturnType> + using IsRequestHandler = lsp::traits::EnableIf<lsp::traits::CompatibleWith< + F, + std::function<ReturnType(const RequestInMessage&)>>:: + value>; + + template <typename F, typename ReturnType> + using IsRequestHandlerWithMonitor = lsp::traits::EnableIf<lsp::traits::CompatibleWith< + F, + std::function<ReturnType(const RequestInMessage&,const CancelMonitor&)>>:: + value>; + +public: + + + RemoteEndPoint(const std::shared_ptr <MessageJsonHandler>& json_handler, + const std::shared_ptr < Endpoint >& localEndPoint, + lsp::Log& _log, uint8_t max_workers = 2); + + ~RemoteEndPoint() override; + template <typename F, typename RequestType = ParamType<F, 0>, typename ResponseType = typename RequestType::Response> + IsRequestHandler< F, lsp::ResponseOrError<ResponseType> > registerHandler(F&& handler) + { + ProcessRequestJsonHandler(handler); + local_endpoint->registerRequestHandler(RequestType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) { + auto req = reinterpret_cast<const RequestType*>(msg.get()); + lsp::ResponseOrError<ResponseType> res(handler(*req)); + if (res.is_error) { + res.error.id = req->id; + send(res.error); + } + else + { + res.response.id = req->id; + send(res.response); + } + return true; + }); + } + template <typename F, typename RequestType = ParamType<F, 0>, typename ResponseType = typename RequestType::Response> + IsRequestHandlerWithMonitor< F, lsp::ResponseOrError<ResponseType> > registerHandler(F&& handler) { + ProcessRequestJsonHandler(handler); + local_endpoint->registerRequestHandler(RequestType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) { + auto req = static_cast<const RequestType*>(msg.get()); + lsp::ResponseOrError<ResponseType> res(handler(*req , getCancelMonitor(req->id))); + if (res.is_error) { + res.error.id = req->id; + send(res.error); + } + else + { + res.response.id = req->id; + send(res.response); + } + return true; + }); + } + using RequestErrorCallback = std::function<void(const Rsp_Error&)>; + + template <typename T, typename F, typename ResponseType = ParamType<F, 0> > + void send(T& request, F&& handler, RequestErrorCallback onError) + { + ProcessRequestJsonHandler(handler); + auto cb = [=](std::unique_ptr<LspMessage> msg) { + if (!msg) + return true; + const auto result = msg.get(); + + if (static_cast<ResponseInMessage*>(result)->IsErrorType()) { + const auto rsp_error = static_cast<const Rsp_Error*>(result); + onError(*rsp_error); + } + else { + handler(*static_cast<ResponseType*>(result)); + } + + return true; + }; + internalSendRequest(request, cb); + } + + + template <typename F, typename NotifyType = ParamType<F, 0> > + IsNotify<NotifyType> registerHandler(F&& handler) { + { + std::lock_guard<std::mutex> lock(m_sendMutex); + if (!jsonHandler->GetNotificationJsonHandler(NotifyType::kMethodInfo)) + { + jsonHandler->SetNotificationJsonHandler(NotifyType::kMethodInfo, + [](Reader& visitor) + { + return NotifyType::ReflectReader(visitor); + }); + } + } + local_endpoint->registerNotifyHandler(NotifyType::kMethodInfo, [=](std::unique_ptr<LspMessage> msg) { + handler(*static_cast<NotifyType*>(msg.get())); + return true; + }); + } + + template <typename T, typename = IsRequest<T>> + std::future< lsp::ResponseOrError<typename T::Response> > send(T& request) { + + ProcessResponseJsonHandler(request); + using Response = typename T::Response; + auto promise = std::make_shared< std::promise<lsp::ResponseOrError<Response>>>(); + auto cb = [=](std::unique_ptr<LspMessage> msg) { + if (!msg) + return true; + auto result = msg.get(); + + if (reinterpret_cast<ResponseInMessage*>(result)->IsErrorType()) + { + Rsp_Error* rsp_error = static_cast<Rsp_Error*>(result); + Rsp_Error temp; + std::swap(temp, *rsp_error); + promise->set_value(std::move(lsp::ResponseOrError<Response>(std::move(temp)))); + } + else + { + Response temp; + std::swap(temp, *static_cast<Response*>(result)); + promise->set_value(std::move(lsp::ResponseOrError<Response>(std::move(temp)))); + } + return true; + }; + internalSendRequest(request, cb); + return promise->get_future(); + } + + template <typename T, typename = IsRequest<T>> + std::unique_ptr<lsp::ResponseOrError<typename T::Response>> waitResponse(T& request, const unsigned time_out = 0) + { + auto future_rsp = send(request); + if (time_out == 0) + { + future_rsp.wait(); + } + else + { + auto state = future_rsp.wait_for(std::chrono::milliseconds(time_out)); + if (std::future_status::timeout == state) + { + return {}; + } + } + + using Response = typename T::Response; + return std::make_unique<lsp::ResponseOrError<Response>>(std::move(future_rsp.get())); + } + + void send(NotificationInMessage& msg) + { + sendMsg(msg); + } + + void send(ResponseInMessage& msg) + { + sendMsg(msg); + } + + void sendNotification(NotificationInMessage& msg) + { + send(msg); + } + void sendResponse(ResponseInMessage& msg) + { + send(msg); + } + void startProcessingMessages(std::shared_ptr<lsp::istream> r, + std::shared_ptr<lsp::ostream> w); + + bool IsWorking() const + { + if (message_producer_thread_) + return true; + return false; + } + void Stop(); + + std::unique_ptr<LspMessage> internalWaitResponse(RequestInMessage&, unsigned time_out = 0); + + void internalSendRequest(RequestInMessage&, GenericResponseHandler); + + void handle(std::vector<MessageIssue>&&) override; + void handle(MessageIssue&&) override; +private: + CancelMonitor getCancelMonitor(const lsRequestId&); + void sendMsg(LspMessage& msg); + void mainLoop(std::unique_ptr<LspMessage>); + bool dispatch(const std::string&); + template <typename F, typename RequestType = ParamType<F, 0>> + IsRequest<RequestType> ProcessRequestJsonHandler(const F& handler) { + std::lock_guard<std::mutex> lock(m_sendMutex); + if (!jsonHandler->GetRequestJsonHandler(RequestType::kMethodInfo)) + { + jsonHandler->SetRequestJsonHandler(RequestType::kMethodInfo, + [](Reader& visitor) + { + return RequestType::ReflectReader(visitor); + }); + } + } + template <typename T, typename = IsRequest<T>> + void ProcessResponseJsonHandler(T& request) + { + using Response = typename T::Response; + std::lock_guard<std::mutex> lock(m_sendMutex); + if (!jsonHandler->GetResponseJsonHandler(T::kMethodInfo)) + { + jsonHandler->SetResponseJsonHandler(T::kMethodInfo, [](Reader& visitor) + { + if (visitor.HasMember("error")) + return Rsp_Error::ReflectReader(visitor); + return Response::ReflectReader(visitor); + }); + } + } + + struct Data; + + Data* d_ptr; + + std::shared_ptr < MessageJsonHandler> jsonHandler; + std::mutex m_sendMutex; + + std::shared_ptr < Endpoint > local_endpoint; +public: + std::shared_ptr < std::thread > message_producer_thread_; +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RequestInMessage.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RequestInMessage.h new file mode 100644 index 0000000000..163d038a2e --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/RequestInMessage.h @@ -0,0 +1,70 @@ +#pragma once + + +#include "serializer.h" +#include <atomic> +#include <mutex> +#include "lsRequestId.h" +#include "LibLsp/JsonRpc/message.h" +#include "LibLsp/lsp/method_type.h" +#include "lsResponseMessage.h" + +struct RequestInMessage : public LspMessage { + // number or string, actually no null + lsRequestId id; + std::string method; + Kind GetKid() override + { + return REQUEST_MESSAGE; + } + +}; + + + +template <class T, class TDerived > +struct lsRequest : public RequestInMessage +{ + lsRequest(MethodType _method) + { + method = _method; + } + MethodType GetMethodType() const override { return method.c_str(); } + void SetMethodType(MethodType _method) override + { + method = _method; + } \ + void ReflectWriter(Writer& writer) override { + Reflect(writer, static_cast<TDerived&>(*this)); + } + + static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) { + + TDerived* temp = new TDerived(); + std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp); + // Reflect may throw and *message will be partially deserialized. + Reflect(visitor, static_cast<TDerived&>(*temp)); + return message; + } + void swap(lsRequest& arg) noexcept + { + id.swap(arg.id); + method.swap(method); + std::swap(params, arg.params); + } + T params; +}; + + +#define DEFINE_REQUEST_RESPONSE_TYPE(MSG,request_param,response_result,methodInfo)\ +namespace MSG {\ + struct response :public ResponseMessage< response_result, response> {}; \ + struct request : public lsRequest< request_param , request >{\ + static constexpr MethodType kMethodInfo = methodInfo;\ + request():lsRequest(kMethodInfo){} \ + using Response = response;\ + };\ +};\ +MAKE_REFLECT_STRUCT(MSG::request, jsonrpc, id, method, params);\ +MAKE_REFLECT_STRUCT(MSG::response, jsonrpc, id, result); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/ScopeExit.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/ScopeExit.h new file mode 100644 index 0000000000..024b700b4a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/ScopeExit.h @@ -0,0 +1,59 @@ +//===- llvm/ADT/ScopeExit.h - Execute code at scope exit --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the make_scope_exit function, which executes user-defined +// cleanup logic at scope exit. +// +//===----------------------------------------------------------------------===// +#pragma once +#include <type_traits> +#include <utility> + +namespace lsp { +namespace detail { + +template <typename Callable> class scope_exit { + Callable ExitFunction; + bool Engaged = true; // False once moved-from or release()d. + +public: + template <typename Fp> + explicit scope_exit(Fp &&F) : ExitFunction(std::forward<Fp>(F)) {} + + scope_exit(scope_exit &&Rhs) + : ExitFunction(std::move(Rhs.ExitFunction)), Engaged(Rhs.Engaged) { + Rhs.release(); + } + scope_exit(const scope_exit &) = delete; + scope_exit &operator=(scope_exit &&) = delete; + scope_exit &operator=(const scope_exit &) = delete; + + void release() { Engaged = false; } + + ~scope_exit() { + if (Engaged) + ExitFunction(); + } +}; + +} // end namespace detail + +// Keeps the callable object that is passed in, and execute it at the +// destruction of the returned object (usually at the scope exit where the +// returned object is kept). +// +// Interface is specified by p0052r2. +template <typename Callable> + detail::scope_exit<typename std::decay<Callable>::type> +make_scope_exit(Callable &&F) { + return detail::scope_exit<typename std::decay<Callable>::type>( + std::forward<Callable>(F)); +} + +} // end namespace lsp + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/StreamMessageProducer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/StreamMessageProducer.h new file mode 100644 index 0000000000..439a9f1b0e --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/StreamMessageProducer.h @@ -0,0 +1,48 @@ +#pragma once +#include <string> +#include <functional> +#include "MessageProducer.h" +#include <iostream> +#include <memory> +#include "MessageIssue.h" + +namespace lsp { + class istream; +} + +class StreamMessageProducer : public MessageProducer +{ +public: + struct Headers + { + int contentLength = -1; + std::string charset; + void clear() + { + contentLength = -1; + charset.clear(); + } + }; + bool handleMessage(Headers& headers, MessageConsumer callBack); + StreamMessageProducer( + MessageIssueHandler& message_issue_handler, std::shared_ptr < lsp::istream> _input) + : issueHandler(message_issue_handler), + input(_input) + { + } + StreamMessageProducer( + MessageIssueHandler& message_issue_handler) + : issueHandler(message_issue_handler) + { + } + + bool keepRunning = false; + void listen(MessageConsumer) override; + void bind(std::shared_ptr < lsp::istream>); + void parseHeader(std::string& line, Headers& headers); +private: + MessageIssueHandler& issueHandler; + std::shared_ptr < lsp::istream> input; + + +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/TcpServer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/TcpServer.h new file mode 100644 index 0000000000..e533acf056 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/TcpServer.h @@ -0,0 +1,40 @@ +#pragma once + +#include <boost/asio.hpp> +#include <string> +#include "RemoteEndPoint.h" + +namespace lsp { + class Log; +} +namespace lsp +{ + /// The top-level class of the HTTP server. + class TcpServer + { + public: + TcpServer(const TcpServer&) = delete; + TcpServer& operator=(const TcpServer&) = delete; + ~TcpServer(); + /// Construct the server to listen on the specified TCP address and port, and + /// serve up files from the given directory. + explicit TcpServer(const std::string& address, const std::string& port, + std::shared_ptr < MessageJsonHandler> json_handler, + std::shared_ptr < Endpoint> localEndPoint, lsp::Log& ,uint32_t _max_workers = 2); + + /// Run the server's io_context loop. + void run(); + void stop(); + + RemoteEndPoint point; + private: + struct Data; + /// Perform an asynchronous accept operation. + void do_accept(); + + /// Wait for a request to stop the server. + void do_stop(); + Data* d_ptr = nullptr; + }; +} // namespace + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/WebSocketServer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/WebSocketServer.h new file mode 100644 index 0000000000..5206525ceb --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/WebSocketServer.h @@ -0,0 +1,87 @@ +#pragma once + +#include <boost/asio.hpp> +#include <string> +#include <boost/beast/core/tcp_stream.hpp> +#include <boost/beast/websocket/stream.hpp> + + +#include "RemoteEndPoint.h" +#include "stream.h" +#include "threaded_queue.h" + +namespace lsp { + class Log; +} + + +namespace lsp +{ + + + + class websocket_stream_wrapper :public istream, public ostream + { + public: + + websocket_stream_wrapper(boost::beast::websocket::stream<boost::beast::tcp_stream>& _w); + + boost::beast::websocket::stream<boost::beast::tcp_stream>& ws_; + std::atomic<bool> quit{}; + std::shared_ptr < MultiQueueWaiter> request_waiter; + ThreadedQueue< char > on_request; + std::string error_message; + bool fail() override; + + bool eof() override; + + bool good() override; + + websocket_stream_wrapper& read(char* str, std::streamsize count) override; + + int get() override; + + bool bad() override; + + websocket_stream_wrapper& write(const std::string& c) override; + + websocket_stream_wrapper& write(std::streamsize _s) override; + + websocket_stream_wrapper& flush() override; + + void clear() override; + + std::string what() override; + }; + + /// The top-level class of the HTTP server. + class WebSocketServer + { + public: + WebSocketServer(const WebSocketServer&) = delete; + WebSocketServer& operator=(const WebSocketServer&) = delete; + ~WebSocketServer(); + /// Construct the server to listen on the specified TCP address and port, and + /// serve up files from the given directory. + explicit WebSocketServer(const std::string& user_agent, const std::string& address, const std::string& port, + std::shared_ptr < MessageJsonHandler> json_handler, + std::shared_ptr < Endpoint> localEndPoint, lsp::Log& ,uint32_t _max_workers = 2); + + /// Run the server's io_context loop. + void run(); + void stop(); + + RemoteEndPoint point; + private: + struct Data; + /// Perform an asynchronous accept operation. + void do_accept(); + + /// Wait for a request to stop the server. + void do_stop(); + Data* d_ptr = nullptr; + + + }; + + } // namespace diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/json.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/json.h new file mode 100644 index 0000000000..98ee91b544 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/json.h @@ -0,0 +1,81 @@ +#pragma once + +#include "serializer.h" + +#include <rapidjson/document.h> +#include <rapidjson/prettywriter.h> + +class JsonReader : public Reader { + + std::vector<const char*> path_; + + public: + rapidjson::GenericValue<rapidjson::UTF8<>>* m_; + JsonReader(rapidjson::GenericValue<rapidjson::UTF8<>>* m) : m_(m) {} + SerializeFormat Format() const override { return SerializeFormat::Json; } + + bool IsBool() override { return m_->IsBool(); } + bool IsNull() override { return m_->IsNull(); } + bool IsArray() override { return m_->IsArray(); } + bool IsInt() override { return m_->IsInt(); } + bool IsInt64() override { return m_->IsInt64(); } + bool IsUint64() override { return m_->IsUint64(); } + bool IsDouble() override { return m_->IsDouble(); } + bool IsNumber() override { return m_->IsNumber(); } + bool IsString() override { return m_->IsString(); } + + void GetNull() override {} + bool GetBool() override { return m_->GetBool(); } + int GetInt() override { return m_->GetInt(); } + uint32_t GetUint32() override { return uint32_t(m_->GetUint64()); } + int64_t GetInt64() override { return m_->GetInt64(); } + uint64_t GetUint64() override { return m_->GetUint64(); } + double GetDouble() override { return m_->GetDouble(); } + std::string GetString() override { return m_->GetString(); } + + bool HasMember(const char* x) override + { + if (m_->IsObject()) + return m_->HasMember(x); + else + return false; + } + std::unique_ptr<Reader> operator[](const char* x) override { + auto& sub = (*m_)[x]; + return std::unique_ptr<JsonReader>(new JsonReader(&sub)); + } + + std::string ToString() const override; + + void IterMap(std::function<void(const char*, Reader&)> fn) override; + + void IterArray(std::function<void(Reader&)> fn) override; + + void DoMember(const char* name, std::function<void(Reader&)> fn) override; + + std::string GetPath() const; +}; + +class JsonWriter : public Writer { + + public: + rapidjson::Writer<rapidjson::StringBuffer>* m_; + + JsonWriter(rapidjson::Writer<rapidjson::StringBuffer>* m) : m_(m) {} + SerializeFormat Format() const override { return SerializeFormat::Json; } + + void Null() override { m_->Null(); } + void Bool(bool x) override { m_->Bool(x); } + void Int(int x) override { m_->Int(x); } + void Uint32(uint32_t x) override { m_->Uint64(x); } + void Int64(int64_t x) override { m_->Int64(x); } + void Uint64(uint64_t x) override { m_->Uint64(x); } + void Double(double x) override { m_->Double(x); } + void String(const char* x) override { m_->String(x); } + void String(const char* x, size_t len) override { m_->String(x, len); } + void StartArray(size_t) override { m_->StartArray(); } + void EndArray() override { m_->EndArray(); } + void StartObject() override { m_->StartObject(); } + void EndObject() override { m_->EndObject(); } + void Key(const char* name) override { m_->Key(name); } +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsRequestId.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsRequestId.h new file mode 100644 index 0000000000..87e94669ab --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsRequestId.h @@ -0,0 +1,51 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" + +struct lsRequestId { + // The client can send the request id as an int or a string. We should output + // the same format we received. + enum Type { kNone, kInt, kString }; + Type type = kNone; + + int value = -1; + std::string k_string; + bool has_value() const { return type != kNone; } + void swap(lsRequestId& arg) noexcept + { + std::swap(arg, *this); + } + void set(int v) + { + value = v; + type = kInt; + } + void set(const std::string& v) + { + k_string = v; + type = kString; + } + bool operator==(const lsRequestId& rhs) const + { + if (type != rhs.type) return false; + if (type == kInt) + return value == rhs.value; + return k_string == rhs.k_string; + } + bool operator!=(const lsRequestId& rhs) const + { + return !operator==(rhs); + } + bool operator<(const lsRequestId& rhs) const + { + if (type != rhs.type) return false; + if (type == kInt) + return value < rhs.value; + return k_string < rhs.k_string; + } +}; +void Reflect(Reader& visitor, lsRequestId& value); +void Reflect(Writer& visitor, lsRequestId& value); + +// Debug method to convert an id to a string. +std::string ToString(const lsRequestId& id);
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsResponseMessage.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsResponseMessage.h new file mode 100644 index 0000000000..ba94167cf8 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/lsResponseMessage.h @@ -0,0 +1,71 @@ +#pragma once +#include "serializer.h" +#include "lsRequestId.h" +#include "LibLsp/JsonRpc/message.h" +#include "LibLsp/lsp/method_type.h" + + +struct ResponseInMessage :public LspMessage { + + lsRequestId id; + std::string m_methodType; + + virtual MethodType GetMethodType() const override + { + return m_methodType.data(); + }; + virtual void SetMethodType(MethodType _type) override + { + m_methodType = _type; + }; + + Kind GetKid() override + { + return RESPONCE_MESSAGE; + } + virtual bool IsErrorType() + { + return false; + } +}; +template <class TDerived > +struct BaseResponseMessage : ResponseInMessage { + + void ReflectWriter(Writer& writer) override { + Reflect(writer, static_cast<TDerived&>(*this)); + } + static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor) { + + TDerived* temp = new TDerived(); + std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp); + // Reflect may throw and *message will be partially deserialized. + Reflect(visitor, static_cast<TDerived&>(*temp)); + return message; + } + +}; + + +template <class T, class TDerived > +struct ResponseMessage : BaseResponseMessage<TDerived> { + T result; + void swap(ResponseMessage<T, TDerived>& arg) noexcept + { + std::swap(result, arg.result); + this->id.swap(arg.id); + this->m_methodType.swap(arg.m_methodType); + } +}; + +template <class T, class TDerived > +struct ResponseError : BaseResponseMessage<TDerived> { + T error; + bool IsErrorType() override { return true; } + void swap(ResponseError<T, TDerived>& arg) noexcept + { + + this->id.swap(arg.id); + this->m_methodType.swap(arg.m_methodType); + std::swap(error, arg.error); + } +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/macro_map.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/macro_map.h new file mode 100644 index 0000000000..f09ba5b1a7 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/macro_map.h @@ -0,0 +1,134 @@ +/* +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +// Taken from https://github.com/cbeck88/visit_struct. +// +// Usage +// +// #define PRINT_DOUBLE(x) printf(#x " = %d\n", x); +// +// MACRO_MAP(PRINT_DOUBLE, 1, 2, 3) +// #define PRINT_DOUBLES(...) MACRO_MAP(PRINT_DOUBLE, __VA_ARGS__) + +#pragma once + +static constexpr const int max_visitable_members = 69; + +#define VISIT_STRUCT_EXPAND(x) x +#define VISIT_STRUCT_PP_ARG_N( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9, _10,\ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20,\ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30,\ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40,\ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50,\ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60,\ + _61, _62, _63, _64, _65, _66, _67, _68, _69, N, ...) N +#define VISIT_STRUCT_PP_NARG(...) VISIT_STRUCT_EXPAND(VISIT_STRUCT_PP_ARG_N(__VA_ARGS__, \ + 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, \ + 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) + +/* need extra level to force extra eval */ +#define VISIT_STRUCT_CONCAT_(a,b) a ## b +#define VISIT_STRUCT_CONCAT(a,b) VISIT_STRUCT_CONCAT_(a,b) + +#define VISIT_STRUCT_APPLYF0(f) +#define VISIT_STRUCT_APPLYF1(f,_1) f(_1) +#define VISIT_STRUCT_APPLYF2(f,_1,_2) f(_1) f(_2) +#define VISIT_STRUCT_APPLYF3(f,_1,_2,_3) f(_1) f(_2) f(_3) +#define VISIT_STRUCT_APPLYF4(f,_1,_2,_3,_4) f(_1) f(_2) f(_3) f(_4) +#define VISIT_STRUCT_APPLYF5(f,_1,_2,_3,_4,_5) f(_1) f(_2) f(_3) f(_4) f(_5) +#define VISIT_STRUCT_APPLYF6(f,_1,_2,_3,_4,_5,_6) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) +#define VISIT_STRUCT_APPLYF7(f,_1,_2,_3,_4,_5,_6,_7) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) +#define VISIT_STRUCT_APPLYF8(f,_1,_2,_3,_4,_5,_6,_7,_8) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) +#define VISIT_STRUCT_APPLYF9(f,_1,_2,_3,_4,_5,_6,_7,_8,_9) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) +#define VISIT_STRUCT_APPLYF10(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) +#define VISIT_STRUCT_APPLYF11(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) +#define VISIT_STRUCT_APPLYF12(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) +#define VISIT_STRUCT_APPLYF13(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) +#define VISIT_STRUCT_APPLYF14(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) +#define VISIT_STRUCT_APPLYF15(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) +#define VISIT_STRUCT_APPLYF16(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) +#define VISIT_STRUCT_APPLYF17(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) +#define VISIT_STRUCT_APPLYF18(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) +#define VISIT_STRUCT_APPLYF19(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) +#define VISIT_STRUCT_APPLYF20(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) +#define VISIT_STRUCT_APPLYF21(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) +#define VISIT_STRUCT_APPLYF22(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) +#define VISIT_STRUCT_APPLYF23(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) +#define VISIT_STRUCT_APPLYF24(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) +#define VISIT_STRUCT_APPLYF25(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) +#define VISIT_STRUCT_APPLYF26(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) +#define VISIT_STRUCT_APPLYF27(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) +#define VISIT_STRUCT_APPLYF28(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) +#define VISIT_STRUCT_APPLYF29(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) +#define VISIT_STRUCT_APPLYF30(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) +#define VISIT_STRUCT_APPLYF31(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) +#define VISIT_STRUCT_APPLYF32(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) +#define VISIT_STRUCT_APPLYF33(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) +#define VISIT_STRUCT_APPLYF34(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) +#define VISIT_STRUCT_APPLYF35(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) +#define VISIT_STRUCT_APPLYF36(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) +#define VISIT_STRUCT_APPLYF37(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) +#define VISIT_STRUCT_APPLYF38(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) +#define VISIT_STRUCT_APPLYF39(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) +#define VISIT_STRUCT_APPLYF40(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) +#define VISIT_STRUCT_APPLYF41(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) +#define VISIT_STRUCT_APPLYF42(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) +#define VISIT_STRUCT_APPLYF43(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) +#define VISIT_STRUCT_APPLYF44(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) +#define VISIT_STRUCT_APPLYF45(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) +#define VISIT_STRUCT_APPLYF46(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) +#define VISIT_STRUCT_APPLYF47(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) +#define VISIT_STRUCT_APPLYF48(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) +#define VISIT_STRUCT_APPLYF49(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) +#define VISIT_STRUCT_APPLYF50(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) +#define VISIT_STRUCT_APPLYF51(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) +#define VISIT_STRUCT_APPLYF52(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) +#define VISIT_STRUCT_APPLYF53(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) +#define VISIT_STRUCT_APPLYF54(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) +#define VISIT_STRUCT_APPLYF55(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) +#define VISIT_STRUCT_APPLYF56(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) +#define VISIT_STRUCT_APPLYF57(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) +#define VISIT_STRUCT_APPLYF58(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) +#define VISIT_STRUCT_APPLYF59(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) +#define VISIT_STRUCT_APPLYF60(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) +#define VISIT_STRUCT_APPLYF61(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) +#define VISIT_STRUCT_APPLYF62(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) +#define VISIT_STRUCT_APPLYF63(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) +#define VISIT_STRUCT_APPLYF64(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) +#define VISIT_STRUCT_APPLYF65(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) +#define VISIT_STRUCT_APPLYF66(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) +#define VISIT_STRUCT_APPLYF67(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) f(_67) +#define VISIT_STRUCT_APPLYF68(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67,_68) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) f(_67) f(_68) +#define VISIT_STRUCT_APPLYF69(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67,_68,_69) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) f(_67) f(_68) f(_69) + +#define VISIT_STRUCT_APPLY_F_(M, ...) VISIT_STRUCT_EXPAND(M(__VA_ARGS__)) +#define MACRO_MAP(f, ...) VISIT_STRUCT_EXPAND(VISIT_STRUCT_APPLY_F_(VISIT_STRUCT_CONCAT(VISIT_STRUCT_APPLYF, VISIT_STRUCT_PP_NARG(__VA_ARGS__)), f, __VA_ARGS__)) diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/message.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/message.h new file mode 100644 index 0000000000..6603f3fb3a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/message.h @@ -0,0 +1,34 @@ +#pragma once + +#include <atomic> +#include <string> +#include <iostream> +#include <LibLsp/JsonRpc/serializer.h> +#include "LibLsp/lsp/method_type.h" + +struct LspMessage +{ +public: + std::string jsonrpc = "2.0"; + virtual void ReflectWriter(Writer&) = 0; + + // Send the message to the language client by writing it to stdout. + void Write(std::ostream& out); + + + virtual MethodType GetMethodType() const = 0; + virtual void SetMethodType(MethodType) = 0; + + virtual ~LspMessage()=default; + enum Kind + { + REQUEST_MESSAGE, + RESPONCE_MESSAGE, + NOTIFICATION_MESSAGE + }; + + virtual Kind GetKid() = 0; + virtual std::string ToJson() ; + +}; + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h new file mode 100644 index 0000000000..71b6bede59 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/serializer.h @@ -0,0 +1,378 @@ +#pragma once + +#include "macro_map.h" +#ifdef boost +#include "optional.hpp" +#else +#include <boost/optional.hpp> +#endif + +#include <cassert> +#include <memory> +#include <string> +#include <type_traits> +#include <vector> +#include <functional> +#include <map> +#include <algorithm> + + +struct AbsolutePath; + +enum class SerializeFormat { Json, MessagePack }; + +// A tag type that can be used to write `null` to json. +struct JsonNull +{ + void swap(JsonNull& arg) noexcept; +}; + + + +class Reader { +public: + virtual ~Reader() {} + virtual SerializeFormat Format() const = 0; + + virtual bool IsBool() = 0; + virtual bool IsNull() = 0; + virtual bool IsArray() = 0; + virtual bool IsInt() = 0; + virtual bool IsInt64() = 0; + virtual bool IsUint64() = 0; + virtual bool IsDouble() = 0; + virtual bool IsNumber() = 0; + virtual bool IsString() = 0; + + virtual void GetNull() = 0; + virtual bool GetBool() = 0; + virtual int GetInt() = 0; + virtual uint32_t GetUint32() = 0; + virtual int64_t GetInt64() = 0; + virtual uint64_t GetUint64() = 0; + virtual double GetDouble() = 0; + virtual std::string GetString() = 0; + + virtual bool HasMember(const char* x) = 0; + virtual std::unique_ptr<Reader> operator[](const char* x) = 0; + virtual void IterMap( std::function<void(const char*, Reader&)> fn) = 0; + virtual void IterArray(std::function<void(Reader&)> fn) = 0; + virtual void DoMember(const char* name, std::function<void(Reader&)> fn) = 0; + virtual std::string ToString() const = 0; +}; + + + +class Writer { +public: + virtual ~Writer() {} + virtual SerializeFormat Format() const = 0; + + virtual void Null() = 0; + virtual void Bool(bool x) = 0; + virtual void Int(int x) = 0; + virtual void Uint32(uint32_t x) = 0; + virtual void Int64(int64_t x) = 0; + virtual void Uint64(uint64_t x) = 0; + virtual void Double(double x) = 0; + virtual void String(const char* x) = 0; + virtual void String(const char* x, size_t len) = 0; + virtual void StartArray(size_t) = 0; + virtual void EndArray() = 0; + virtual void StartObject() = 0; + virtual void EndObject() = 0; + virtual void Key(const char* name) = 0; +}; + + + +struct optionals_mandatory_tag {}; + +#define REFLECT_MEMBER_START() ReflectMemberStart(visitor, value) +#define REFLECT_MEMBER_END() ReflectMemberEnd(visitor, value); +#define REFLECT_MEMBER_END1(value) ReflectMemberEnd(visitor, value); +#define REFLECT_MEMBER(name) ReflectMember(visitor, #name, value.name) +#define REFLECT_MEMBER_OPTIONALS(name) \ + ReflectMember(visitor, #name, value.name, optionals_mandatory_tag{}) +#define REFLECT_MEMBER2(name, value) ReflectMember(visitor, name, value) + +#define MAKE_REFLECT_TYPE_PROXY(type_name) \ + MAKE_REFLECT_TYPE_PROXY2(type_name, std::underlying_type<type_name>::type) +#define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \ + inline void Reflect(Reader& visitor, type& value) { \ + as_type value0; \ + ::Reflect(visitor, value0); \ + value = static_cast<type>(value0); \ + } \ + inline void Reflect(Writer& visitor, type& value) { \ + auto value0 = static_cast<as_type>(value); \ + ::Reflect(visitor, value0); \ + } + +#define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name); +#define _MAPPABLE_REFLECT_MEMBER_OPTIONALS(name) REFLECT_MEMBER_OPTIONALS(name); + +#define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \ + template <typename TVisitor> \ + void Reflect(TVisitor& visitor, type& value) { \ + REFLECT_MEMBER_START(); \ + REFLECT_MEMBER_END(); \ + } + +#define MAKE_REFLECT_STRUCT(type, ...) \ + template <typename TVisitor> \ + void Reflect(TVisitor& visitor, type& value) { \ + REFLECT_MEMBER_START(); \ + MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \ + REFLECT_MEMBER_END(); \ + } + + +#define _MAPPABLE_SWAP_MEMBER(name) std::swap(name,arg.name); + +#define MAKE_SWAP_METHOD(type, ...) \ +void swap(type& arg) noexcept{ \ + MACRO_MAP(_MAPPABLE_SWAP_MEMBER, __VA_ARGS__) \ +} + +#define MAKE_REFLECT_STRUCT_OPTIONALS_MANDATORY(type, ...) \ + template <typename TVisitor> \ + void Reflect(TVisitor& visitor, type& value) { \ + REFLECT_MEMBER_START(); \ + MACRO_MAP(_MAPPABLE_REFLECT_MEMBER_OPTIONALS, __VA_ARGS__) \ + REFLECT_MEMBER_END(); \ + } + +// clang-format off +// Config has many fields, we need to support at least its number of fields. +#define NUM_VA_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,N,...) N +#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1) +// clang-format on + +#define _MAPPABLE_REFLECT_ARRAY(name) Reflect(visitor, value.name); + +// Reflects the struct so it is serialized as an array instead of an object. +// This currently only supports writers. +#define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \ + inline void Reflect(Writer& visitor, type& value) { \ + visitor.StartArray(NUM_VA_ARGS(__VA_ARGS__)); \ + MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \ + visitor.EndArray(); \ + } + +//// Elementary types + +void Reflect(Reader& visitor, uint8_t& value); +void Reflect(Writer& visitor, uint8_t& value); + +void Reflect(Reader& visitor, short& value); +void Reflect(Writer& visitor, short& value); + +void Reflect(Reader& visitor, unsigned short& value); +void Reflect(Writer& visitor, unsigned short& value); + +void Reflect(Reader& visitor, int& value); +void Reflect(Writer& visitor, int& value); + +void Reflect(Reader& visitor, unsigned& value); +void Reflect(Writer& visitor, unsigned& value); + +void Reflect(Reader& visitor, long& value); +void Reflect(Writer& visitor, long& value); + +void Reflect(Reader& visitor, unsigned long& value); +void Reflect(Writer& visitor, unsigned long& value); + +void Reflect(Reader& visitor, long long& value); +void Reflect(Writer& visitor, long long& value); + +void Reflect(Reader& visitor, unsigned long long& value); +void Reflect(Writer& visitor, unsigned long long& value); + +void Reflect(Reader& visitor, double& value); +void Reflect(Writer& visitor, double& value); + +void Reflect(Reader& visitor, bool& value); +void Reflect(Writer& visitor, bool& value); + +void Reflect(Reader& visitor, std::string& value); +void Reflect(Writer& visitor, std::string& value); + +void Reflect(Reader& visitor, JsonNull& value); +void Reflect(Writer& visitor, JsonNull& value); + +void Reflect(Reader& visitor, SerializeFormat& value); +void Reflect(Writer& visitor, SerializeFormat& value); + +//// Type constructors + +template <typename T> +void Reflect(Reader& visitor, boost::optional<T>& value) { + if (visitor.IsNull()) { + visitor.GetNull(); + return; + } + T real_value; + Reflect(visitor, real_value); + value = std::move(real_value); +} +template <typename T> +void Reflect(Writer& visitor, boost::optional<T>& value) { + if (value) + Reflect(visitor, *value); + else + visitor.Null(); +} + + +template <typename T> +void ReflectMember(Writer& visitor, const char* name, boost::optional<T>& value) { + // For TypeScript optional property key?: value in the spec, + // We omit both key and value if value is std::nullopt (null) for JsonWriter + // to reduce output. But keep it for other serialization formats. + if (value || visitor.Format() != SerializeFormat::Json) { + visitor.Key(name); + Reflect(visitor, value); + } +} + + + +template <typename T> +void ReflectMember(Writer& visitor, + const char* name, + T& value, + optionals_mandatory_tag) { + visitor.Key(name); + Reflect(visitor, value); +} +template <typename T> +void ReflectMember(Reader& visitor, + const char* name, + T& value, + optionals_mandatory_tag) { + Reflect(visitor, value); +} + +template<class T > +void Reflect(Reader& visitor, std::map<std::string, T>& value) +{ + visitor.IterMap([&](const char* name,Reader& entry) { + T entry_value; + Reflect(entry, entry_value); + value[name]=(std::move(entry_value)); + }); +} +template<class _Ty > +void Reflect(Writer& visitor, std::map<std::string, _Ty>& value) +{ + REFLECT_MEMBER_START(); + for (auto& it : value) + { + visitor.Key(it.first.c_str()); + Reflect(visitor, it.second); + } + REFLECT_MEMBER_END(); +} + +// std::vector +template <typename T> +void Reflect(Reader& visitor, std::vector<T>& values) { + visitor.IterArray([&](Reader& entry) { + T entry_value; + Reflect(entry, entry_value); + values.push_back(std::move(entry_value)); + }); +} + + +template <typename T> +void Reflect(Writer& visitor, std::vector<T>& values) { + visitor.StartArray(values.size()); + for (auto& value : values) + Reflect(visitor, value); + visitor.EndArray(); +} + +// ReflectMember + +inline void DefaultReflectMemberStart(Writer& visitor) { + visitor.StartObject(); +} +inline void DefaultReflectMemberStart(Reader& visitor) {} + +template <typename T> +bool ReflectMemberStart(Reader& visitor, T& value) { + return false; +} +template <typename T> +bool ReflectMemberStart(Writer& visitor, T& value) { + visitor.StartObject(); + return true; +} + +template <typename T> +void ReflectMemberEnd(Reader& visitor, T& value) {} +template <typename T> +void ReflectMemberEnd(Writer& visitor, T& value) { + visitor.EndObject(); +} + +template <typename T> +void ReflectMember(Reader& visitor, const char* name, T& value) { + visitor.DoMember(name, [&](Reader& child) { Reflect(child, value); }); +} +template <typename T> +void ReflectMember(Writer& visitor, const char* name, T& value) { + visitor.Key(name); + Reflect(visitor, value); +} + +template<class _Ty1, class _Ty2> +void Reflect(Writer& visitor, std::pair< boost::optional<_Ty1>, boost::optional<_Ty2> >& value) +{ + if (value.first) + { + Reflect(visitor, value.first); + } + else + { + Reflect(visitor, value.second); + } +} +template<class _Ty2> +void Reflect(Reader& visitor, std::pair< boost::optional<bool>, boost::optional<_Ty2> >& value) +{ + if(visitor.IsBool()) + { + Reflect(visitor, value.first); + return; + } + + Reflect(visitor, value.second); +} +template<class _Ty2> +void Reflect(Reader& visitor, std::pair< boost::optional<std::string>, boost::optional<_Ty2> >& value) +{ + if (visitor.IsString()) + { + Reflect(visitor, value.first); + return; + } + + Reflect(visitor, value.second); +} + + +template<class _Ty1, class _Ty2> +void Reflect(Reader& visitor, std::pair< boost::optional<_Ty1>, boost::optional<_Ty2> >& value) +{ + try + { + Reflect(visitor, value.second); + } + catch (...) + { + Reflect(visitor, value.first); + } +} diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/stream.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/stream.h new file mode 100644 index 0000000000..549c361950 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/stream.h @@ -0,0 +1,196 @@ +#pragma once +#include <mutex> +#include <string> +namespace lsp +{ + class stream + { + public: + virtual ~stream() = default; + virtual bool fail() = 0; + virtual bool bad() = 0; + virtual bool eof() = 0; + virtual bool good() = 0; + virtual void clear() = 0; + virtual std::string what() = 0; + virtual bool need_to_clear_the_state() + { + return false; + } + + bool operator!() + { + return bad(); + } + }; + class istream : public stream + { + public: + virtual int get() = 0; + virtual ~istream() = default; + virtual istream& read(char* str, std::streamsize count) = 0; + }; + template <class T > + class base_istream : public istream + { + public: + explicit base_istream(T& _t) :_impl(_t) + { + + } + + int get() override + { + return _impl.get(); + } + bool fail() override + { + return _impl.fail(); + } + bool bad() override + { + return _impl.bad(); + } + bool eof() override + { + return _impl.eof(); + } + bool good() override + { + return _impl.good(); + } + istream& read(char* str, std::streamsize count) override + { + _impl.read(str, count); + return *this; + } + + void clear() override + { + _impl.clear(); + } + T& _impl; + }; + class ostream : public stream + { + public: + virtual ~ostream() = default; + + virtual ostream& write(const std::string&) = 0; + virtual ostream& write(std::streamsize) = 0; + virtual ostream& flush() = 0; + + }; + template <class T > + class base_ostream : public ostream + { + public: + explicit base_ostream(T& _t) :_impl(_t) + { + + } + + bool fail() override + { + return _impl.fail(); + } + bool good() override + { + return _impl.good(); + } + bool bad() override + { + return _impl.bad(); + } + bool eof() override + { + return _impl.eof(); + } + + ostream& write(const std::string& c) override + { + _impl << c; + return *this; + } + + ostream& write(std::streamsize _s) override + { + + _impl << std::to_string(_s); + return *this; + } + + ostream& flush() override + { + _impl.flush(); + return *this; + } + + void clear() override + { + _impl.clear(); + } + protected: + T& _impl; + }; + + template <class T > + class base_iostream : public istream, public ostream + { + public: + explicit base_iostream(T& _t) :_impl(_t) + { + + } + + int get() override + { + return _impl.get(); + } + bool fail() override + { + return _impl.fail(); + } + bool bad() override + { + return _impl.bad(); + } + bool eof() override + { + return _impl.eof(); + } + bool good() override + { + return _impl.good(); + } + istream& read(char* str, std::streamsize count) override + { + _impl.read(str, count); + return *this; + } + ostream& write(const std::string& c) override + { + _impl << c; + return *this; + } + + ostream& write(std::streamsize _s) override + { + _impl << std::to_string(_s); + return *this; + } + + ostream& flush() override + { + _impl.flush(); + return *this; + } + + void clear() override + { + _impl.clear(); + } + protected: + T& _impl; + }; +} diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/threaded_queue.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/threaded_queue.h new file mode 100644 index 0000000000..cca9f9a486 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/threaded_queue.h @@ -0,0 +1,249 @@ +#pragma once + +#include <boost/optional/optional.hpp> +#include <algorithm> +#include <atomic> +#include <condition_variable> +#include <deque> +#include <memory> +#include <mutex> +#include <tuple> +#include <utility> +#include <vector> + + +struct MultiQueueWaiter; + +struct BaseThreadQueue { + virtual ~BaseThreadQueue() = default; + + virtual bool IsEmpty() = 0; + + std::shared_ptr<MultiQueueWaiter> waiter; +}; + +// std::lock accepts two or more arguments. We define an overload for one +// argument. +namespace std { +template <typename Lockable> +void lock(Lockable& l) { + l.lock(); +} +} // namespace std + +template <typename... Queue> +struct MultiQueueLock { + MultiQueueLock(Queue... lockable) : tuple_{lockable...} { lock(); } + ~MultiQueueLock() { unlock(); } + void lock() { lock_impl(typename std::index_sequence_for<Queue...>{}); } + void unlock() { unlock_impl(typename std::index_sequence_for<Queue...>{}); } + + private: + template <size_t... Is> + void lock_impl(std::index_sequence<Is...>) { + std::lock(std::get<Is>(tuple_)->mutex...); + } + + template <size_t... Is> + void unlock_impl(std::index_sequence<Is...>) { + (void)std::initializer_list<int>{ + (std::get<Is>(tuple_)->mutex.unlock(), 0)...}; + } + + std::tuple<Queue...> tuple_; +}; + +struct MultiQueueWaiter { + static bool HasState(std::initializer_list<BaseThreadQueue*> queues); + + bool ValidateWaiter(std::initializer_list<BaseThreadQueue*> queues); + + template <typename... BaseThreadQueue> + bool Wait(std::atomic<bool>& quit, BaseThreadQueue... queues) { + MultiQueueLock<BaseThreadQueue...> l(queues...); + while (!quit.load(std::memory_order_relaxed)) { + if (HasState({ queues... })) + return false; + cv.wait(l); + } + return true; + } + template <typename... BaseThreadQueue> + void WaitUntil(std::chrono::steady_clock::time_point t, + BaseThreadQueue... queues) { + MultiQueueLock<BaseThreadQueue...> l(queues...); + if (!HasState({ queues... })) + cv.wait_until(l, t); + } + template <typename... BaseThreadQueue> + void Wait(BaseThreadQueue... queues) { + assert(ValidateWaiter({queues...})); + + MultiQueueLock<BaseThreadQueue...> l(queues...); + while (!HasState({queues...})) + cv.wait(l); + } + + std::condition_variable_any cv; +}; + +// A threadsafe-queue. http://stackoverflow.com/a/16075550 +template <class T> +struct ThreadedQueue : public BaseThreadQueue { + public: + ThreadedQueue() : ThreadedQueue(std::make_shared<MultiQueueWaiter>()) {} + + explicit ThreadedQueue(std::shared_ptr<MultiQueueWaiter> waiter) + : total_count_(0) { + this->waiter = waiter; + } + + // Returns the number of elements in the queue. This is lock-free. + size_t Size() const { return total_count_; } + + // Add an element to the queue. + void Enqueue(T&& t, bool priority) { + { + std::lock_guard<std::mutex> lock(mutex); + if (priority) + priority_.push_back(std::move(t)); + else + queue_.push_back(std::move(t)); + ++total_count_; + } + waiter->cv.notify_one(); + } + + // Add a set of elements to the queue. + void EnqueueAll(std::vector<T>&& elements, bool priority) { + if (elements.empty()) + return; + + { + std::lock_guard<std::mutex> lock(mutex); + total_count_ += elements.size(); + for (T& element : elements) { + if (priority) + priority_.push_back(std::move(element)); + else + queue_.push_back(std::move(element)); + } + elements.clear(); + } + + waiter->cv.notify_all(); + } + + // Returns true if the queue is empty. This is lock-free. + bool IsEmpty() { return total_count_ == 0; } + + // Get the first element from the queue. Blocks until one is available. + T Dequeue() { + std::unique_lock<std::mutex> lock(mutex); + waiter->cv.wait(lock, + [&]() { return !priority_.empty() || !queue_.empty(); }); + + auto execute = [&](std::deque<T>* q) { + auto val = std::move(q->front()); + q->pop_front(); + --total_count_; + return std::move(val); + }; + if (!priority_.empty()) + return execute(&priority_); + return execute(&queue_); + } + + // Get the first element from the queue without blocking. Returns a null + // value if the queue is empty. + boost::optional<T> TryDequeue(bool priority) { + std::lock_guard<std::mutex> lock(mutex); + + auto pop = [&](std::deque<T>* q) { + auto val = std::move(q->front()); + q->pop_front(); + --total_count_; + return std::move(val); + }; + + auto get_result = [&](std::deque<T>* first, + std::deque<T>* second) -> boost::optional<T> { + if (!first->empty()) + return pop(first); + if (!second->empty()) + return pop(second); + return {}; + }; + + if (priority) + return get_result(&priority_, &queue_); + return get_result(&queue_, &priority_); + } + // Return all elements in the queue. + std::vector<T> DequeueAll() { + std::lock_guard<std::mutex> lock(mutex); + + total_count_ = 0; + + std::vector<T> result; + result.reserve(priority_.size() + queue_.size()); + while (!priority_.empty()) { + result.emplace_back(std::move(priority_.front())); + priority_.pop_front(); + } + while (!queue_.empty()) { + result.emplace_back(std::move(queue_.front())); + queue_.pop_front(); + } + + return result; + } + std::vector<T> TryDequeueSome(size_t num) { + std::lock_guard<std::mutex> lock(mutex); + + std::vector<T> result; + num = std::min(num, priority_.size() + queue_.size()); + total_count_ -= num; + result.reserve(num); + while (num) + { + if(!priority_.empty()) { + result.emplace_back(std::move(priority_.front())); + priority_.pop_front(); + } + else + { + break; + } + num -= 1; + } + while (num) + { + if (!queue_.empty()) { + result.emplace_back(std::move(queue_.front())); + queue_.pop_front(); + } + else + { + break; + } + num -= 1; + } + return result; + } + template <typename Fn> + void Iterate(Fn fn) { + std::lock_guard<std::mutex> lock(mutex); + for (auto& entry : priority_) + fn(entry); + for (auto& entry : queue_) + fn(entry); + } + + mutable std::mutex mutex; + + private: + std::atomic<int> total_count_; + std::deque<T> priority_; + std::deque<T> queue_; +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/traits.h b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/traits.h new file mode 100644 index 0000000000..ce8905a840 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/JsonRpc/traits.h @@ -0,0 +1,158 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + + +#include <tuple> +#include <type_traits> + +namespace lsp { +namespace traits { + +// NthTypeOf returns the `N`th type in `Types` +template <int N, typename... Types> +using NthTypeOf = typename std::tuple_element<N, std::tuple<Types...>>::type; + +// `IsTypeOrDerived<BASE, T>::value` is true iff `T` is of type `BASE`, or +// derives from `BASE`. +template <typename BASE, typename T> +using IsTypeOrDerived = std::integral_constant< + bool, + std::is_base_of<BASE, typename std::decay<T>::type>::value || + std::is_same<BASE, typename std::decay<T>::type>::value>; + +// `EachIsTypeOrDerived<N, BASES, TYPES>::value` is true iff all of the types in +// the std::tuple `TYPES` is of, or derives from the corresponding indexed type +// in the std::tuple `BASES`. +// `N` must be equal to the number of types in both the std::tuple `BASES` and +// `TYPES`. +template <int N, typename BASES, typename TYPES> +struct EachIsTypeOrDerived { + using base = typename std::tuple_element<N - 1, BASES>::type; + using type = typename std::tuple_element<N - 1, TYPES>::type; + using last_matches = IsTypeOrDerived<base, type>; + using others_match = EachIsTypeOrDerived<N - 1, BASES, TYPES>; + static constexpr bool value = last_matches::value && others_match::value; +}; + +// EachIsTypeOrDerived specialization for N = 1 +template <typename BASES, typename TYPES> +struct EachIsTypeOrDerived<1, BASES, TYPES> { + using base = typename std::tuple_element<0, BASES>::type; + using type = typename std::tuple_element<0, TYPES>::type; + static constexpr bool value = IsTypeOrDerived<base, type>::value; +}; + +// EachIsTypeOrDerived specialization for N = 0 +template <typename BASES, typename TYPES> +struct EachIsTypeOrDerived<0, BASES, TYPES> { + static constexpr bool value = true; +}; + +// Signature describes the signature of a function. +template <typename RETURN, typename... PARAMETERS> +struct Signature { + // The return type of the function signature + using ret = RETURN; + // The parameters of the function signature held in a std::tuple + using parameters = std::tuple<PARAMETERS...>; + // The type of the Nth parameter of function signature + template <std::size_t N> + using parameter = NthTypeOf<N, PARAMETERS...>; + // The total number of parameters + static constexpr std::size_t parameter_count = sizeof...(PARAMETERS); +}; + +// SignatureOf is a traits helper that infers the signature of the function, +// method, static method, lambda, or function-like object `F`. +template <typename F> +struct SignatureOf { + // The signature of the function-like object `F` + using type = typename SignatureOf<decltype(&F::operator())>::type; +}; + +// SignatureOf specialization for a regular function or static method. +template <typename R, typename... ARGS> +struct SignatureOf<R (*)(ARGS...)> { + // The signature of the function-like object `F` + using type = Signature<typename std::decay<R>::type, + typename std::decay<ARGS>::type...>; +}; + +// SignatureOf specialization for a non-static method. +template <typename R, typename C, typename... ARGS> +struct SignatureOf<R (C::*)(ARGS...)> { + // The signature of the function-like object `F` + using type = Signature<typename std::decay<R>::type, + typename std::decay<ARGS>::type...>; +}; + +// SignatureOf specialization for a non-static, const method. +template <typename R, typename C, typename... ARGS> +struct SignatureOf<R (C::*)(ARGS...) const> { + // The signature of the function-like object `F` + using type = Signature<typename std::decay<R>::type, + typename std::decay<ARGS>::type...>; +}; + +// SignatureOfT is an alias to `typename SignatureOf<F>::type`. +template <typename F> +using SignatureOfT = typename SignatureOf<F>::type; + +// ParameterType is an alias to `typename SignatureOf<F>::type::parameter<N>`. +template <typename F, std::size_t N> +using ParameterType = typename SignatureOfT<F>::template parameter<N>; + +// `HasSignature<F, S>::value` is true iff the function-like `F` has a matching +// signature to the function-like `S`. +template <typename F, typename S> +using HasSignature = std::integral_constant< + bool, + std::is_same<SignatureOfT<F>, SignatureOfT<S>>::value>; + +// `Min<A, B>::value` resolves to the smaller value of A and B. +template <std::size_t A, std::size_t B> +using Min = std::integral_constant<std::size_t, (A < B ? A : B)>; + +// `CompatibleWith<F, S>::value` is true iff the function-like `F` +// can be called with the argument types of the function-like `S`. Return type +// of the two functions are not considered. +template <typename F, typename S> +using CompatibleWith = std::integral_constant< + bool, + (SignatureOfT<S>::parameter_count == SignatureOfT<F>::parameter_count) && + EachIsTypeOrDerived<Min<SignatureOfT<S>::parameter_count, + SignatureOfT<F>::parameter_count>::value, + typename SignatureOfT<S>::parameters, + typename SignatureOfT<F>::parameters>::value>; + +// If `CONDITION` is true then EnableIf resolves to type T, otherwise an +// invalid type. +template <bool CONDITION, typename T = void> +using EnableIf = typename std::enable_if<CONDITION, T>::type; + +// If `BASE` is a base of `T` then EnableIfIsType resolves to type `TRUE`, +// otherwise an invalid type. +template <typename BASE, typename T, typename TRUE_ = void> +using EnableIfIsType = EnableIf<IsTypeOrDerived<BASE, T>::value, TRUE_>; + +// If the function-like `F` has a matching signature to the function-like `S` +// then EnableIfHasSignature resolves to type `TRUE`, otherwise an invalid type. +template <typename F, typename S, typename TRUE_ = void> +using EnableIfHasSignature = EnableIf<HasSignature<F, S>::value, TRUE_>; + +} // namespace traits +} // namespace lsp + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/AbsolutePath.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/AbsolutePath.h new file mode 100644 index 0000000000..ef1ee43860 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/AbsolutePath.h @@ -0,0 +1,27 @@ +#pragma once + +#include <LibLsp/JsonRpc/serializer.h> +#include <string> + +struct AbsolutePath { + static AbsolutePath BuildDoNotUse(const std::string& path); + + // Try not to use this. + AbsolutePath(); + + // Provide implicit conversions to std::string for the time being. + AbsolutePath(const std::string& path, bool validate = true); + operator std::string() const; + + bool operator==(const AbsolutePath& rhs) const; + bool operator!=(const AbsolutePath& rhs) const; + bool operator<(const AbsolutePath& rhs) const; + bool operator>(const AbsolutePath& rhs) const; + std::string path; + bool qualify = true; +}; + + +void Reflect(Reader& visitor, AbsolutePath& value); +void Reflect(Writer& visitor, AbsolutePath& value); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/ClientPreferences.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ClientPreferences.h new file mode 100644 index 0000000000..7adf557f83 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ClientPreferences.h @@ -0,0 +1,306 @@ +#pragma once +#include <LibLsp/lsp/general/lsClientCapabilities.h> +#include <LibLsp/lsp/utils.h> +#include <memory> +#include <vector> +#include <string> + +class ClientPreferences +{ +public: + + std::shared_ptr<lsWorkspaceClientCapabilites> workspace; + lsTextDocumentClientCapabilities textDocument ; + + ClientPreferences(const lsClientCapabilities& capabilities) + { + v3supported = capabilities.textDocument.has_value(); + if (v3supported) + textDocument = capabilities.textDocument.value(); + if(capabilities.workspace) + { + workspace = std::make_shared<lsWorkspaceClientCapabilites>(capabilities.workspace.value()); + } + } + + bool v3supported=false; + + bool isSignatureHelpSupported() { + + return v3supported && (textDocument.signatureHelp); + } + bool isWorkspaceDidChangeConfigurationSupported() const + { + return workspace && isDynamicRegistrationSupported(workspace->didChangeConfiguration); + } + bool isWorkspaceFoldersSupported() { + return workspace != nullptr && isTrue(workspace->workspaceFolders); + } + + bool isCompletionDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.completion); + } + + bool isCompletionSnippetsSupported() { + //@formatter:off + if(!v3supported || !textDocument.completion) + { + return false; + } + const auto& completion = textDocument.completion.value(); + if(completion.completionItem) + { + return isTrue(completion.completionItem.value().snippetSupport); + } + return false; + } + + bool isV3Supported() { + return v3supported; + } + + bool isFormattingDynamicRegistrationSupported() { + return v3supported && isDynamicRegistrationSupported(textDocument.formatting); + } + + bool isRangeFormattingDynamicRegistrationSupported() { + return v3supported && isDynamicRegistrationSupported(textDocument.rangeFormatting); + } + + bool isOnTypeFormattingDynamicRegistrationSupported() { + return v3supported && isDynamicRegistrationSupported(textDocument.onTypeFormatting); + } + + bool isCodeLensDynamicRegistrationSupported() { + return v3supported && isDynamicRegistrationSupported(textDocument.codeLens); + } + + bool isSignatureHelpDynamicRegistrationSupported() { + return v3supported && isDynamicRegistrationSupported(textDocument.signatureHelp); + } + template<typename T> + static bool isDynamicRegistrationSupported(boost::optional<T>& capability) + { + if(capability) + return (capability.value().dynamicRegistration.value()); + return false; + } + + bool isTrue(const boost::optional<bool>& value) + { + return value.get_value_or(false); + } + + bool isRenameDynamicRegistrationSupported() { + return v3supported && isDynamicRegistrationSupported(textDocument.rename); + } + + bool isExecuteCommandDynamicRegistrationSupported() { + return v3supported && workspace != nullptr && isDynamicRegistrationSupported(workspace->executeCommand); + } + + bool isWorkspaceSymbolDynamicRegistered() { + return v3supported && workspace != nullptr && isDynamicRegistrationSupported(workspace->symbol); + } + + bool isWorkspaceChangeWatchedFilesDynamicRegistered() { + return v3supported && workspace != nullptr && isDynamicRegistrationSupported(workspace->didChangeWatchedFiles); + } + + bool isDocumentSymbolDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.documentSymbol); + } + + bool isCodeActionDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.codeAction); + } + + bool isDefinitionDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.definition); + } + + bool isTypeDefinitionDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.typeDefinition); + } + + bool isHoverDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.hover); + } + + bool isReferencesDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.references); + } + + bool isDocumentHighlightDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.documentHighlight); + } + + bool isFoldgingRangeDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.foldingRange); + } + + bool isImplementationDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.implementation); + } + + bool isSelectionRangeDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.selectionRange); + } + + bool isWillSaveRegistered() { + return v3supported && isTrue(textDocument.synchronization.willSave); + } + + bool isWillSaveWaitUntilRegistered() { + return v3supported && isTrue(textDocument.synchronization.willSaveWaitUntil); + } + + bool isWorkspaceApplyEditSupported() { + return workspace != nullptr && isTrue(workspace->applyEdit); + } + + bool isSupportsCompletionDocumentationMarkdown() { + + if (!v3supported || !textDocument.completion) + { + return false; + } + const auto& completion = textDocument.completion.value(); + if (completion.completionItem) + { + auto& documentationFormat = completion.completionItem.value().documentationFormat; + if(documentationFormat) + { + auto& data = documentationFormat.value(); + for(auto& it : data) + { + if(it == "markdown") + { + return true; + } + } + } + } + return false; + + } + + + bool isWorkspaceEditResourceChangesSupported() { + if(!workspace) return false; + + if(workspace->workspaceEdit) + { + return isTrue(workspace->workspaceEdit.value().resourceChanges); + } + return false; + } + static bool contains(const std::vector<std::string>& v, const std::string& target) + { + for(auto& it : v) + { + if(it == target) return true; + } + return false; + } + bool isResourceOperationSupported() const + { + if (!workspace) return false; + if (!workspace->workspaceEdit) + { + return false; + } + auto& it = (workspace->workspaceEdit.value()); + if(!it.resourceOperations) return false; + const auto& resourceOperations = it.resourceOperations.value(); + return contains(resourceOperations, "create") && contains(resourceOperations, "rename") && contains(resourceOperations, "delete"); + + } + + /** + * {@code true} if the client has explicitly set the + * {@code textDocument.documentSymbol.hierarchicalDocumentSymbolSupport} to + * {@code true} when initializing the LS. Otherwise, {@code false}. + */ + bool isHierarchicalDocumentSymbolSupported() { + if(!v3supported || !textDocument.documentSymbol) return false; + return isTrue(textDocument.documentSymbol.value().hierarchicalDocumentSymbolSupport); + + } + + bool isSemanticHighlightingSupported() { + //@formatter:off + if (!v3supported || !textDocument.semanticHighlightingCapabilities) return false; + return isTrue(textDocument.semanticHighlightingCapabilities.value().semanticHighlighting); + //@formatter:on + } + + /** + * {@code true} if the client has explicitly set the + * {@code textDocument.codeAction.codeActionLiteralSupport.codeActionKind.valueSet} + * value. Otherwise, {@code false}. + */ + bool isSupportedCodeActionKind(const std::string& kind) { + if (!v3supported || !textDocument.codeAction) return false; + //@formatter:off + const auto& codeAction = textDocument.codeAction.value(); + if(codeAction.codeActionLiteralSupport) + { + const auto& codeActionKind = codeAction.codeActionLiteralSupport.value().codeActionKind; + if(codeActionKind) + { + const auto& valueSet = codeActionKind.value().valueSet; + if(valueSet) + { + for(auto& k : valueSet.value()) + { + if(lsp::StartsWith(kind,k)) + { + return true; + } + } + } + } + } + return false; + + //@formatter:on + } + + /** + * {@code true} if the client has explicitly set the + * {@code textDocument.publishDiagnostics.tagSupport} to + * {@code true} when initializing the LS. Otherwise, {@code false}. + */ + bool isDiagnosticTagSupported() { + if (!v3supported || !textDocument.publishDiagnostics) return false; + const auto& publishDiagnostics = textDocument.publishDiagnostics.value(); + if(publishDiagnostics.tagSupport) + { + isTagSupported(publishDiagnostics.tagSupport); + } + return false; + } + + bool isTagSupported(const boost::optional < std::pair<boost::optional<bool>, + boost::optional<DiagnosticsTagSupport> > >& tagSupport) { + if(tagSupport) + { + auto &v = tagSupport.value(); + if (v.first) + { + return v.first.value(); + } + if (v.second) { + return !v.second.value().valueSet.empty(); + } + } + return false; + } + + bool isCallHierarchyDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.callHierarchy); + } + +}; + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/CodeActionParams.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/CodeActionParams.h new file mode 100644 index 0000000000..a1e3f1dcc1 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/CodeActionParams.h @@ -0,0 +1,114 @@ +#pragma once +#include "LibLsp/lsp/method_type.h" +#include "LibLsp/JsonRpc/message.h" +#include "LibLsp/lsp/lsp_diagnostic.h" +#include "LibLsp/lsp/workspace/execute_command.h" +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" +#include "LibLsp/lsp/lsCodeAction.h" +namespace JDT +{ + namespace CodeActionKind { + + + /** + * Base kind for quickfix actions: 'quickfix' + */ + extern const char* QuickFix; + + /** + * Base kind for refactoring actions: 'refactor' + */ + extern const char* Refactor; + + /** + * Base kind for refactoring extraction actions: 'refactor.extract' + * + * Example extract actions: + * + * - Extract method - Extract function - Extract variable - Extract interface + * from class - ... + */ + extern const char* RefactorExtract; + + /** + * Base kind for refactoring inline actions: 'refactor.inline' + * + * Example inline actions: + * + * - Inline function - Inline variable - Inline constant - ... + */ + extern const char* RefactorInline; + + /** + * Base kind for refactoring rewrite actions: 'refactor.rewrite' + * + * Example rewrite actions: + * + * - Convert JavaScript function to class - Add or remove parameter - + * Encapsulate field - Make method static - Move method to base class - ... + */ + extern const char* RefactorRewrite; + + /** + * Base kind for source actions: `source` + * + * Source code actions apply to the entire file. + */ + extern const char* Source ; + + /** + * Base kind for an organize imports source action: `source.organizeImports` + */ + extern const char* SourceOrganizeImports; + + extern const char* COMMAND_ID_APPLY_EDIT; + }; + + +} +struct lsCodeActionContext { + // An array of diagnostics. + std::vector<lsDiagnostic> diagnostics; + /** + * Requested kind of actions to return. + * + * Actions not of this kind are filtered out by the client before being shown. So servers + * can omit computing them. + * + * See {@link CodeActionKind} for allowed values. + */ + boost::optional<std::vector<std::string>> only; + + MAKE_SWAP_METHOD(lsCodeActionContext, + diagnostics, only); +}; +MAKE_REFLECT_STRUCT(lsCodeActionContext, + diagnostics, only); + + +// Params for the CodeActionRequest +struct lsCodeActionParams { + // The document in which the command was invoked. + lsTextDocumentIdentifier textDocument; + // The range for which the command was invoked. + lsRange range; + // Context carrying additional information. + lsCodeActionContext context; + + MAKE_SWAP_METHOD(lsCodeActionParams, + textDocument, + range, + context); +}; +MAKE_REFLECT_STRUCT(lsCodeActionParams, + textDocument, + range, + context); + + + + + + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/Directory.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/Directory.h new file mode 100644 index 0000000000..93f2c0807d --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/Directory.h @@ -0,0 +1,13 @@ +#pragma once +#include <string> + +struct AbsolutePath; + +struct Directory { + explicit Directory(const AbsolutePath& path); + + bool operator==(const Directory& rhs) const; + bool operator!=(const Directory& rhs) const; + + std::string path; +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/ExecuteCommandParams.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ExecuteCommandParams.h new file mode 100644 index 0000000000..c06eed4b1c --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ExecuteCommandParams.h @@ -0,0 +1,20 @@ +#pragma once + +#include "lsAny.h" +struct ExecuteCommandParams { + /** + * The identifier of the actual command handler. + */ + + std::string command; + + /** + * Arguments that the command should be invoked with. + * The arguments are typically specified when a command is returned from the server to the client. + * Example requests that return a command are textDocument/codeAction or textDocument/codeLens. + */ + boost::optional<std::vector<lsp::Any>> arguments; + + MAKE_SWAP_METHOD(ExecuteCommandParams, command, arguments); +}; +MAKE_REFLECT_STRUCT(ExecuteCommandParams,command,arguments) diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/IProgressMonitor.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/IProgressMonitor.h new file mode 100644 index 0000000000..bf1337e44f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/IProgressMonitor.h @@ -0,0 +1,145 @@ +#pragma once + + +#include <string> +namespace lsp { +/** + * The <code>IProgressMonitor</code> interface is implemented + * by objects that monitor the progress of an activity; the methods + * in this interface are invoked by code that performs the activity. + * <p> + * All activity is broken down into a linear sequence of tasks against + * which progress is reported. When a task begins, a <code>beginTask(const wstring&, int) + * </code> notification is reported, followed by any number and mixture of + * progress reports (<code>worked()</code>) and subtask notifications + * (<code>subTask(const wstring&)</code>). When the task is eventually completed, a + * <code>done()</code> notification is reported. After the <code>done()</code> + * notification, the progress monitor cannot be reused; i.e., <code> + * beginTask(const wstring&, int)</code> cannot be called again after the call to + * <code>done()</code>. + * </p> + * <p> + * A request to cancel an operation can be signaled using the + * <code>setCanceled</code> method. Operations taking a progress + * monitor are expected to poll the monitor (using <code>isCanceled</code>) + * periodically and abort at their earliest convenience. Operation can however + * choose to ignore cancelation requests. + * </p> + * <p> + * Since notification is synchronous with the activity itself, the listener should + * provide a fast and robust implementation. If the handling of notifications would + * involve blocking operations, or operations which might throw uncaught exceptions, + * the notifications should be queued, and the actual processing deferred (or perhaps + * delegated to a separate thread). + * </p> + * <p> + * Clients may implement this interface. + * </p> + */ + class IProgressMonitor { + public: + virtual ~IProgressMonitor() + { + } + + /** Constant indicating an unknown amount of work. + */ + + const static int UNKNOWN = -1; + + /** + * Notifies that the main task is beginning. This must only be called once + * on a given progress monitor instance. + * + * @param name the name (or description) of the main task + * @param totalWork the total number of work units into which + * the main task is been subdivided. If the value is <code>UNKNOWN</code> + * the implemenation is free to indicate progress in a way which + * doesn't require the total number of work units in advance. + */ + virtual void beginTask(void* , int totalWork) + { + + }; + /** + * Notifies that the work is done; that is, either the main task is completed + * or the user canceled it. This method may be called more than once + * (implementations should be prepared to handle this case). + */ + + virtual void endTask(void*, int totalWork) + { + + } + + virtual void done(void*) = 0; + + /** + * Internal method to handle scaling correctly. This method + * must not be called by a client. Clients should + * always use the method </code>worked(int)</code>. + */ + virtual void internalWorked(double work) + { + + } + /** + * Returns whether cancelation of current operation has been requested. + * Long-running operations should poll to see if cancelation + * has been requested. + * + * @return <code>true</code> if cancellation has been requested, + * and <code>false</code> otherwise + * @see #setCanceled + */ + virtual bool isCanceled() = 0; + /** + * Sets the cancel state to the given value. + * + * @param value <code>true</code> indicates that cancelation has + * been requested (but not necessarily acknowledged); + * <code>false</code> clears this flag + * + * @see #isCanceled + */ + virtual void setCanceled(bool value) = 0; + /** + * Sets the task name to the given value. This method is used to + * restore the task label after a nested operation was executed. + * Normally there is no need for clients to call this method. + * + * @param name the name (or description) of the main task + * @see #beginTask(java.lang.const wstring&, int) + */ + virtual void setTaskName(void*) + { + + }; + /** + * Notifies that a subtask of the main task is beginning. + * Subtasks are optional; the main task might not have subtasks. + * + * @param name the name (or description) of the subtask + */ + virtual void subTask(void* ) + { + + } + /** + * Notifies that a given number of work unit of the main task + * has been completed. Note that this amount represents an + * installment, as opposed to a cumulative amount of work done + * to date. + * + * @param work the number of work units just completed + */ + virtual void worked(int work) + { + + }; + + virtual void catch_exception(void*) = 0; + }; +} + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/Markup/Markup.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/Markup/Markup.h new file mode 100644 index 0000000000..92d773db0c --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/Markup/Markup.h @@ -0,0 +1,119 @@ +#pragma once +#include <cctype> +#include <clocale> +#include <cstddef> +#include <memory> +#include <string> +#include <vector> +#include <sstream> + +#include "string_ref.h" + +namespace lsp +{ + +/// Holds text and knows how to lay it out. Multiple blocks can be grouped to +/// form a document. Blocks include their own trailing newlines, std::string_ref +/// should trim them if need be. +class Block { +public: + virtual void renderMarkdown(std::ostringstream &OS) const = 0; + virtual void renderPlainText(std::ostringstream &OS) const = 0; + virtual std::unique_ptr<Block> clone() const = 0; + std::string_ref asMarkdown() const; + std::string_ref asPlainText() const; + + virtual bool isRuler() const { return false; } + virtual ~Block() = default; +}; + +/// Represents parts of the markup that can contain strings, like inline code, +/// code block or plain text. +/// One must introduce different paragraphs to create separate blocks. +class Paragraph : public Block { +public: + void renderMarkdown(std::ostringstream &OS) const override; + void renderPlainText(std::ostringstream &OS) const override; + std::unique_ptr<Block> clone() const override; + + /// Append plain text to the end of the string. + Paragraph &appendText(const std::string_ref& Text); + + /// Append inline code, this translates to the ` block in markdown. + /// \p Preserve indicates the code span must be apparent even in plaintext. + Paragraph &appendCode(const std::string_ref& Code, bool Preserve = false); + + /// Ensure there is space between the surrounding chunks. + /// Has no effect at the beginning or end of a paragraph. + Paragraph &appendSpace(); + +private: + struct Chunk { + enum { + PlainText, + InlineCode, + } Kind = PlainText; + // Preserve chunk markers in plaintext. + bool Preserve = false; + std::string_ref Contents; + // Whether this chunk should be surrounded by whitespace. + // Consecutive SpaceAfter and SpaceBefore will be collapsed into one space. + // Code spans don't usually set this: their spaces belong "inside" the span. + bool SpaceBefore = false; + bool SpaceAfter = false; + }; + std::vector<Chunk> Chunks; +}; + +/// Represents a sequence of one or more documents. Knows how to print them in a +/// list like format, e.g. by prepending with "- " and indentation. +class BulletList : public Block { +public: + void renderMarkdown(std::ostringstream &OS) const override; + void renderPlainText(std::ostringstream &OS) const override; + std::unique_ptr<Block> clone() const override; + + class Document &addItem(); + +private: + std::vector<class Document> Items; +}; + +/// A format-agnostic representation for structured text. Allows rendering into +/// markdown and plaintext. +class Document { +public: + Document() = default; + Document(const Document &Other) { *this = Other; } + Document &operator=(const Document &); + Document(Document &&) = default; + Document &operator=(Document &&) = default; + + void append(Document Other); + + /// Adds a semantical block that will be separate from others. + Paragraph &addParagraph(); + /// Inserts a horizontal separator to the document. + void addRuler(); + /// Adds a block of code. This translates to a ``` block in markdown. In plain + /// text representation, the code block will be surrounded by newlines. + void addCodeBlock( std::string_ref Code, std::string_ref Language = "cpp"); + /// Heading is a special type of paragraph that will be prepended with \p + /// Level many '#'s in markdown. + Paragraph &addHeading(size_t Level); + + BulletList &addBulletList(); + + /// Doesn't contain any trailing newlines. + /// We try to make the markdown human-readable, e.g. avoid extra escaping. + /// At least one client (coc.nvim) displays the markdown verbatim! + std::string_ref asMarkdown() const; + /// Doesn't contain any trailing newlines. + std::string_ref asPlainText() const; + +private: + std::vector<std::unique_ptr<Block>> Children; +}; + + +} diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/Markup/string_ref.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/Markup/string_ref.h new file mode 100644 index 0000000000..220817a1a2 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/Markup/string_ref.h @@ -0,0 +1,1061 @@ + +#pragma once +#include <algorithm> +#include <string> +#include <vector> +#include <stdarg.h> +#include<functional> + +#ifndef _WIN32 +#include <cstring> +#endif +namespace std +{ + + /** + * An extension of STL's string providing additional functionality that is often availiable in + * higher-level languages such as Python. + */ + class string_ref : public string + { + public: + + //static unsigned GetAutoSenseRadix(string_ref& Str) { + // if (Str.empty()) + // return 10; + + // if (Str.start_with("0x") || Str.start_with("0X")) { + // Str = Str.substr(2); + // return 16; + // } + + // if (Str.start_with("0b") || Str.start_with("0B")) { + // Str = Str.substr(2); + // return 2; + // } + + // if (Str.start_with("0o")) { + // Str = Str.substr(2); + // return 8; + // } + + // if (Str[0] == '0' && Str.size() > 1 && std::isdigit(Str[1])) { + // Str = Str.substr(1); + // return 8; + // } + + // return 10; + //} + + //static bool consumeUnsignedInteger(string_ref& Str, unsigned Radix, + // unsigned long long& Result) { + // // Autosense radix if not specified. + // if (Radix == 0) + // Radix = GetAutoSenseRadix(Str); + + // // Empty strings (after the radix autosense) are invalid. + // if (Str.empty()) return true; + + // // Parse all the bytes of the string given this radix. Watch for overflow. + // string_ref Str2 = Str; + // Result = 0; + // while (!Str2.empty()) { + // unsigned CharVal; + // if (Str2[0] >= '0' && Str2[0] <= '9') + // CharVal = Str2[0] - '0'; + // else if (Str2[0] >= 'a' && Str2[0] <= 'z') + // CharVal = Str2[0] - 'a' + 10; + // else if (Str2[0] >= 'A' && Str2[0] <= 'Z') + // CharVal = Str2[0] - 'A' + 10; + // else + // break; + + // // If the parsed value is larger than the integer radix, we cannot + // // consume any more characters. + // if (CharVal >= Radix) + // break; + + // // Add in this character. + // unsigned long long PrevResult = Result; + // Result = Result * Radix + CharVal; + + // // Check for overflow by shifting back and seeing if bits were lost. + // if (Result / Radix < PrevResult) + // return true; + + // Str2 = Str2.substr(1); + // } + + // // We consider the operation a failure if no characters were consumed + // // successfully. + // if (Str.size() == Str2.size()) + // return true; + + // Str = Str2; + // return false; + //} + + //static bool consumeSignedInteger(string_ref& Str, unsigned Radix, + // long long& Result) { + // unsigned long long ULLVal; + + // // Handle positive strings first. + // if (Str.empty() || Str.front() != '-') { + // if (consumeUnsignedInteger(Str, Radix, ULLVal) || + // // Check for value so large it overflows a signed value. + // (long long)ULLVal < 0) + // return true; + // Result = ULLVal; + // return false; + // } + + // // Get the positive part of the value. + // string_ref Str2 = Str.drop_front(1); + // if (consumeUnsignedInteger(Str2, Radix, ULLVal) || + // // Reject values so large they'd overflow as negative signed, but allow + // // "-0". This negates the unsigned so that the negative isn't undefined + // // on signed overflow. + // (long long)-ULLVal > 0) + // return true; + + // Str = Str2; + // Result = -ULLVal; + // return false; + //} + + ///// GetAsUnsignedInteger - Workhorse method that converts a integer character + ///// sequence of radix up to 36 to an unsigned long long value. + //static bool getAsUnsignedInteger(string_ref Str, unsigned Radix, + // unsigned long long& Result) { + // if (consumeUnsignedInteger(Str, Radix, Result)) + // return true; + + // // For getAsUnsignedInteger, we require the whole string to be consumed or + // // else we consider it a failure. + // return !Str.empty(); + //} + + //static bool getAsSignedInteger(string_ref Str, unsigned Radix, + // long long& Result) { + // if (consumeSignedInteger(Str, Radix, Result)) + // return true; + + // // For getAsSignedInteger, we require the whole string to be consumed or else + // // we consider it a failure. + // return !Str.empty(); + //} + + + ///// Parse the current string as an integer of the specified radix. If + ///// \p Radix is specified as zero, this does radix autosensing using + ///// extended C rules: 0 is octal, 0x is hex, 0b is binary. + ///// + ///// If the string is invalid or if only a subset of the string is valid, + ///// this returns true to signify the error. The string is considered + ///// erroneous if empty or if it overflows T. + //template <typename T> + //std::enable_if_t<std::numeric_limits<T>::is_signed, bool> + // getAsInteger(unsigned Radix, T& Result) const { + // long long LLVal; + // if (getAsSignedInteger(*this, Radix, LLVal) || + // static_cast<T>(LLVal) != LLVal) + // return true; + // Result = LLVal; + // return false; + //} + + //template <typename T> + //std::enable_if_t<!std::numeric_limits<T>::is_signed, bool> + // getAsInteger(unsigned Radix, T& Result) const { + // unsigned long long ULLVal; + // // The additional cast to unsigned long long is required to avoid the + // // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type + // // 'unsigned __int64' when instantiating getAsInteger with T = bool. + // if (getAsUnsignedInteger(*this, Radix, ULLVal) || + // static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal) + // return true; + // Result = ULLVal; + // return false; + //} + + + + /**` + * Default constructor + * + * Constructs an empty string_ref ("") + */ + string_ref() : string() { } + + /** + * Duplicate the STL string copy constructor + * + * @param[in] s The string to copy + * @param[in] pos The starting position in the string to copy from + * @param[in] n The number of characters to copy + */ + string_ref(const string &s, size_type pos = 0, size_type n = npos) : string(s, pos, npos) { } + + /** + * Construct an string_ref from a null-terminated character array + * + * @param[in] s The character array to copy into the new string + */ + string_ref(const value_type *s) : string(s) { } + + /** + * Construct an string_ref from a character array and a length + * + * @param[in] s The character array to copy into the new string + * @param[in] n The number of characters to copy + */ + string_ref(const value_type *s, size_type n) : string(s, n) { } + + /** + * Create an string_ref with @p n copies of @p c + * + * @param[in] n The number of copies + * @param[in] c The character to copy @p n times + */ + string_ref(size_type n, value_type c) : string(n, c) { } + + /** + * Create a string from a range + * + * @param[in] first The first element to copy in + * @param[in] last The last element to copy in + */ + template <class InputIterator> + string_ref(InputIterator first, InputIterator last) : string(first, last) { } + + /** + * The destructor + */ + ~string_ref() { } + + /** + * Split a string by whitespace + * + * @return A vector of strings, each of which is a substring of the string + */ + vector<string_ref> split(size_type limit = npos) const + { + vector<string_ref> v; + + const_iterator + i = begin(), + last = i; + for (; i != end(); i++) + { + if (*i == ' ' || *i == '\n' || *i == '\t' || *i == '\r') + { + if (i + 1 != end() && (i[1] == ' ' || i[1] == '\n' || i[1] == '\t' || i[1] == '\r')) + continue; + v.push_back(string_ref(last, i)); + last = i + 1; + if (v.size() >= limit - 1) + { + v.push_back(string_ref(last, end())); + return v; + } + } + } + + if (last != i) + v.push_back(string_ref(last, i)); + + return v; + } + + /** + * Split a string by a character + * + * Returns a vector of ext_strings, each of which is a substring of the string formed by splitting + * it on boundaries formed by the character @p separator. If @p limit is set, the returned vector + * will contain a maximum of @p limit elements with the last element containing the rest of + * the string. + * + * If @p separator is not found in the string, a single element will be returned in the vector + * containing the entire string. + * + * The separators are removed from the output + * + * @param[in] separator The character separator to split the string on + * @param[in] limit The maximum number of output elements + * @return A vector of strings, each of which is a substring of the string + * + * @section split_ex Example + * @code + * std::string_ref s("This|is|a|test."); + * std::vector<std::string_ref> v = s.split('|'); + * std::copy(v.begin(), v.end(), std::ostream_iterator<std::string_ref>(std::cout, "\n")); + * + * This + * is + * a + * test. + * @endcode + */ + vector<string_ref> split(value_type separator, size_type limit = npos) const + { + vector<string_ref> v; + + const_iterator + i = begin(), + last = i; + for (; i != end(); i++) + { + if (*i == separator) + { + v.push_back(string_ref(last, i)); + last = i + 1; + if (v.size() >= limit - 1) + { + v.push_back(string_ref(last, end())); + return v; + } + } + } + + if (last != i) + v.push_back(string_ref(last, i)); + + return v; + } + + /** + * Split a string by another string + * + * Returns a vector of ext_strings, each of which is a substring of the string formed by + * splitting it on boundaries formed by the string @p separator. If @p limit is set, the + * returned vector will contain a maximum of @p limit elements with the last element + * containing the rest of the string. + * + * If @p separator is not found in the string, a single element will be returned in the + * vector containing the entire string. + * + * The separators are removed from the output + * + * @param[in] separator The string separator to split the string on + * @param[in] limit The maximum number of output elements + * @return A vector of strings, each of which is a substring of the string + * + * @ref split_ex + */ + vector<string_ref> split(const string &separator, size_type limit = npos) const + { + vector<string_ref> v; + + const_iterator + i = begin(), + last = i; + for (; i != end(); i++) + { + if (string(i, i + separator.length()) == separator) + { + v.push_back(string_ref(last, i)); + last = i + separator.length(); + + if (v.size() >= limit - 1) + { + v.push_back(string_ref(last, end())); + return v; + } + } + } + + if (last != i) + v.push_back(string_ref(last, i)); + + return v; + } + + /** + * Convert a string into an integer + * + * Convert the initial portion of a string into a signed integer. Once a non-numeric + * character is reached, the remainder of @p string is ignored and the integer that was + * read returned. + * + * @param s The string to convert + * @return The integer converted from @p string + */ + static long int integer(const string &s) + { + long int retval = 0; + bool neg = false; + + for (const_iterator i = s.begin(); i != s.end(); i++) + { + if (i == s.begin()) + { + if (*i == '-') + { + neg = true; + continue; + } + else if (*i == '+') + continue; + } + if (*i >= '0' && *i <= '9') + { + retval *= 10; + retval += *i - '0'; + } + else + break; + } + + if (neg) + retval *= -1; + + return retval; + } + + /** + * Convert the string to an integer + * + * Convert the initial portion of the string into a signed integer. Once a non-numeric + * character is reached, the remainder of the string is ignored and the integer that had + * been read thus far is returned. + * + * @return The integer converted from the string + */ + long int integer() const + { + return integer(*this); + } + + /** + * Split a string into chunks of size @p chunklen. Returns a vector of strings. + * + * Splits a string into chunks of the given size. The final chunk may not fill its + * entire allocated number of characters. + * + * @param[in] chunklen The number of characters per chunk + * @return A vector of strings, each of length <= chunklen + * + * @section chunk_split-ex Example + * @code + * std::string_ref s("abcdefghijk"); + * std::vector<std::string_ref> v = s.chunk_split(3); + * std::copy(v.begin(), v.end(), ostream_iterator<std::string_ref>(cout, " ")); + * + * abc def ghi jk + * @endcode + */ + vector<string_ref> chunk_split(size_type chunklen) const + { + vector<string_ref> retval; + retval.reserve(size() / chunklen + 1); + + size_type count = 0; + const_iterator + i = begin(), + last = i; + for (; i != end(); i++, count++) + { + if (count == chunklen) + { + count = 0; + retval.push_back(string_ref(last, i)); + last = i; + } + } + + if (last != i) + retval.push_back(string_ref(last, i)); + + return retval; + } + + /** + * Join a sequence of strings by some glue to create a new string + * + * Glue is not added to the end of the string. + * + * @pre [first, last) is a valid range + * @pre InputIterator is a model of STL's Input Iterator + * @pre InputIterator must point to a string type (std::string, std::string_ref, char *) + * + * @param[in] glue The glue to join strings with + * @param[in] first The beginning of the range to join + * @param[in] last The end of the range to join + * @return A string constructed of each element of the range connected together with @p glue + * + * @section join_ex Example + * @code + * std::vector<std::string_ref> v; + * v.push_back("This"); + * v.push_back("is"); + * v.push_back("a"); + * v.push_back("test."); + * std::cout << std::string_ref::join("|", v.begin(), v.end()) << std::endl; + * + * This|is|a|test. + * @endcode + */ + template <class InputIterator> + static string_ref join(const string &glue, InputIterator first, InputIterator last) + { + string_ref retval; + + for (; first != last; ++first) + { + retval.append(*first); + retval.append(glue); + } + retval.erase(retval.length() - glue.length()); + + return retval; + } + + /** + * Join a sequence of strings by some glue to create a new string + * + * @copydoc join + * @ref join_ex + */ + template <class InputIterator> + static string_ref join(value_type glue, InputIterator first, InputIterator last) + { + string_ref retval; + + for (; first != last; ++first) + { + retval.append(*first); + retval.append(1, glue); + } + retval.erase(retval.length() - 1); + + return retval; + } + + /** + * Search for any instances of @p needle and replace them with @p s + * + * @param[in] needle The string to replace + * @param[in] s The replacement string + * @return *this + * @post All instances of @p needle in the string are replaced with @p s + * + * @section replace-ex Example + * @code + * std::string_ref s("This is a test."); + * s.replace("is", "ere"); + * std::cout << s << std::endl; + * + * There ere a test. + * @endcode + */ + string_ref &replace(const string &needle, const string &s) + { + size_type + lastpos = 0, + thispos; + + while ((thispos = find(needle, lastpos)) != npos) + { + string::replace(thispos, needle.length(), s); + lastpos = thispos + 1; + } + return *this; + } + string_ref &replace_first(const string &needle, const string &s) + { + size_type + lastpos = 0, + thispos; + + if ((thispos = find(needle, lastpos)) != npos) + { + string::replace(thispos, needle.length(), s); + lastpos = thispos + 1; + } + return *this; + } + /** + * Search of any instances of @p needle and replace them with @p c + * + * @param[in] needle The character to replace + * @param[in] c The replacement character + * @return *this + * @post All instances of @p needle in the string are replaced with @p c + * + * @ref replace-ex + */ + string_ref &replace(value_type needle, value_type c) + { + for (iterator i = begin(); i != end(); i++) + if (*i == needle) + *i = c; + + return *this; + } + + /** + * Repeat a string @p n times + * + * @param[in] n The number of times to repeat the string + * @return string_ref containing @p n copies of the string + * + * @section repeat-ex Example + * @code + * std::string_ref s("123"); + * s = s * 3; + * std::cout << s << std::endl; + * + * 123123123 + * @endcode + */ + string_ref operator*(size_type n) + { + string_ref retval; + for (size_type i = 0; i < n; i++) + retval.append(*this); + + return retval; + } + + /** + * Convert the string to lowercase + * + * @return *this + * @post The string is converted to lowercase + */ + string_ref &tolower() + { + for (iterator i = begin(); i != end(); i++) + if (*i >= 'A' && *i <= 'Z') + *i = (*i) + ('a' - 'A'); + return *this; + } + + /** + * Convert the string to uppercase + * + * @return *this + * @post The string is converted to uppercase + */ + string_ref &toupper() + { + for (iterator i = begin(); i != end(); i++) + if (*i >= 'a' && *i <= 'z') + *i = (*i) - ('a' - 'A'); + return *this; + } + + /** + * Count the occurances of @p str in the string. + * + * @return The count of substrings @p str in the string + */ + size_type count(const string &str) const + { + size_type + count = 0, + last = 0, + cur = 0; + + while ((cur = find(str, last + 1)) != npos) + { + count++; + last = cur; + } + + return count; + } + + /** + * Determine if the string is alphanumeric + * + * @return true if the string contains only characters between a-z, A-Z and 0-9 and + * contains at least one character, else false + */ + bool is_alnum() const + { + if (length() == 0) + return false; + + for (const_iterator i = begin(); i != end(); i++) + { + if (*i < 'A' || *i > 'Z') + if (*i < '0' || *i > '9') + if (*i < 'a' || *i > 'z') + return false; + } + + return true; + } + + /** + * Determine if the string is alphabetic only + * + * @return true of the string contains only characters between a-z and A-Z and contains at + * least one character, else false + */ + bool is_alpha() const + { + if (length() == 0) + return false; + + for (const_iterator i = begin(); i != end(); i++) + if (*i < 'A' || (*i > 'Z' && (*i < 'a' || *i > 'z'))) + return false; + + return true; + } + + /** + * Determine if the string is numeric only + * + * @return true if the string contains only characters between 0-9 and contains at least + * one character, else false + */ + bool is_numeric() const + { + if (length() == 0) + return false; + + for (const_iterator i = begin(); i != end(); i++) + if (*i < '0' || *i > '9') + return false; + + return true; + } + + /** + * Determine if a string is all lower case + * + * @return true if there is at least one character, and all characters are lowercase + * letters, else false + */ + bool is_lower() const + { + if (length() == 0) + return false; + + for (const_iterator i = begin(); i != end(); i++) + if (*i < 'a' || *i < 'z') + return false; + + return true; + } + + /** + * Determine if a string is all upper case + * + * @return true if there is at least one character, and all characters are uppercase + * letters, else false + */ + bool is_upper() const + { + if (length() == 0) + return false; + + for (const_iterator i = begin(); i != end(); i++) + if (*i < 'A' || *i > 'Z') + return false; + + return true; + } + + /** + * Swap the case of a string + * + * @post Converts all uppercase to lowercase, and all lowercase to uppercase in the string + * @return *this + */ + string_ref &swapcase() + { + for (iterator i = begin(); i != end(); i++) + if (*i >= 'A' && *i <= 'Z') + *i += ('a' - 'A'); + else if (*i >= 'a' && *i <= 'z') + *i -= ('a' - 'A'); + + return *this; + } + + /******************************************************************************* + Function: std::string_ref::start_with + Access: public + Qualifier: const + Parameter: const string & str + Returns: bool + + Purpose: is the string start with str + *******************************************************************************/ + bool start_with(const string& str) const + { + return ( this->find(str) == 0 ); + } + + /// Return a string_ref equal to 'this' but with only the last \p N + /// elements remaining. If \p N is greater than the length of the + /// string, the entire string is returned. + + string_ref take_back(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_front(size() - N); + } + /// Return a string_ref equal to 'this' but with the first \p N elements + /// dropped. + + string_ref drop_front(size_t N = 1) const { + //assert(size() >= N && "Dropping more elements than exist"); + return substr(N); + } + + + + /// Return a string_ref equal to 'this' but with the last \p N elements + /// dropped. + + string_ref drop_back(size_t N = 1) const { + + return substr(0, size() - N); + } + + /// Return a string_ref equal to 'this', but with all characters satisfying + /// the given predicate dropped from the beginning of the string. + + string_ref drop_while(std::function<bool(char)> F) const { + return substr(std::find_if_not(begin(),end(),F)-begin()); + } + + /// Return a string_ref equal to 'this', but with all characters not + /// satisfying the given predicate dropped from the beginning of the string. + + string_ref drop_until(std::function<bool(char)> F) const { + return substr(std::find_if(begin(), end(), F) - begin()); + } + + /// Returns true if this string_ref has the given prefix and removes that + /// prefix. + bool consume_front(string_ref Prefix) { + if (!start_with(Prefix)) + return false; + + *this = drop_front(Prefix.size()); + return true; + } + + /// Returns true if this string_ref has the given suffix and removes that + /// suffix. + bool consume_back(string_ref Suffix) { + if (!end_with(Suffix)) + return false; + + *this = drop_back(Suffix.size()); + return true; + } + + /******************************************************************************* + Function: std::string_ref::end_with + Access: public + Qualifier: const + Parameter: const string & str + Returns: bool + + Purpose: is the string end with str + *******************************************************************************/ + bool end_with(const string& str) const + { + if (str.length() > this->length()) + { + return false; + } + size_type off = this->length() - str.length(); + return ( find(str, off) == off); + } + + /******************************************************************************* + Function: hl_lib::string_ref::format + Access: public + Qualifier: + Parameter: const char * format_string + Parameter: ... + Returns: string_ref& + + Purpose: format the string + *******************************************************************************/ + string_ref& format(const char* format_string, ...) + { + if (format_string == 0) + { + return *this; + } + + va_list argList; + va_start( argList, format_string ); + +#ifdef _WIN32 + int len = _vscprintf( format_string, argList ); + char* pbuf = new char[len + 1]; + if (pbuf != 0) + { + vsprintf_s( pbuf, len + 1, format_string, argList ); + *this = pbuf; + delete[] pbuf; + } +#else + const int INLINE_FORMAT_BUFFER_LEN =2048; + char* buf = new char[INLINE_FORMAT_BUFFER_LEN + 1]; + if (buf != 0) + { + int len =vsnprintf(buf,INLINE_FORMAT_BUFFER_LEN, format_string, argList); + assign(buf,buf+len); + delete[] buf; + } +#endif + va_end( argList ); + return *this; + } + + /******************************************************************************* + Function: hl_lib::string_ref::trim_left + Access: public + Qualifier: + Parameter: value_type ch + Returns: string_ref& + + Purpose: delete all char which is ch at the left of the string + *******************************************************************************/ + string_ref& trim_left(value_type ch = ' ') + { + size_type off = this->find_first_not_of(ch); + if (off != string::npos) + { + this->erase(0, off); + } + return *this; + } + + /******************************************************************************* + Function: hl_lib::string_ref::trim_right + Access: public + Qualifier: + Parameter: value_type ch + Returns: string_ref& + + Purpose: delete all char which is ch at the right of the string + *******************************************************************************/ + string_ref& trim_right(value_type ch = ' ') + { + size_type off = this->find_last_not_of(ch); + if (off == string::npos) + { + off = 0; + } + else + { + off++; + } + this->erase(off, length() - off); + return *this; + } + + /******************************************************************************* + Function: hl_lib::string_ref::trim + Access: public + Qualifier: + Parameter: value_type ch + Returns: string_ref& + + Purpose: delete all char which is ch at the left and right of the string + *******************************************************************************/ + string_ref& trim(value_type ch = ' ') + { + trim_left(ch); + trim_right(ch); + return *this; + } + + /******************************************************************************* + Function: hl_lib::string_ref::float_num + Access: public static + Qualifier: + Parameter: const string & str + Returns: double + + Purpose: parse str to a float number + *******************************************************************************/ + static double float_num(const string& str) + { + return atof(str.c_str()); + } + + /******************************************************************************* + Function: hl_lib::string_ref::float_num + Access: public static + Qualifier: + Returns: double + + Purpose: parse this to a float number + *******************************************************************************/ + double float_num() const + { + return float_num(*this); + } + + /******************************************************************************* + Function: hl_lib::string_ref::compare_nocase + Access: public + Qualifier: const + Parameter: const string & str + Returns: int + + Purpose: compare string no case + *******************************************************************************/ + int compare_nocase(const string& str) const + { +#ifdef _WIN32 + return _stricmp(this->c_str(), str.c_str()); +#else + return strcasecmp(this->c_str(), str.c_str()); +#endif + } + + /******************************************************************************* + Function: hl_lib::string_ref::compare_nocase + Access: public + Qualifier: const + Parameter: size_type index + Parameter: size_type length + Parameter: const string & str + Returns: int + + Purpose: compare substring no case + *******************************************************************************/ + int compare_nocase( size_type index, size_type length, const string &str ) const + { + string_ref temp = this->substr(index, length); + return temp.compare_nocase(str); + } + + /******************************************************************************* + Function: hl_lib::string_ref::compare_nocase + Access: public + Qualifier: const + Parameter: size_type index + Parameter: size_type length + Parameter: const string & str + Parameter: size_type index2 + Parameter: size_type length2 + Returns: int + + Purpose: compare two substring no case + *******************************************************************************/ + int compare_nocase( size_type index, size_type length, const string &str, size_type index2, size_type length2) const + { + string_ref temp1 = this->substr(index, length); + string_ref temp2 = str.substr(index2, length2); + return temp1.compare_nocase(temp2); + } + + }; + +} + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/ParentProcessWatcher.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ParentProcessWatcher.h new file mode 100644 index 0000000000..fa84e4109a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ParentProcessWatcher.h @@ -0,0 +1,17 @@ +#pragma once + +#include "LibLsp/JsonRpc/MessageIssue.h" +#include <memory> + +class ParentProcessWatcher +{ +public: + struct ParentProcessWatcherData; + + ParentProcessWatcher(lsp::Log& log, int pid, const std::function<void()>&& callback, uint32_t poll_delay_secs = 10); + + ~ParentProcessWatcher(); + + std::shared_ptr<ParentProcessWatcherData> d_ptr; +}; + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/ProcessIoService.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ProcessIoService.h new file mode 100644 index 0000000000..1389a1d5b7 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ProcessIoService.h @@ -0,0 +1,48 @@ +#pragma once +#include <boost/asio.hpp> +#include <iostream> + +namespace lsp +{ + class ProcessIoService + { + public: + using IOService = boost::asio::io_service; + using Work = boost::asio::io_service::work; + using WorkPtr = std::unique_ptr<Work>; + + ProcessIoService() { + + work_ = std::unique_ptr<Work>(new Work(ioService_)); + auto temp_thread_ = new std::thread([this] + { + ioService_.run(); + }); + thread_ = std::unique_ptr<std::thread>(temp_thread_); + } + + ProcessIoService(const ProcessIoService&) = delete; + ProcessIoService& operator=(const ProcessIoService&) = delete; + + boost::asio::io_service& getIOService() + { + return ioService_; + } + + void stop() + { + + work_.reset(); + + thread_->join(); + + } + + private: + IOService ioService_; + WorkPtr work_; + std::unique_ptr<std::thread> thread_; + + }; + +} diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/ProtocolJsonHandler.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ProtocolJsonHandler.h new file mode 100644 index 0000000000..b563f810d2 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ProtocolJsonHandler.h @@ -0,0 +1,11 @@ +#pragma once + +#include "LibLsp/JsonRpc/MessageJsonHandler.h" +namespace lsp { + class ProtocolJsonHandler : public MessageJsonHandler + { + public: + ProtocolJsonHandler(); + }; + +} diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/ResourceOperation.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ResourceOperation.h new file mode 100644 index 0000000000..caf2ea5d5f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/ResourceOperation.h @@ -0,0 +1,121 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include <vector> +#include "lsDocumentUri.h" +#include "LibLsp/lsp/lsAny.h" +#include "LibLsp/lsp/lsTextEdit.h" +struct ResourceOperation { + std::string kind; + virtual ~ResourceOperation() = default; + + MAKE_SWAP_METHOD(ResourceOperation, kind); +}; +MAKE_REFLECT_STRUCT(ResourceOperation, kind); +extern void Reflect(Writer& visitor, ResourceOperation* value); +struct CreateFileOptions{ + + /** + * Overwrite existing file. Overwrite wins over `ignoreIfExists` + */ + boost::optional<bool> overwrite = false; + + /** + * Ignore if exists. + */ + boost::optional< bool> ignoreIfExists =false; + + MAKE_SWAP_METHOD(CreateFileOptions, overwrite, ignoreIfExists) +}; +MAKE_REFLECT_STRUCT(CreateFileOptions, overwrite, ignoreIfExists) +struct lsCreateFile :public ResourceOperation { + + /** + * The resource to create. + */ + lsCreateFile(); + lsDocumentUri uri; + + /** + * Additional options + */ + boost::optional<CreateFileOptions> options; + + + /** + * An optional annotation identifer describing the operation. + * + * @since 3.16.0 + */ + boost::optional<lsChangeAnnotationIdentifier> annotationId; + + MAKE_SWAP_METHOD(lsCreateFile, kind, uri, options, annotationId) +}; +MAKE_REFLECT_STRUCT(lsCreateFile, kind, uri,options, annotationId) + + +struct DeleteFileOptions { + /** + * Delete the content recursively if a folder is denoted. + */ + boost::optional<bool> recursive = false; + + /** + * Ignore the operation if the file doesn't exist. + */ + boost::optional<bool> ignoreIfNotExists = false; + + + MAKE_SWAP_METHOD(DeleteFileOptions, recursive, ignoreIfNotExists); +}; + +MAKE_REFLECT_STRUCT(DeleteFileOptions, recursive, ignoreIfNotExists) + +struct lsDeleteFile :public ResourceOperation { + /** + * The file to delete. + */ + lsDeleteFile(); + lsDocumentUri uri; + + /** + * Delete options. + */ + boost::optional<DeleteFileOptions> options; + + MAKE_SWAP_METHOD(lsDeleteFile, kind, uri, options); +}; +MAKE_REFLECT_STRUCT(lsDeleteFile, kind, uri,options); + +typedef CreateFileOptions RenameFileOptions; +struct lsRenameFile :public ResourceOperation { + /** + * The old (existing) location. + */ + lsRenameFile(); + lsDocumentUri oldUri; + + /** + * The new location. + */ + + lsDocumentUri newUri; + + /** + * Rename options. + */ + boost::optional<RenameFileOptions> options; + + /** + * An optional annotation identifer describing the operation. + * + * @since 3.16.0 + */ + boost::optional<lsChangeAnnotationIdentifier> annotationId; + + MAKE_SWAP_METHOD(lsRenameFile, kind, oldUri, newUri, options, annotationId) +}; +MAKE_REFLECT_STRUCT(lsRenameFile, kind, oldUri, newUri, options, annotationId); + + +extern ResourceOperation* GetResourceOperation(lsp::Any& lspAny);
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/SimpleTimer.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/SimpleTimer.h new file mode 100644 index 0000000000..0a2707979d --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/SimpleTimer.h @@ -0,0 +1,49 @@ +#pragma once +#include <thread> +#include <atomic> +#include <functional> +#include <boost/asio.hpp> + +template<typename Duration = boost::posix_time::milliseconds> +class SimpleTimer +{ +public: + SimpleTimer(unsigned int duration,const std::function<void()>& _call_back) + :is_running_(true), call_back(_call_back), _deadline_timer(_ios, Duration(duration)) + { + _deadline_timer.async_wait([&](const boost::system::error_code& e) + { + if (e.value() == boost::asio::error::operation_aborted) + { + return; + } + if(is_running_.load(std::memory_order_relaxed)) + { + call_back(); + } + + }); + _thread = std::thread([this] { _ios.run(); }); + } + ~SimpleTimer() + { + Stop(); + } + void Stop() + { + is_running_.store(false, std::memory_order_relaxed); + _ios.stop(); + if (_thread.joinable()) + { + _thread.join(); + } + } +private: + std::atomic_bool is_running_; + std::function<void()> call_back; + boost::asio::io_service _ios; + boost::asio::deadline_timer _deadline_timer; + std::thread _thread; + + +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/client/registerCapability.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/client/registerCapability.h new file mode 100644 index 0000000000..fa5d111403 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/client/registerCapability.h @@ -0,0 +1,49 @@ +#pragma once +#include "LibLsp/JsonRpc/message.h" +#include "LibLsp/lsp/lsDocumentUri.h" + +/** + * General parameters to register for a capability. + */ + +struct Registration { + static Registration Create(const std::string& method); + /** + * The id used to register the request. The id can be used to deregister + * the request again. + */ + std::string id; + + /** + * The method / capability to register for. + */ + + std::string method; + + MAKE_SWAP_METHOD(Registration, id, method); +}; + + +MAKE_REFLECT_STRUCT(Registration, id, method); + +/** + * The client/registerCapability request is sent from the server to the client to register + * for a new capability on the client side. Not all clients need to support dynamic + * capability registration. A client opts in via the dynamicRegistration property on the + * specific client capabilities. A client can even provide dynamic registration for + * capability A but not for capability B (see TextDocumentClientCapabilities as an example). + */ +struct RegistrationParams +{ + std::vector<Registration> registrations; + MAKE_SWAP_METHOD(RegistrationParams, registrations); +}; +/** + * The client/registerCapability request is sent from the server to the client + * to register for a new capability on the client side. + * Not all clients need to support dynamic capability registration. + * A client opts in via the ClientCapabilities.dynamicRegistration property + */ +MAKE_REFLECT_STRUCT(RegistrationParams, registrations); + +DEFINE_REQUEST_RESPONSE_TYPE(Req_ClientRegisterCapability, RegistrationParams,JsonNull, "client/registerCapability");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/client/unregisterCapability.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/client/unregisterCapability.h new file mode 100644 index 0000000000..aa51d7efee --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/client/unregisterCapability.h @@ -0,0 +1,41 @@ +#pragma once + +#include "LibLsp/lsp/lsDocumentUri.h" + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +/** + * General parameters to unregister a capability. + */ + +struct Unregistration { + /** + * The id used to unregister the request or notification. Usually an id + * provided during the register request. + */ + + std::string id; + + /** + * The method / capability to unregister for. + */ + + std::string method; + + MAKE_SWAP_METHOD(Unregistration, id, method); +}; +MAKE_REFLECT_STRUCT(Unregistration, id, method); +/** + * The client/unregisterCapability request is sent from the server to the client to unregister + * a previously registered capability. + */ +struct UnregistrationParams +{ + std::vector<Unregistration> unregisterations; + MAKE_SWAP_METHOD(UnregistrationParams, unregisterations); +}; + +MAKE_REFLECT_STRUCT(UnregistrationParams, unregisterations); + +DEFINE_REQUEST_RESPONSE_TYPE(Req_ClientUnregisterCapability, UnregistrationParams,JsonNull, "client/unregisterCapability");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/Move.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/Move.h new file mode 100644 index 0000000000..c0beb625f2 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/Move.h @@ -0,0 +1,14 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "LibLsp/lsp/CodeActionParams.h" +#include "getMoveDestinations.h" +#include "getRefactorEdit.h" + + +DEFINE_REQUEST_RESPONSE_TYPE(java_move, MoveParams, RefactorWorkspaceEdit, "java/move"); + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/OverridableMethod.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/OverridableMethod.h new file mode 100644 index 0000000000..cfb17fdf34 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/OverridableMethod.h @@ -0,0 +1,34 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include <string> +struct OverridableMethod +{ + std::string bindingKey; + std::string name; + std::vector<std::string> parameters; + bool unimplemented = false; + std::string declaringClass; + std::string declaringClassType; + + void swap(OverridableMethod& arg) noexcept + { + bindingKey.swap(arg.bindingKey); + name.swap(arg.name); + parameters.swap(arg.parameters); + declaringClass.swap(arg.declaringClass); + declaringClassType.swap(arg.declaringClassType); + std::swap(unimplemented, arg.unimplemented); + } +}; +MAKE_REFLECT_STRUCT(OverridableMethod, bindingKey, name, parameters, unimplemented, declaringClass, declaringClassType); + +struct OverridableMethodsResponse +{ + std::string type; + std::vector<OverridableMethod> methods; + + MAKE_SWAP_METHOD(OverridableMethodsResponse, type, methods) +}; + +MAKE_REFLECT_STRUCT(OverridableMethodsResponse, type, methods) diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/WorkspaceSymbolParams.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/WorkspaceSymbolParams.h new file mode 100644 index 0000000000..c7faa94d6c --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/WorkspaceSymbolParams.h @@ -0,0 +1,13 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include <string> + + +struct WorkspaceSymbolParams +{ + std::string query; + MAKE_SWAP_METHOD(WorkspaceSymbolParams, query); +}; +MAKE_REFLECT_STRUCT(WorkspaceSymbolParams, query); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/addOverridableMethods.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/addOverridableMethods.h new file mode 100644 index 0000000000..5da14a452a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/addOverridableMethods.h @@ -0,0 +1,19 @@ +#pragma once + +#include "LibLsp/JsonRpc/message.h" +#include "OverridableMethod.h" +#include "LibLsp/lsp/CodeActionParams.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +struct AddOverridableMethodParams { + lsCodeActionParams context; + std::vector<OverridableMethod> overridableMethods; + + MAKE_SWAP_METHOD(AddOverridableMethodParams, context, overridableMethods); +}; + +MAKE_REFLECT_STRUCT(AddOverridableMethodParams, context, overridableMethods); + +DEFINE_REQUEST_RESPONSE_TYPE(java_addOverridableMethods, AddOverridableMethodParams, lsWorkspaceEdit, "java/addOverridableMethods"); + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/buildWorkspace.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/buildWorkspace.h new file mode 100644 index 0000000000..a2c2c062cc --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/buildWorkspace.h @@ -0,0 +1,17 @@ +#pragma once + +#include "WorkspaceSymbolParams.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + + + + + +enum class BuildWorkspaceStatus : uint8_t{ + + FAILED, SUCCEED, WITH_ERROR, CANCELLED, +}; +MAKE_REFLECT_TYPE_PROXY(BuildWorkspaceStatus) + +DEFINE_REQUEST_RESPONSE_TYPE(java_buildWorkspace, bool, BuildWorkspaceStatus, "java/buildWorkspace");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkConstructorsStatus.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkConstructorsStatus.h new file mode 100644 index 0000000000..261a0cc551 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkConstructorsStatus.h @@ -0,0 +1,29 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/lsp/CodeActionParams.h" +#include "checkHashCodeEqualsStatus.h" + +struct LspMethodBinding { + std::string bindingKey; + std::string name; + std::vector< std::string> parameters; + + MAKE_SWAP_METHOD(LspMethodBinding, bindingKey, name, parameters); +}; +MAKE_REFLECT_STRUCT(LspMethodBinding, bindingKey, name, parameters); + + +struct CheckConstructorsResponse { + std::vector<LspMethodBinding> constructors; + std::vector<LspVariableBinding> fields; + MAKE_SWAP_METHOD(CheckConstructorsResponse, constructors, fields) +}; +MAKE_REFLECT_STRUCT(CheckConstructorsResponse, constructors,fields) + +DEFINE_REQUEST_RESPONSE_TYPE(java_checkConstructorsStatus, lsCodeActionParams, CheckConstructorsResponse,"java/checkConstructorsStatus") + + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkDelegateMethodsStatus.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkDelegateMethodsStatus.h new file mode 100644 index 0000000000..729639eafa --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkDelegateMethodsStatus.h @@ -0,0 +1,29 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/CodeActionParams.h" +#include "checkHashCodeEqualsStatus.h" +#include "checkConstructorsStatus.h" + +struct LspDelegateField { + LspVariableBinding field; + std::vector<LspMethodBinding> delegateMethods; + + MAKE_SWAP_METHOD(LspDelegateField, field, delegateMethods); +}; +MAKE_REFLECT_STRUCT(LspDelegateField, field, delegateMethods); + + +struct CheckDelegateMethodsResponse { + std::vector<LspDelegateField> delegateFields; + + MAKE_SWAP_METHOD(CheckDelegateMethodsResponse, delegateFields) +}; +MAKE_REFLECT_STRUCT(CheckDelegateMethodsResponse, delegateFields) + +DEFINE_REQUEST_RESPONSE_TYPE(java_checkDelegateMethodsStatus, + lsCodeActionParams, CheckDelegateMethodsResponse, "java/checkDelegateMethodsStatus"); + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkHashCodeEqualsStatus.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkHashCodeEqualsStatus.h new file mode 100644 index 0000000000..1d9652dd44 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkHashCodeEqualsStatus.h @@ -0,0 +1,36 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include <LibLsp/lsp/lsCodeAction.h> + +#include "LibLsp/lsp/CodeActionParams.h" + +struct LspVariableBinding { + std::string bindingKey; + std::string name; + std::string type; + bool isField; + void swap(LspVariableBinding& arg) noexcept + { + bindingKey.swap(arg.bindingKey); + name.swap(arg.name); + type.swap(arg.type); + std::swap(isField, arg.isField); + } +}; +MAKE_REFLECT_STRUCT(LspVariableBinding, bindingKey, name, type, isField) + +struct CheckHashCodeEqualsResponse { + std::string type; + std::vector<LspVariableBinding> fields; + std::vector<std::string> existingMethods; + MAKE_SWAP_METHOD(CheckHashCodeEqualsResponse, type, fields, type, existingMethods) +}; +MAKE_REFLECT_STRUCT(CheckHashCodeEqualsResponse, type, fields, type, existingMethods) + +DEFINE_REQUEST_RESPONSE_TYPE(java_checkHashCodeEqualsStatus, + lsCodeActionParams, CheckHashCodeEqualsResponse, "java/checkHashCodeEqualsStatus") + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkToStringStatus.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkToStringStatus.h new file mode 100644 index 0000000000..24580d94c0 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/checkToStringStatus.h @@ -0,0 +1,24 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/CodeActionParams.h" +#include "checkHashCodeEqualsStatus.h" +struct CheckToStringResponse { + std::string type; + std::vector<LspVariableBinding> fields; + bool exists; + void swap(CheckToStringResponse& arg) noexcept + { + type.swap(arg.type); + fields.swap(arg.fields); + std::swap(exists, arg.exists); + } +}; +MAKE_REFLECT_STRUCT(CheckToStringResponse,type,fields,exists) + +DEFINE_REQUEST_RESPONSE_TYPE(java_checkToStringStatus, + lsCodeActionParams, CheckToStringResponse ,"java/checkToStringStatus") + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/classFileContents.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/classFileContents.h new file mode 100644 index 0000000000..70eb121b99 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/classFileContents.h @@ -0,0 +1,10 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include <string> +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" + +DEFINE_REQUEST_RESPONSE_TYPE(java_classFileContents, lsTextDocumentIdentifier, std::string ,"java/classFileContents"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/codeActionResult.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/codeActionResult.h new file mode 100644 index 0000000000..02024e3d93 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/codeActionResult.h @@ -0,0 +1,22 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include "LibLsp/JsonRpc/message.h" +#include "LibLsp/lsp/lsCodeAction.h" +#include "LibLsp/lsp/workspace/execute_command.h" +#include <set> +#include "LibLsp/lsp/textDocument/code_action.h" + +namespace SourceAssistProcessor { + + /*std::set<std::string> UNSUPPORTED_RESOURCES = { "module-info.java", "package-info.java" + };*/ + +// static const char* COMMAND_ID_ACTION_OVERRIDEMETHODSPROMPT = "java.action.overrideMethodsPrompt"; +// static const char* COMMAND_ID_ACTION_HASHCODEEQUALSPROMPT = "java.action.hashCodeEqualsPrompt"; +// static const char* COMMAND_ID_ACTION_ORGANIZEIMPORTS = "java.action.organizeImports"; +// static const char* COMMAND_ID_ACTION_GENERATETOSTRINGPROMPT = "java.action.generateToStringPrompt"; +// static const char* COMMAND_ID_ACTION_GENERATEACCESSORSPROMPT = "java.action.generateAccessorsPrompt"; +// static const char* COMMAND_ID_ACTION_GENERATECONSTRUCTORSPROMPT = "java.action.generateConstructorsPrompt"; +// static const char* COMMAND_ID_ACTION_GENERATEDELEGATEMETHODSPROMPT = "java.action.generateDelegateMethodsPrompt"; +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/executeCommand.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/executeCommand.h new file mode 100644 index 0000000000..92d4a3627b --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/executeCommand.h @@ -0,0 +1,29 @@ +#pragma once +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "LibLsp/lsp/lsWorkspaceEdit.h" +#include "LibLsp/lsp/ExecuteCommandParams.h" +namespace buildpath +{ +// static const char* EDIT_ORGNIZEIMPORTS = "java.edit.organizeImports"; +// static const char* RESOLVE_SOURCE_ATTACHMENT = "java.project.resolveSourceAttachment"; + +// static const char* UPDATE_SOURCE_ATTACHMENT = "java.project.updateSourceAttachment"; + +// static const char* ADD_TO_SOURCEPATH = "java.project.addToSourcePath"; + +// static const char* REMOVE_FROM_SOURCEPATH = "java.project.removeFromSourcePath"; + +// static const char* LIST_SOURCEPATHS = "java.project.listSourcePaths"; + struct Result { + bool status; + std::string message; + }; + + + +} + + +DEFINE_REQUEST_RESPONSE_TYPE(java_executeCommand, ExecuteCommandParams, lsWorkspaceEdit, "java/executeCommand"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/findLinks.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/findLinks.h new file mode 100644 index 0000000000..d184c675d8 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/findLinks.h @@ -0,0 +1,22 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "LibLsp/lsp/CodeActionParams.h" +#include "getRefactorEdit.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" + +struct FindLinksParams { + // Supported link types: superImplementation + std::string type; + lsTextDocumentPositionParams position; + + MAKE_SWAP_METHOD(FindLinksParams, type, position) +}; +MAKE_REFLECT_STRUCT(FindLinksParams,type,position) + +DEFINE_REQUEST_RESPONSE_TYPE(java_findLinks, FindLinksParams,lsp::Any, "java/findLinks"); + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateAccessors.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateAccessors.h new file mode 100644 index 0000000000..200d840e94 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateAccessors.h @@ -0,0 +1,19 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "checkHashCodeEqualsStatus.h" +#include "resolveUnimplementedAccessors.h" + + +struct GenerateAccessorsParams { + lsCodeActionParams context; + std::vector<AccessorField> accessors; + + + MAKE_SWAP_METHOD(GenerateAccessorsParams, context, accessors) +}; +MAKE_REFLECT_STRUCT(GenerateAccessorsParams, context, accessors) + +DEFINE_REQUEST_RESPONSE_TYPE(java_generateAccessors, GenerateAccessorsParams, lsWorkspaceEdit, "java/generateAccessors"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateConstructors.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateConstructors.h new file mode 100644 index 0000000000..77c49a66a2 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateConstructors.h @@ -0,0 +1,19 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "checkHashCodeEqualsStatus.h" +#include "checkConstructorsStatus.h" + + +struct GenerateConstructorsParams { + lsCodeActionParams context; + std::vector<LspMethodBinding> constructors; + std::vector< LspVariableBinding >fields; + MAKE_SWAP_METHOD(GenerateConstructorsParams, context, fields) +}; +MAKE_REFLECT_STRUCT(GenerateConstructorsParams, context, fields) + +DEFINE_REQUEST_RESPONSE_TYPE(java_generateConstructors, GenerateConstructorsParams, lsWorkspaceEdit, "java/generateConstructors"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateDelegateMethods.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateDelegateMethods.h new file mode 100644 index 0000000000..8958ae4d7e --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateDelegateMethods.h @@ -0,0 +1,25 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "checkHashCodeEqualsStatus.h" +#include "checkConstructorsStatus.h" + +struct LspDelegateEntry { + LspVariableBinding field; + LspMethodBinding delegateMethod; + MAKE_SWAP_METHOD(LspDelegateEntry, field, delegateMethod); +}; +MAKE_REFLECT_STRUCT(LspDelegateEntry, field, delegateMethod); + + +struct GenerateDelegateMethodsParams { + lsCodeActionParams context; + std::vector<LspDelegateEntry> delegateEntries; + MAKE_SWAP_METHOD(GenerateDelegateMethodsParams, context, delegateEntries) +}; +MAKE_REFLECT_STRUCT(GenerateDelegateMethodsParams, context, delegateEntries) + +DEFINE_REQUEST_RESPONSE_TYPE(java_generateDelegateMethods, GenerateDelegateMethodsParams, lsWorkspaceEdit, "java/generateDelegateMethods"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateHashCodeEquals.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateHashCodeEquals.h new file mode 100644 index 0000000000..937c358733 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateHashCodeEquals.h @@ -0,0 +1,25 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <LibLsp/lsp/lsCodeAction.h> + +#include "LibLsp/lsp/CodeActionParams.h" +#include "checkHashCodeEqualsStatus.h" + +struct GenerateHashCodeEqualsParams { + lsCodeActionParams context; + std::vector<LspVariableBinding> fields; + bool regenerate= false; + void swap(GenerateHashCodeEqualsParams& arg) noexcept + { + context.swap(arg.context); + fields.swap(arg.fields); + std::swap(regenerate, arg.regenerate); + } +}; +MAKE_REFLECT_STRUCT(GenerateHashCodeEqualsParams, context, fields, regenerate); + +DEFINE_REQUEST_RESPONSE_TYPE(java_generateHashCodeEquals, GenerateHashCodeEqualsParams, lsWorkspaceEdit, "java/generateHashCodeEquals") + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateToString.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateToString.h new file mode 100644 index 0000000000..1f8ccc73b8 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/generateToString.h @@ -0,0 +1,18 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "checkHashCodeEqualsStatus.h" + + +struct GenerateToStringParams { + lsCodeActionParams context; + std::vector< LspVariableBinding >fields; + + MAKE_SWAP_METHOD(GenerateToStringParams, context, fields) + +}; +MAKE_REFLECT_STRUCT(GenerateToStringParams, context, fields) + +DEFINE_REQUEST_RESPONSE_TYPE(java_generateToString, GenerateToStringParams, lsWorkspaceEdit, "java/generateToString"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/getMoveDestinations.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/getMoveDestinations.h new file mode 100644 index 0000000000..bcbf6f8c2b --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/getMoveDestinations.h @@ -0,0 +1,65 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "LibLsp/lsp/lsAny.h" +#include "LibLsp/lsp/CodeActionParams.h" + +struct MoveKindInfo +{ + static std::string moveResource() + { + return "moveResource"; + } + static std::string moveInstanceMethod() + { + return "moveInstanceMethod"; + } + static std::string moveStaticMember() + { + return "moveStaticMember"; + } +}; + +struct MoveParams { + /** + * The supported move kind: moveResource, moveInstanceMethod, moveStaticMember, + * moveTypeToNewFile. + */ + std::string moveKind; + /** + * The selected resource uris when the move operation is triggered. + */ + std::vector<std::string> sourceUris; + /** + * The code action params when the move operation is triggered. + */ + boost::optional<lsCodeActionParams> params; + /** + * The possible destination: a folder/package, class, instanceDeclaration. + */ + lsp::Any destination; + bool updateReferences; + void swap(MoveParams& arg) noexcept + { + moveKind.swap(arg.moveKind); + sourceUris.swap(arg.sourceUris); + params.swap(arg.params); + destination.swap(arg.destination); + std::swap(updateReferences, arg.updateReferences); + } +}; +MAKE_REFLECT_STRUCT(MoveParams, moveKind, sourceUris, params, destination, updateReferences); + +struct MoveDestinationsResponse { + std::string errorMessage; + std::vector<lsp::Any > destinations; + MAKE_SWAP_METHOD(MoveDestinationsResponse, errorMessage, destinations); +}; +MAKE_REFLECT_STRUCT(MoveDestinationsResponse, errorMessage, destinations); + +DEFINE_REQUEST_RESPONSE_TYPE(java_getMoveDestinations, MoveParams, MoveDestinationsResponse, "java/getMoveDestinations"); + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/getRefactorEdit.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/getRefactorEdit.h new file mode 100644 index 0000000000..e46327075a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/getRefactorEdit.h @@ -0,0 +1,77 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + + + +#include <string> +#include <vector> +#include "WorkspaceSymbolParams.h" +#include "LibLsp/lsp/method_type.h" +#include "LibLsp/lsp/textDocument/code_action.h" +#include "LibLsp/lsp/lsFormattingOptions.h" + +namespace +RefactorProposalUtility +{ + extern const char* APPLY_REFACTORING_COMMAND_ID; + extern const char* EXTRACT_VARIABLE_ALL_OCCURRENCE_COMMAND; + extern const char* EXTRACT_VARIABLE_COMMAND; + extern const char* EXTRACT_CONSTANT_COMMAND; + extern const char* EXTRACT_METHOD_COMMAND; + extern const char* EXTRACT_FIELD_COMMAND; + extern const char* CONVERT_VARIABLE_TO_FIELD_COMMAND; + extern const char* MOVE_FILE_COMMAND; + extern const char* MOVE_INSTANCE_METHOD_COMMAND; + extern const char* MOVE_STATIC_MEMBER_COMMAND; + extern const char* MOVE_TYPE_COMMAND; +}; + + +struct RenamePosition { + lsDocumentUri uri; + int offset = 0; + int length = 0; + void swap(RenamePosition& arg) noexcept + { + uri.swap(arg.uri); + std::swap(offset, arg.offset); + std::swap(length, arg.length); + } +}; +MAKE_REFLECT_STRUCT(RenamePosition, uri, offset, length); + +struct GetRefactorEditParams +{ + std::string command; + std::vector<lsp::Any> commandArguments; + lsCodeActionParams context; + boost::optional<lsFormattingOptions> options; + MAKE_SWAP_METHOD(GetRefactorEditParams, command, context, options); +}; +MAKE_REFLECT_STRUCT(GetRefactorEditParams, command, context, options); + + + + +struct RefactorWorkspaceEdit { + /** + * The workspace edit this code action performs. + */ + lsWorkspaceEdit edit; + /** + * A command this code action executes. If a code action provides a edit and a + * command, first the edit is executed and then the command. + */ + + boost::optional<std::string> errorMessage; + + boost::optional < lsCommandWithAny > command; + + MAKE_SWAP_METHOD(RefactorWorkspaceEdit, edit, command, errorMessage) +}; +MAKE_REFLECT_STRUCT(RefactorWorkspaceEdit,edit,command,errorMessage) + +DEFINE_REQUEST_RESPONSE_TYPE(java_getRefactorEdit, GetRefactorEditParams, RefactorWorkspaceEdit, "java/getRefactorEdit"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/listOverridableMethods.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/listOverridableMethods.h new file mode 100644 index 0000000000..13b73ce5c2 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/listOverridableMethods.h @@ -0,0 +1,17 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/CodeActionParams.h" +#include "OverridableMethod.h" + + + + + +DEFINE_REQUEST_RESPONSE_TYPE(java_listOverridableMethods, lsCodeActionParams, OverridableMethodsResponse, "java/listOverridableMethods"); + + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/organizeImports.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/organizeImports.h new file mode 100644 index 0000000000..817d52d32b --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/organizeImports.h @@ -0,0 +1,12 @@ +#pragma once +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <LibLsp/lsp/lsCodeAction.h> + +#include "LibLsp/lsp/CodeActionParams.h" + + + +DEFINE_REQUEST_RESPONSE_TYPE(java_organizeImports, lsCodeActionParams, lsWorkspaceEdit, "java/organizeImports"); + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/projectConfigurationUpdate.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/projectConfigurationUpdate.h new file mode 100644 index 0000000000..342d167093 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/projectConfigurationUpdate.h @@ -0,0 +1,13 @@ +#pragma once + +#include "LibLsp/JsonRpc/NotificationInMessage.h" + + +#include <string> +#include <vector> +#include "WorkspaceSymbolParams.h" + +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" + +DEFINE_NOTIFICATION_TYPE(java_projectConfigurationUpdate, lsTextDocumentIdentifier, "java/projectConfigurationUpdate"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/resolveUnimplementedAccessors.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/resolveUnimplementedAccessors.h new file mode 100644 index 0000000000..ba77041474 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/resolveUnimplementedAccessors.h @@ -0,0 +1,24 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "checkHashCodeEqualsStatus.h" + + +struct AccessorField { + std::string fieldName; + bool isStatic =false; + bool generateGetter = false; + bool generateSetter = false; + void swap(AccessorField& arg) noexcept{ + fieldName.swap(arg.fieldName); + std::swap(isStatic, arg.isStatic); + std::swap(generateGetter, arg.generateGetter); + std::swap(generateSetter, arg.generateSetter); + } +}; + +MAKE_REFLECT_STRUCT(AccessorField, fieldName,isStatic,generateGetter,generateSetter) + +DEFINE_REQUEST_RESPONSE_TYPE(java_resolveUnimplementedAccessors, lsCodeActionParams, std::vector<AccessorField>, "java/resolveUnimplementedAccessors"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/searchSymbols.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/searchSymbols.h new file mode 100644 index 0000000000..ac8a2419f6 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/jdtls/searchSymbols.h @@ -0,0 +1,27 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + + +#include <string> +#include <vector> +#include "WorkspaceSymbolParams.h" +#include "LibLsp/lsp/method_type.h" +#include "LibLsp/lsp/symbol.h" + + +struct SearchSymbolParams :public WorkspaceSymbolParams +{ + boost::optional<std::string> projectName; + boost::optional< bool >sourceOnly; + boost::optional< int> maxResults; + MAKE_SWAP_METHOD(SearchSymbolParams, query, projectName, sourceOnly, maxResults); +}; +MAKE_REFLECT_STRUCT(SearchSymbolParams, query, projectName, sourceOnly, maxResults); + + +DEFINE_REQUEST_RESPONSE_TYPE(java_searchSymbols, SearchSymbolParams, std::vector<lsSymbolInformation>, "java/searchSymbols"); + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/sonarlint/protocol.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/sonarlint/protocol.h new file mode 100644 index 0000000000..d81c3eaa63 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/extention/sonarlint/protocol.h @@ -0,0 +1,176 @@ +#pragma once +#include <string> +#include <boost/optional.hpp> +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/lsp/lsDocumentUri.h" +#include "LibLsp/lsp/lsAny.h" +#include "LibLsp/JsonRpc/NotificationInMessage.h" +#include "LibLsp/lsp/general/InitializeParams.h" + +struct LintRule +{ + std::string key; + std::string name; + + + std::string Display() const + { + return name + " (" + key + ")"; + } + bool activeByDefault = true; + boost::optional<std::string> severity; + boost::optional<std::string> type; + int icon_index = -1; + MAKE_SWAP_METHOD(LintRule, key, name, activeByDefault, severity, type); + +}; +MAKE_REFLECT_STRUCT(LintRule, key, name, activeByDefault, severity, type); + + +struct RuleParameter { + std::string name; + boost::optional<std::string> description; + boost::optional<std::string> defaultValue; + +}; +MAKE_REFLECT_STRUCT(RuleParameter, name, description, defaultValue); + +struct ShowRuleDescriptionParams { + + boost::optional<std::string> key; + + boost::optional<std::string> name; + + boost::optional<std::string> htmlDescription; + + boost::optional<std::string> type; + + boost::optional<std::string> severity; + + boost::optional< std::vector<RuleParameter> > parameters; + MAKE_SWAP_METHOD(ShowRuleDescriptionParams, key, name, htmlDescription, type, severity, parameters) + + +}; +MAKE_REFLECT_STRUCT(ShowRuleDescriptionParams, key, name, htmlDescription, type, severity, parameters); + + +struct GetJavaConfigResponse { + std::string projectRoot; + std::string sourceLevel; + std::vector<std::string> classpath; + bool isTest; + std::string vmLocation; + MAKE_SWAP_METHOD(GetJavaConfigResponse, projectRoot, sourceLevel, classpath, isTest, vmLocation); +}; +MAKE_REFLECT_STRUCT(GetJavaConfigResponse, projectRoot, sourceLevel, classpath, isTest, vmLocation); + +struct SetTraceNotificationParams { + lsInitializeParams::lsTrace value; +}; +MAKE_REFLECT_STRUCT(SetTraceNotificationParams, value); + + +struct ServerConnectionSettings { + + std::string SONARCLOUD_URL = "https://sonarcloud.io"; + std::vector<std::string>SONARCLOUD_ALIAS = { "https://sonarqube.com", + "https://www.sonarqube.com", + "https://www.sonarcloud.io", + "https://sonarcloud.io" }; + + std::string connectionId; + std::string serverUrl; + std::string token; + boost::optional<std::string> organizationKey; + MAKE_SWAP_METHOD(ServerConnectionSettings, connectionId, serverUrl, token, organizationKey) + +}; +MAKE_REFLECT_STRUCT(ServerConnectionSettings, connectionId, serverUrl, token, organizationKey) + +struct RuleSetting +{ + bool IsOn(); + std::string level = "on"; + RuleSetting(bool activate); + RuleSetting() = default; + void toggle(); + void on() + { + level = "on"; + } + void off() + { + level = "off"; + } + void turn(bool activate) + { + if (activate) + { + on(); + } + else + { + off(); + } + } + boost::optional< std::map<std::string, std::string > > parameters; +}; +MAKE_REFLECT_STRUCT(RuleSetting, level, parameters) + +struct ConsoleParams +{ + boost::optional < bool >showAnalyzerLogs; + boost::optional < bool >showVerboseLogs; + MAKE_SWAP_METHOD(ConsoleParams, showAnalyzerLogs, showVerboseLogs) +}; +MAKE_REFLECT_STRUCT(ConsoleParams, showAnalyzerLogs, showVerboseLogs) + +struct SonarLintWorkspaceSettings +{ + boost::optional < bool > disableTelemetry; + boost::optional < std::map<std::string, ServerConnectionSettings> >connectedMode; + boost::optional<std::map<std::string, RuleSetting>> rules; + boost::optional<ConsoleParams> output; + + boost::optional<std::string > pathToNodeExecutable; + + boost::optional< std::map<std::string, std::string > > getConfigurationParameters(const std::string& ruleKey); + + +}; + +MAKE_REFLECT_STRUCT(SonarLintWorkspaceSettings, disableTelemetry, connectedMode, + rules, output, pathToNodeExecutable) + + + + DEFINE_REQUEST_RESPONSE_TYPE(slls_listAllRules, JsonNull, lsp::Any, "sonarlint/listAllRules"); + + + +DEFINE_NOTIFICATION_TYPE(Notify_didClasspathUpdate, lsDocumentUri, "sonarlint/didClasspathUpdate") + + +DEFINE_NOTIFICATION_TYPE(Notify_didJavaServerModeChange, std::string, "sonarlint/didJavaServerModeChange") + + + +DEFINE_REQUEST_RESPONSE_TYPE(slls_showSonarLintOutput, JsonNull, JsonNull, "sonarlint/showSonarLintOutput"); + + + +DEFINE_REQUEST_RESPONSE_TYPE(slls_openJavaHomeSettings, JsonNull, JsonNull, "sonarlint/openJavaHomeSettings"); + + + + +DEFINE_REQUEST_RESPONSE_TYPE(slls_openPathToNodeSettings, JsonNull, JsonNull, "sonarlint/openPathToNodeSettings"); + + +DEFINE_REQUEST_RESPONSE_TYPE(slls_showRuleDescription, ShowRuleDescriptionParams, JsonNull, "sonarlint/showRuleDescription"); + +DEFINE_REQUEST_RESPONSE_TYPE(slls_getJavaConfig, lsDocumentUri, GetJavaConfigResponse, "sonarlint/getJavaConfig"); + + +DEFINE_NOTIFICATION_TYPE(slls_setTraceNotification, SetTraceNotificationParams, "$/setTraceNotification")
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/InitializeParams.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/InitializeParams.h new file mode 100644 index 0000000000..f10080ea21 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/InitializeParams.h @@ -0,0 +1,128 @@ +#pragma once + +#include "LibLsp/lsp/lsDocumentUri.h" +#include "LibLsp/lsp/lsAny.h" +#include "lsClientCapabilities.h" +#include "LibLsp/lsp/workspace/workspaceFolders.h" + +struct ClientInfo { + std::string name; + boost::optional<std::string> version; + + MAKE_SWAP_METHOD(ClientInfo,name,version); +}; +MAKE_REFLECT_STRUCT(ClientInfo,name,version); + +struct lsInitializeParams { + // The process Id of the parent process that started + // the server. Is null if the process has not been started by another process. + // If the parent process is not alive then the server should exit (see exit + // notification) its process. + boost::optional<int> processId; + + /** + * Information about the client + * + * @since 3.15.0 + */ + boost::optional<ClientInfo> clientInfo; + /** + * The locale the client is currently showing the user interface + * in. This must not necessarily be the locale of the operating + * system. + * + * Uses IETF language tags as the value's syntax + * (See https://en.wikipedia.org/wiki/IETF_language_tag) + * + * @since 3.16.0 + */ + boost::optional<std::string> locale; + + // The rootPath of the workspace. Is null + // if no folder is open. + // + // @deprecated in favour of rootUri. + boost::optional<std::string> rootPath; + + // The rootUri of the workspace. Is null if no + // folder is open. If both `rootPath` and `rootUri` are set + // `rootUri` wins. + boost::optional<lsDocumentUri> rootUri; + + // User provided initialization options. + boost::optional<lsp::Any> initializationOptions; + + // The capabilities provided by the client (editor or tool) + lsClientCapabilities capabilities; + + + /** + * An boost::optional extension to the protocol. + * To tell the server what client (editor) is talking to it. + */ + // @Deprecated + boost::optional< std::string >clientName; + + + + enum class lsTrace { + // NOTE: serialized as a string, one of 'off' | 'messages' | 'verbose'; + Off, // off + Messages, // messages + Verbose // verbose + + }; + + // The initial trace setting. If omitted trace is disabled ('off'). + lsTrace trace = lsTrace::Off; + + + /** + * The workspace folders configured in the client when the server starts. + * This property is only available if the client supports workspace folders. + * It can be `null` if the client supports workspace folders but none are + * configured. + * + * Since 3.6.0 + */ + boost::optional< std::vector<WorkspaceFolder> > workspaceFolders; + + MAKE_SWAP_METHOD(lsInitializeParams, + processId, + rootPath, + rootUri, + initializationOptions, + capabilities, clientName, clientInfo, + trace, workspaceFolders, locale) +}; + +void Reflect(Reader& reader, lsInitializeParams::lsTrace& value); + + +void Reflect(Writer& writer, lsInitializeParams::lsTrace& value); + + +MAKE_REFLECT_STRUCT(lsInitializeParams, + processId, + rootPath, + rootUri, + initializationOptions, + capabilities, clientName, clientInfo, + trace, workspaceFolders, locale) + +struct lsInitializeError { + // Indicates whether the client should retry to send the + // initilize request after showing the message provided + // in the ResponseError. + bool retry; + void swap(lsInitializeError& arg) noexcept + { + auto tem = retry; + retry = arg.retry; + arg.retry = tem; + } +}; +MAKE_REFLECT_STRUCT(lsInitializeError, retry); + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/exit.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/exit.h new file mode 100644 index 0000000000..02fe216017 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/exit.h @@ -0,0 +1,7 @@ +#pragma once + +#include "LibLsp/JsonRpc/NotificationInMessage.h" +/** + * A notification to ask the server to exit its process. + */ +DEFINE_NOTIFICATION_TYPE(Notify_Exit, boost::optional<JsonNull>, "exit"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/initialize.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/initialize.h new file mode 100644 index 0000000000..eb8810939a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/initialize.h @@ -0,0 +1,39 @@ +#pragma once +#include "LibLsp/JsonRpc/message.h" +#include "InitializeParams.h" +#include "lsServerCapabilities.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" + + + + + + +/** + * The capabilities the language server provides. + */ + struct InitializeResult { + lsServerCapabilities capabilities; + MAKE_SWAP_METHOD(InitializeResult, capabilities); + }; + +MAKE_REFLECT_STRUCT(InitializeResult, capabilities); + + +/** + * The initialize request is sent as the first request from the client to + * the server. + * + * If the server receives request or notification before the initialize request it should act as follows: + * - for a request the respond should be errored with code: -32001. The message can be picked by the server. + * - notifications should be dropped, except for the exit notification. This will allow the exit a server without an initialize request. + * + * Until the server has responded to the initialize request with an InitializeResult + * the client must not sent any additional requests or notifications to the server. + * + * During the initialize request the server is allowed to sent the notifications window/showMessage, + * window/logMessage and telemetry/event as well as the window/showMessageRequest request to the client. + */ + +DEFINE_REQUEST_RESPONSE_TYPE(td_initialize, lsInitializeParams, InitializeResult, "initialize"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/initialized.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/initialized.h new file mode 100644 index 0000000000..bb6d12511c --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/initialized.h @@ -0,0 +1,13 @@ +#pragma once + + +#include "LibLsp/JsonRpc/NotificationInMessage.h" +/** + * The initialized notification is sent from the client to the server after + * the client received the result of the initialize request but before the + * client is sending any other request or notification to the server. The + * server can use the initialized notification for example to dynamically + * register capabilities. + */ +DEFINE_NOTIFICATION_TYPE(Notify_InitializedNotification, JsonNull, "initialized"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsClientCapabilities.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsClientCapabilities.h new file mode 100644 index 0000000000..fcf6634e13 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsClientCapabilities.h @@ -0,0 +1,48 @@ +#pragma once + +#include "LibLsp/lsp/lsAny.h" +#include "lsWorkspaceClientCapabilites.h" +#include "lsTextDocumentClientCapabilities.h" + +/** + * Client capabilities specific to the used markdown parser. + * + * @since 3.16.0 + */ +struct MarkdownClientCapabilities { + /** + * The name of the parser. + */ + std::string parser; + + /** + * The version of the parser. + */ + boost::optional<std::string> version; + MAKE_SWAP_METHOD(MarkdownClientCapabilities, parser, version) + +}; +MAKE_REFLECT_STRUCT(MarkdownClientCapabilities, parser, version) + +struct lsClientCapabilities { + // Workspace specific client capabilities. + boost::optional<lsWorkspaceClientCapabilites> workspace; + + // Text document specific client capabilities. + boost::optional<lsTextDocumentClientCapabilities> textDocument; + + /** + * Window specific client capabilities. + */ + boost::optional<lsp::Any> window; + /** + * Experimental client capabilities. + */ + boost::optional<lsp::Any> experimental; + + MAKE_SWAP_METHOD(lsClientCapabilities, workspace, textDocument, window, experimental) +}; +MAKE_REFLECT_STRUCT(lsClientCapabilities, workspace, textDocument, window, experimental) + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsServerCapabilities.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsServerCapabilities.h new file mode 100644 index 0000000000..66af2ced6b --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsServerCapabilities.h @@ -0,0 +1,589 @@ +#pragma once +#include "LibLsp/lsp/method_type.h" + + +#include <stdexcept> +#include "LibLsp/JsonRpc/message.h" +#include "LibLsp/lsp/lsDocumentUri.h" +#include "LibLsp/lsp/lsAny.h" +#include "InitializeParams.h" +#include "LibLsp/lsp/textDocument/SemanticTokens.h" + + +extern void Reflect(Reader&, std::pair<boost::optional<lsTextDocumentSyncKind>, boost::optional<lsTextDocumentSyncOptions> >&); + +// + // Code Action options. + // +struct CodeActionOptions : WorkDoneProgressOptions { + // + // CodeActionKinds that this server may return. + // + // The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server + // may list out every specific kind they provide. + // + typedef std::string CodeActionKind; + std::vector<CodeActionKind> codeActionKinds; + + MAKE_SWAP_METHOD(CodeActionOptions, workDoneProgress, codeActionKinds); +}; +MAKE_REFLECT_STRUCT(CodeActionOptions, workDoneProgress, codeActionKinds) +struct CodeLensOptions : WorkDoneProgressOptions { + // + // Code lens has a resolve provider as well. + // + boost::optional<bool> resolveProvider ; + MAKE_SWAP_METHOD(CodeLensOptions, workDoneProgress, resolveProvider); +}; +MAKE_REFLECT_STRUCT(CodeLensOptions, workDoneProgress, resolveProvider) + + +// Format document on type options +struct lsDocumentOnTypeFormattingOptions :WorkDoneProgressOptions { + // A character on which formatting should be triggered, like `}`. + std::string firstTriggerCharacter; + + // More trigger characters. + std::vector<std::string> moreTriggerCharacter; + MAKE_SWAP_METHOD(lsDocumentOnTypeFormattingOptions, workDoneProgress, + firstTriggerCharacter, + moreTriggerCharacter); +}; +MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, workDoneProgress, + firstTriggerCharacter, + moreTriggerCharacter); +struct RenameOptions : WorkDoneProgressOptions { + // + // Renames should be checked and tested before being executed. + // + boost::optional<bool> prepareProvider; + MAKE_SWAP_METHOD(RenameOptions, workDoneProgress, prepareProvider); +}; +MAKE_REFLECT_STRUCT(RenameOptions,workDoneProgress,prepareProvider) + +struct DocumentFilter{ + // + // A language id, like `typescript`. + // + boost::optional<std::string> language; + // + // A Uri [scheme](#Uri.scheme), like `file` or `untitled`. + // + boost::optional<std::string>scheme; + // + // A glob pattern, like `*.{ts,js}`. + // + // Glob patterns can have the following syntax: + // - `*` to match one or more characters in a path segment + // - `?` to match on one character in a path segment + // - `**` to match any number of path segments, including none + // - `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js} + // matches all TypeScript and JavaScript files) + // - `[]` to declare a range of characters to match in a path segment + // (e.g., `example.[0-9]` to match on `example.0`, `example.1`,...) + // - `[!...]` to negate a range of characters to match in a path segment + // (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but + // not `example.0`) + // + boost::optional<std::string>pattern; + MAKE_SWAP_METHOD(DocumentFilter, language, scheme, pattern) +}; +MAKE_REFLECT_STRUCT(DocumentFilter, language, scheme, pattern) + +//A document selector is the combination of one or more document filters. +using DocumentSelector = std::vector<DocumentFilter>; + +// Document link options +struct lsDocumentLinkOptions :WorkDoneProgressOptions { + // Document links have a resolve provider as well. + boost::optional<bool> resolveProvider; + MAKE_SWAP_METHOD(lsDocumentLinkOptions, workDoneProgress, resolveProvider); +}; +MAKE_REFLECT_STRUCT(lsDocumentLinkOptions, workDoneProgress,resolveProvider); + +// Execute command options. +struct lsExecuteCommandOptions : WorkDoneProgressOptions { + // The commands to be executed on the server + std::vector<std::string> commands; + MAKE_SWAP_METHOD(lsExecuteCommandOptions, workDoneProgress, commands); +}; +MAKE_REFLECT_STRUCT(lsExecuteCommandOptions, workDoneProgress, commands); + + +struct TextDocumentRegistrationOptions +{ +// + // A document selector to identify the scope of the registration. If set to null + // the document selector provided on the client side will be used. + // + boost::optional<DocumentSelector> documentSelector; + + MAKE_SWAP_METHOD(TextDocumentRegistrationOptions, documentSelector); +}; +MAKE_REFLECT_STRUCT(TextDocumentRegistrationOptions, documentSelector); + +// + // Static registration options to be returned in the initialize request. + // +struct StaticRegistrationOptions :public TextDocumentRegistrationOptions +{ + // + // The id used to register the request. The id can be used to deregister + // the request again. See also Registration#id. + // + boost::optional<std::string> id; + MAKE_SWAP_METHOD(StaticRegistrationOptions, documentSelector, id) +}; +MAKE_REFLECT_STRUCT(StaticRegistrationOptions, documentSelector,id) + +// + // The server supports workspace folder. + // + // Since 3.6.0 + // + +struct WorkspaceFoldersOptions { + // + // The server has support for workspace folders + // + boost::optional<bool> supported; + + // + // Whether the server wants to receive workspace folder + // change notifications. + // + // If a string is provided, the string is treated as an ID + // under which the notification is registered on the client + // side. The ID can be used to unregister for these events + // using the `client/unregisterCapability` request. + // + boost::optional<std::pair< boost::optional<std::string>, boost::optional<bool> > > changeNotifications; + MAKE_SWAP_METHOD(WorkspaceFoldersOptions, supported, changeNotifications); +}; +MAKE_REFLECT_STRUCT(WorkspaceFoldersOptions, supported, changeNotifications); + +// + // A pattern kind describing if a glob pattern matches a file a folder or + // both. + // + // @since 3.16.0 + // +enum lsFileOperationPatternKind +{ + file, + folder +}; +MAKE_REFLECT_TYPE_PROXY(lsFileOperationPatternKind) + +// + // Matching options for the file operation pattern. + // + // @since 3.16.0 + // +struct lsFileOperationPatternOptions { + + // + // The pattern should be matched ignoring casing. + // + boost::optional<bool> ignoreCase; + MAKE_SWAP_METHOD(lsFileOperationPatternOptions, ignoreCase) +}; +MAKE_REFLECT_STRUCT(lsFileOperationPatternOptions, ignoreCase) +// + // A pattern to describe in which file operation requests or notifications + // the server is interested in. + // + // @since 3.16.0 + // +struct lsFileOperationPattern { + // + // The glob pattern to match. Glob patterns can have the following syntax: + // - `*` to match one or more characters in a path segment + // - `?` to match on one character in a path segment + // - `**` to match any number of path segments, including none + // - `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}` + // matches all TypeScript and JavaScript files) + // - `[]` to declare a range of characters to match in a path segment + // (e.g., `example.[0-9]` to match on `example.0`, `example.1`,...) + // - `[!...]` to negate a range of characters to match in a path segment + // (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but + // not `example.0`) + // + std::string glob; + + // + // Whether to match files or folders with this pattern. + // + // Matches both if undefined. + // + boost::optional<lsFileOperationPatternKind> matches; + + // + // Additional options used during matching. + // + boost::optional<lsFileOperationPatternOptions> options ; + MAKE_SWAP_METHOD(lsFileOperationPattern, glob, matches, options) +}; +MAKE_REFLECT_STRUCT(lsFileOperationPattern, glob, matches, options) +// + // A filter to describe in which file operation requests or notifications + // the server is interested in. + // + // @since 3.16.0 + // +struct lsFileOperationFilter { + + // + // A Uri like `file` or `untitled`. + // + boost::optional<std::string> scheme; + + // + // The actual file operation pattern. + // + boost::optional<lsFileOperationPattern> pattern; + MAKE_SWAP_METHOD(lsFileOperationFilter, scheme, pattern) +}; +MAKE_REFLECT_STRUCT(lsFileOperationFilter, scheme, pattern) +// + // The options to register for file operations. + // + // @since 3.16.0 + // +struct lsFileOperationRegistrationOptions { + // + // The actual filters. + // + boost::optional<std::vector<lsFileOperationFilter>> filters; + MAKE_SWAP_METHOD(lsFileOperationRegistrationOptions, filters) +}; +MAKE_REFLECT_STRUCT(lsFileOperationRegistrationOptions, filters) + +struct WorkspaceServerCapabilities { + // + // The server supports workspace folder. + // + // Since 3.6.0 + // + WorkspaceFoldersOptions workspaceFolders; + + + // + // The server is interested in file notifications/requests. + // + // @since 3.16.0 + // + struct lsFileOperations + { + // + // The server is interested in receiving didCreateFiles + // notifications. + // + boost::optional<lsFileOperationRegistrationOptions> didCreate; + + // + // The server is interested in receiving willCreateFiles requests. + // + boost::optional<lsFileOperationRegistrationOptions> willCreate; + + // + // The server is interested in receiving didRenameFiles + // notifications. + // + boost::optional<lsFileOperationRegistrationOptions> didRename; + + // + // The server is interested in receiving willRenameFiles requests. + // + boost::optional<lsFileOperationRegistrationOptions> willRename; + + // + // The server is interested in receiving didDeleteFiles file + // notifications. + // + boost::optional<lsFileOperationRegistrationOptions> didDelete; + + // + // The server is interested in receiving willDeleteFiles file + // requests. + // + boost::optional<lsFileOperationRegistrationOptions> willDelete; + MAKE_SWAP_METHOD(lsFileOperations, didCreate, willCreate, didRename, willRename, didDelete, willDelete) + }; + boost::optional<lsFileOperations>fileOperations; + + + MAKE_SWAP_METHOD(WorkspaceServerCapabilities, workspaceFolders, fileOperations) +}; +MAKE_REFLECT_STRUCT(WorkspaceServerCapabilities, workspaceFolders, fileOperations) +MAKE_REFLECT_STRUCT(WorkspaceServerCapabilities::lsFileOperations, didCreate, willCreate, didRename, willRename, didDelete, willDelete) + +// + // Semantic highlighting server capabilities. + // + // <p> + // <b>Note:</b> the <a href= + // "https://github.com/Microsoft/vscode-languageserver-node/pull/367">{@code textDocument/semanticHighlighting} + // language feature</a> is not yet part of the official LSP specification. + // + +struct SemanticHighlightingServerCapabilities { + // + // A "lookup table" of semantic highlighting <a href="https://manual.macromates.com/en/language_grammars">TextMate scopes</a> + // supported by the language server. If not defined or empty, then the server does not support the semantic highlighting + // feature. Otherwise, clients should reuse this "lookup table" when receiving semantic highlighting notifications from + // the server. + // + std::vector< std::vector<std::string> > scopes; + MAKE_SWAP_METHOD(SemanticHighlightingServerCapabilities, scopes) +}; +MAKE_REFLECT_STRUCT(SemanticHighlightingServerCapabilities, scopes) + +struct SemanticTokensServerFull +{ + // + // The server supports deltas for full documents. + // + bool delta =false; + MAKE_SWAP_METHOD(SemanticTokensServerFull, delta) +}; +MAKE_REFLECT_STRUCT(SemanticTokensServerFull, delta) +struct SemanticTokensWithRegistrationOptions +{ + SemanticTokensLegend legend; + + // + // Server supports providing semantic tokens for a specific range + // of a document. + // + boost::optional< std::pair< boost::optional<bool>, boost::optional<lsp::Any> > > range; + + // + // Server supports providing semantic tokens for a full document. + // + boost::optional< std::pair< boost::optional<bool>, + boost::optional<SemanticTokensServerFull> > > full; + + // + // A document selector to identify the scope of the registration. If set to null + // the document selector provided on the client side will be used. + // + boost::optional < std::vector<DocumentFilter> > documentSelector; + // + // The id used to register the request. The id can be used to deregister + // the request again. See also Registration#id. + // + boost::optional<std::string> id; + MAKE_SWAP_METHOD(SemanticTokensWithRegistrationOptions, legend, range, full, documentSelector, id) +}; +MAKE_REFLECT_STRUCT(SemanticTokensWithRegistrationOptions, legend, range, full, documentSelector ,id) + +using DocumentColorOptions = WorkDoneProgressOptions; +using FoldingRangeOptions = WorkDoneProgressOptions; +struct lsServerCapabilities { + // Defines how text documents are synced. Is either a detailed structure + // defining each notification or for backwards compatibility the + + // TextDocumentSyncKind number. + boost::optional< std::pair<boost::optional<lsTextDocumentSyncKind>, + boost::optional<lsTextDocumentSyncOptions> >> textDocumentSync; + + // The server provides hover support. + boost::optional<bool> hoverProvider; + + // The server provides completion support. + boost::optional < lsCompletionOptions > completionProvider; + + // The server provides signature help support. + boost::optional < lsSignatureHelpOptions > signatureHelpProvider; + + // The server provides goto definition support. + boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > definitionProvider; + + + // + // The server provides Goto Type Definition support. + // + // Since 3.6.0 + // + boost::optional< std::pair< boost::optional<bool>, boost::optional<StaticRegistrationOptions> > > typeDefinitionProvider ; + + // The server provides implementation support. + boost::optional< std::pair< boost::optional<bool>, boost::optional<StaticRegistrationOptions> > > implementationProvider ; + + // The server provides find references support. + boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > referencesProvider ; + + // The server provides document highlight support. + boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > documentHighlightProvider ; + + // The server provides document symbol support. + boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > documentSymbolProvider ; + + // The server provides workspace symbol support. + boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > workspaceSymbolProvider ; + + // The server provides code actions. + boost::optional< std::pair< boost::optional<bool>, boost::optional<CodeActionOptions> > > codeActionProvider ; + + // The server provides code lens. + boost::optional<CodeLensOptions> codeLensProvider; + + // The server provides document formatting. + boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > documentFormattingProvider ; + + // The server provides document range formatting. + boost::optional< std::pair< boost::optional<bool>, boost::optional<WorkDoneProgressOptions> > > documentRangeFormattingProvider ; + + // The server provides document formatting on typing. + boost::optional<lsDocumentOnTypeFormattingOptions> documentOnTypeFormattingProvider; + + // The server provides rename support. + boost::optional< std::pair< boost::optional<bool>, boost::optional<RenameOptions> > > renameProvider; + + + // The server provides document link support. + boost::optional<lsDocumentLinkOptions > documentLinkProvider; + + + // + // The server provides color provider support. + // + // @since 3.6.0 + // + boost::optional< std::pair< boost::optional<bool>, boost::optional<DocumentColorOptions> > > colorProvider; + + + // + // The server provides folding provider support. + // + // @since 3.10.0 + // + boost::optional < std::pair< boost::optional<bool>, boost::optional<FoldingRangeOptions> > > foldingRangeProvider; + + // The server provides execute command support. + boost::optional < lsExecuteCommandOptions >executeCommandProvider; + + + // + // Workspace specific server capabilities + // + boost::optional< WorkspaceServerCapabilities > workspace; + + // + // Semantic highlighting server capabilities. + // + + boost::optional< SemanticHighlightingServerCapabilities >semanticHighlighting; + + // + // Server capability for calculating super- and subtype hierarchies. + // The LS supports the type hierarchy language feature, if this capability is set to {@code true}. + // + // <p> + // <b>Note:</b> the <a href= + // "https://github.com/Microsoft/vscode-languageserver-node/pull/426">{@code textDocument/typeHierarchy} + // language feature</a> is not yet part of the official LSP specification. + // + + boost::optional< std::pair< boost::optional<bool>, + boost::optional<StaticRegistrationOptions> > > typeHierarchyProvider; + + // + // The server provides Call Hierarchy support. + // + + boost::optional< std::pair< boost::optional<bool>, + boost::optional<StaticRegistrationOptions> > > callHierarchyProvider; + + // + // The server provides selection range support. + // + // Since 3.15.0 + // + boost::optional< std::pair< boost::optional<bool>, + boost::optional<StaticRegistrationOptions> > > selectionRangeProvider; + + // + // The server provides linked editing range support. + // + // Since 3.16.0 + // + boost::optional< std::pair< boost::optional<bool>, + boost::optional<StaticRegistrationOptions> > > linkedEditingRangeProvider; + + + // + // The server provides semantic tokens support. + // + // Since 3.16.0 + // + boost::optional < SemanticTokensWithRegistrationOptions> semanticTokensProvider; + + // + // Whether server provides moniker support. + // + // Since 3.16.0 + // + boost::optional< std::pair< boost::optional<bool>, + boost::optional<StaticRegistrationOptions> > > monikerProvider; + + boost::optional<lsp::Any> experimental; + + + MAKE_SWAP_METHOD(lsServerCapabilities, + textDocumentSync, + hoverProvider, + completionProvider, + signatureHelpProvider, + definitionProvider, + typeDefinitionProvider, + implementationProvider, + referencesProvider, + documentHighlightProvider, + documentSymbolProvider, + workspaceSymbolProvider, + codeActionProvider, + codeLensProvider, + documentFormattingProvider, + documentRangeFormattingProvider, + documentOnTypeFormattingProvider, + renameProvider, + documentLinkProvider, + executeCommandProvider, + workspace, + semanticHighlighting, + typeHierarchyProvider, + callHierarchyProvider, + selectionRangeProvider, + experimental, colorProvider, foldingRangeProvider, + linkedEditingRangeProvider, monikerProvider, semanticTokensProvider) + +}; +MAKE_REFLECT_STRUCT(lsServerCapabilities, + textDocumentSync, + hoverProvider, + completionProvider, + signatureHelpProvider, + definitionProvider, + typeDefinitionProvider, + implementationProvider, + referencesProvider, + documentHighlightProvider, + documentSymbolProvider, + workspaceSymbolProvider, + codeActionProvider, + codeLensProvider, + documentFormattingProvider, + documentRangeFormattingProvider, + documentOnTypeFormattingProvider, + renameProvider, + documentLinkProvider, + executeCommandProvider, + workspace, + semanticHighlighting, + typeHierarchyProvider, + callHierarchyProvider, + selectionRangeProvider, + experimental, colorProvider, foldingRangeProvider, + linkedEditingRangeProvider, monikerProvider, semanticTokensProvider) diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h new file mode 100644 index 0000000000..569f203c7a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h @@ -0,0 +1,713 @@ +#pragma once +#include "LibLsp/lsp/method_type.h" + + +#include <stdexcept> +#include "LibLsp/JsonRpc/message.h" +#include "LibLsp/lsp/lsDocumentUri.h" +#include "LibLsp/lsp/lsAny.h" +#include "LibLsp/lsp/extention/jdtls/searchSymbols.h" +#include "lsWorkspaceClientCapabilites.h" +#include "LibLsp/lsp/lsp_completion.h" +#include "LibLsp/lsp/lsp_diagnostic.h" + + +struct WorkDoneProgressOptions +{ + boost::optional<bool>workDoneProgress; + MAKE_SWAP_METHOD(WorkDoneProgressOptions, workDoneProgress); +}; +MAKE_REFLECT_STRUCT(WorkDoneProgressOptions, workDoneProgress); + +// Completion options. +struct lsCompletionOptions:WorkDoneProgressOptions +{ + // The server provides support to resolve additional + // information for a completion item. + boost::optional<bool> resolveProvider = false; + + // + // Most tools trigger completion request automatically without explicitly requesting + // it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user + // starts to type an identifier. For example if the user types `c` in a JavaScript file + // code complete will automatically pop up present `console` besides others as a + // completion item. Characters that make up identifiers don't need to be listed here. + // + // If code complete should automatically be trigger on characters not being valid inside + // an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. + // + // https://github.com/Microsoft/language-server-protocol/issues/138. + boost::optional< std::vector<std::string> > triggerCharacters ; + + // + // The list of all possible characters that commit a completion. This field can be used + // if clients don't support individual commmit characters per completion item. See + // `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport` + // + boost::optional< std::vector<std::string> > allCommitCharacters; + + MAKE_SWAP_METHOD(lsCompletionOptions, workDoneProgress, resolveProvider, triggerCharacters, allCommitCharacters); +}; +MAKE_REFLECT_STRUCT(lsCompletionOptions, workDoneProgress, resolveProvider, triggerCharacters,allCommitCharacters); + + + +// Save options. +struct lsSaveOptions { + // The client is supposed to include the content on save. + bool includeText = false; + void swap(lsSaveOptions& arg)noexcept + { + auto temp = includeText; + includeText = arg.includeText; + arg.includeText = temp; + } +}; +MAKE_REFLECT_STRUCT(lsSaveOptions, includeText); + +// Signature help options. +struct lsSignatureHelpOptions : WorkDoneProgressOptions { + // The characters that trigger signature help automatically. + // NOTE: If updating signature help tokens make sure to also update + // WorkingFile::FindClosestCallNameInBuffer. + std::vector<std::string> triggerCharacters; + MAKE_SWAP_METHOD(lsSignatureHelpOptions, workDoneProgress, triggerCharacters); +}; +MAKE_REFLECT_STRUCT(lsSignatureHelpOptions, workDoneProgress, triggerCharacters); + +// Defines how the host (editor) should sync document changes to the language +// server. +enum class lsTextDocumentSyncKind { + // Documents should not be synced at all. + None = 0, + + // Documents are synced by always sending the full content + // of the document. + Full = 1, + + // Documents are synced by sending the full content on open. + // After that only incremental updates to the document are + // send. + Incremental = 2 +}; + +#if _WIN32 +MAKE_REFLECT_TYPE_PROXY(lsTextDocumentSyncKind) +#else +//#pragma clang diagnostic push +//#pragma clang diagnostic ignored "-Wunused-function" +MAKE_REFLECT_TYPE_PROXY(lsTextDocumentSyncKind) +//#pragma clang diagnostic pop +#endif + +struct lsTextDocumentSyncOptions { + // Open and close notifications are sent to the server. + boost::optional<bool> openClose ; + // Change notificatins are sent to the server. See TextDocumentSyncKind.None, + // TextDocumentSyncKind.Full and TextDocumentSyncKindIncremental. + boost::optional< lsTextDocumentSyncKind> change ; + // Will save notifications are sent to the server. + boost::optional<bool> willSave; + // Will save wait until requests are sent to the server. + boost::optional<bool> willSaveWaitUntil; + // Save notifications are sent to the server. + boost::optional<lsSaveOptions> save; + + MAKE_SWAP_METHOD(lsTextDocumentSyncOptions, + openClose, + change, + willSave, + willSaveWaitUntil, + save); +}; +MAKE_REFLECT_STRUCT(lsTextDocumentSyncOptions, + openClose, + change, + willSave, + willSaveWaitUntil, + save); + +struct SynchronizationCapabilities { + // Whether text document synchronization supports dynamic registration. + boost::optional<bool> dynamicRegistration; + + // The client supports sending will save notifications. + boost::optional<bool> willSave; + + // The client supports sending a will save request and + // waits for a response providing text edits which will + // be applied to the document before it is saved. + boost::optional<bool> willSaveWaitUntil; + + // The client supports did save notifications. + boost::optional<bool> didSave; + + MAKE_SWAP_METHOD(SynchronizationCapabilities, + dynamicRegistration, + willSave, + willSaveWaitUntil, + didSave); +}; +MAKE_REFLECT_STRUCT(SynchronizationCapabilities, + dynamicRegistration, + willSave, + willSaveWaitUntil, + didSave); + +struct CompletionItemKindCapabilities +{ + boost::optional<std::vector<lsCompletionItemKind> >valueSet; + MAKE_SWAP_METHOD(CompletionItemKindCapabilities, valueSet); +}; +MAKE_REFLECT_STRUCT(CompletionItemKindCapabilities, valueSet); + +struct CompletionItemCapabilities { + // Client supports snippets as insert text. + // + // A snippet can define tab stops and placeholders with `$1`, `$2` + // and `${3:foo}`. `$0` defines the final tab stop, it defaults to + // the end of the snippet. Placeholders with equal identifiers are linked, + // that is typing in one will update others too. + boost::optional<bool> snippetSupport; + + // Client supports commit characters on a completion item. + + boost::optional<bool> commitCharactersSupport; + + + // Client supports the following content formats for the documentation + // property. The order describes the preferred format of the client. + + boost::optional< std::vector<std::string> > documentationFormat; + + // Client supports the deprecated property on a completion item. + + boost::optional<bool> deprecatedSupport; + + // + // Client supports the preselect property on a completion item. + // + boost::optional<bool> preselectSupport; + + MAKE_SWAP_METHOD(CompletionItemCapabilities, + snippetSupport, + commitCharactersSupport, + documentationFormat, + deprecatedSupport, preselectSupport); +}; +MAKE_REFLECT_STRUCT(CompletionItemCapabilities, + snippetSupport, + commitCharactersSupport, + documentationFormat, + deprecatedSupport, preselectSupport); + + +// + // Capabilities specific to the `textDocument/completion` + // +struct CompletionCapabilities { + // Whether completion supports dynamic registration. + boost::optional<bool> dynamicRegistration; + + + + // The client supports the following `CompletionItem` specific + // capabilities. + boost::optional<CompletionItemCapabilities> completionItem; + + // + // The client supports the following `CompletionItemKind` specific + // capabilities. + // + boost::optional<CompletionItemKindCapabilities> completionItemKind; + + // + // The client supports sending additional context information for a + // `textDocument/completion` request. + // + boost::optional<bool> contextSupport; + + + MAKE_SWAP_METHOD(CompletionCapabilities, + dynamicRegistration, + completionItem, completionItemKind); +}; + +MAKE_REFLECT_STRUCT(CompletionCapabilities, + dynamicRegistration, + completionItem , completionItemKind); + + +struct HoverCapabilities:public DynamicRegistrationCapabilities +{ + // + // Client supports the following content formats for the content + // property. The order describes the preferred format of the client. + // + // See {@link MarkupKind} for allowed values. + // + boost::optional<std::vector<std::string>> contentFormat; + + MAKE_SWAP_METHOD(HoverCapabilities, dynamicRegistration, contentFormat); +}; +MAKE_REFLECT_STRUCT(HoverCapabilities, dynamicRegistration, contentFormat); + +// + // Client capabilities specific to parameter information. + // +struct ParameterInformationCapabilities { + // + // The client supports processing label offsets instead of a + // simple label string. + // + // Since 3.14.0 + // + boost::optional<bool> labelOffsetSupport; + + MAKE_SWAP_METHOD(ParameterInformationCapabilities, labelOffsetSupport); +}; +MAKE_REFLECT_STRUCT(ParameterInformationCapabilities, labelOffsetSupport) + + +struct SignatureInformationCapabilities { + // + // Client supports the following content formats for the documentation + // property. The order describes the preferred format of the client. + // + // See {@link MarkupKind} for allowed values. + // + std::vector<std::string> documentationFormat; + + // + // Client capabilities specific to parameter information. + // + ParameterInformationCapabilities parameterInformation; + + MAKE_SWAP_METHOD(SignatureInformationCapabilities, documentationFormat, parameterInformation) +}; +MAKE_REFLECT_STRUCT(SignatureInformationCapabilities,documentationFormat, parameterInformation) + +struct SignatureHelpCapabilities :public DynamicRegistrationCapabilities +{ + // + // The client supports the following `SignatureInformation` + // specific properties. + // + boost::optional< SignatureInformationCapabilities > signatureInformation; + + MAKE_SWAP_METHOD(SignatureHelpCapabilities, dynamicRegistration, signatureInformation) +}; +MAKE_REFLECT_STRUCT(SignatureHelpCapabilities, dynamicRegistration, signatureInformation) + +struct DocumentSymbolCapabilities :public DynamicRegistrationCapabilities { + // + // Specific capabilities for the `SymbolKind`. + // + boost::optional<SymbolKindCapabilities> symbolKind; + + // + // The client support hierarchical document symbols. + // + boost::optional<bool> hierarchicalDocumentSymbolSupport; + + MAKE_SWAP_METHOD(DocumentSymbolCapabilities, dynamicRegistration, symbolKind, hierarchicalDocumentSymbolSupport) +}; +MAKE_REFLECT_STRUCT(DocumentSymbolCapabilities, dynamicRegistration, symbolKind, hierarchicalDocumentSymbolSupport) + +struct DeclarationCapabilities:public DynamicRegistrationCapabilities{ + // + // The client supports additional metadata in the form of declaration links. + // + boost::optional<bool>linkSupport; + + MAKE_SWAP_METHOD(DeclarationCapabilities, dynamicRegistration, linkSupport); +}; +MAKE_REFLECT_STRUCT(DeclarationCapabilities, dynamicRegistration, linkSupport) + + +struct CodeActionKindCapabilities +{ + // + // The code action kind values the client supports. When this + // property exists the client also guarantees that it will + // handle values outside its set gracefully and falls back + // to a default value when unknown. + // + // See {@link CodeActionKind} for allowed values. + // + boost::optional< std::vector< std::string> >valueSet; + + MAKE_SWAP_METHOD(CodeActionKindCapabilities, valueSet) +}; +MAKE_REFLECT_STRUCT(CodeActionKindCapabilities,valueSet) + +struct CodeActionLiteralSupportCapabilities +{ + boost::optional<CodeActionKindCapabilities> codeActionKind; + + MAKE_SWAP_METHOD(CodeActionLiteralSupportCapabilities, codeActionKind) +}; +MAKE_REFLECT_STRUCT(CodeActionLiteralSupportCapabilities, codeActionKind) + +struct CodeActionCapabilities:public DynamicRegistrationCapabilities{ + // + // The client support code action literals as a valid + // response of the `textDocument/codeAction` request. + // + boost::optional<CodeActionLiteralSupportCapabilities> codeActionLiteralSupport; + + MAKE_SWAP_METHOD(CodeActionCapabilities, dynamicRegistration, codeActionLiteralSupport) +}; +MAKE_REFLECT_STRUCT(CodeActionCapabilities,dynamicRegistration,codeActionLiteralSupport) + +struct RenameCapabilities :public DynamicRegistrationCapabilities { + // + // The client support code action literals as a valid + // response of the `textDocument/codeAction` request. + // + boost::optional<bool> prepareSupport; + + MAKE_SWAP_METHOD(RenameCapabilities, dynamicRegistration, prepareSupport) +}; +MAKE_REFLECT_STRUCT(RenameCapabilities, dynamicRegistration, prepareSupport) + +struct DiagnosticsTagSupport { + /** + * The tags supported by the client. + */ + std::vector<DiagnosticTag> valueSet; + MAKE_SWAP_METHOD(DiagnosticsTagSupport, valueSet) +}; +MAKE_REFLECT_STRUCT(DiagnosticsTagSupport, valueSet) + +struct PublishDiagnosticsClientCapabilities :public DynamicRegistrationCapabilities { + /** + * The client support code action literals as a valid + * response of the `textDocument/codeAction` request. + */ + boost::optional<bool> relatedInformation; + + /** + * Client supports the tag property to provide meta data about a diagnostic. + * Clients supporting tags have to handle unknown tags gracefully. + * + * This property had been added and implemented as boolean before it was + * added to the specification as {@link DiagnosticsTagSupport}. In order to + * keep this implementation compatible with intermediate clients (including + * vscode-language-client < 6.0.0) we add an either type here. + * + * Since 3.15 + */ + boost::optional < std::pair<boost::optional<bool>, boost::optional<DiagnosticsTagSupport> > > tagSupport; + + /** + * Whether the client interprets the version property of the + * `textDocument/publishDiagnostics` notification's parameter. + * + * Since 3.15.0 + */ + boost::optional<bool> versionSupport; + + /** + * Client supports a codeDescription property + * + * @since 3.16.0 + */ + boost::optional<bool> codeDescriptionSupport ; + + /** + * Whether code action supports the `data` property which is + * preserved between a `textDocument/publishDiagnostics` and + * `textDocument/codeAction` request. + * + * @since 3.16.0 + */ + boost::optional<bool> dataSupport ; + + + MAKE_SWAP_METHOD(PublishDiagnosticsClientCapabilities, dynamicRegistration, relatedInformation, tagSupport,versionSupport,codeDescriptionSupport,dataSupport) +}; +MAKE_REFLECT_STRUCT(PublishDiagnosticsClientCapabilities, dynamicRegistration, relatedInformation, tagSupport, versionSupport, codeDescriptionSupport, dataSupport) + + +struct FoldingRangeCapabilities :public DynamicRegistrationCapabilities { + // + // The maximum number of folding ranges that the client prefers to receive per document. The value serves as a + // hint, servers are free to follow the limit. + // + boost::optional<int> rangeLimit; + + // + // If set, the client signals that it only supports folding complete lines. If set, client will + // ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange. + // + boost::optional<bool> lineFoldingOnly; + MAKE_SWAP_METHOD(FoldingRangeCapabilities, dynamicRegistration, rangeLimit, lineFoldingOnly) +}; +MAKE_REFLECT_STRUCT(FoldingRangeCapabilities, dynamicRegistration, rangeLimit,lineFoldingOnly) + + +struct SemanticHighlightingCapabilities :public DynamicRegistrationCapabilities { + // + // The client support code action literals as a valid + // response of the `textDocument/codeAction` request. + // + boost::optional<bool> semanticHighlighting; + + MAKE_SWAP_METHOD(SemanticHighlightingCapabilities, dynamicRegistration, semanticHighlighting) +}; +MAKE_REFLECT_STRUCT(SemanticHighlightingCapabilities, dynamicRegistration, semanticHighlighting) + +struct SemanticTokensClientCapabilitiesRequestsFull { + + // + // The client will send the `textDocument/semanticTokens/full/delta` request if + // the server provides a corresponding handler. + // + bool delta = false; + MAKE_SWAP_METHOD(SemanticTokensClientCapabilitiesRequestsFull, delta) +}; +MAKE_REFLECT_STRUCT(SemanticTokensClientCapabilitiesRequestsFull, delta) + +struct SemanticTokensClientCapabilities : public DynamicRegistrationCapabilities +{ + //export TokenFormat = 'relative'; + struct lsRequests + { + // + // The client will send the `textDocument/semanticTokens/range` request + // if the server provides a corresponding handler. + // + boost::optional<std::pair< boost::optional<bool>, + boost::optional<SemanticTokensClientCapabilitiesRequestsFull>>> range; + // + // The client will send the `textDocument/semanticTokens/full` request + // if the server provides a corresponding handler. + // + boost::optional<std::pair< boost::optional<bool>, boost::optional<lsp::Any>>> full; + MAKE_SWAP_METHOD(lsRequests, range, full) + }; + + lsRequests requests; + // + // The token types that the client supports. + // + std::vector<std::string> tokenTypes; + + // + // The token modifiers that the client supports. + // + std::vector<std::string> tokenModifiers; + // + // The formats the clients supports. + // + std::vector<std::string> formats; + // + // Whether the client supports tokens that can overlap each other. + // + boost::optional < bool >overlappingTokenSupport; + + // + // Whether the client supports tokens that can span multiple lines. + // + boost::optional < bool > multilineTokenSupport; + + MAKE_SWAP_METHOD(SemanticTokensClientCapabilities, dynamicRegistration,requests, tokenTypes, tokenModifiers, + formats, overlappingTokenSupport, multilineTokenSupport) + +}; +MAKE_REFLECT_STRUCT(SemanticTokensClientCapabilities::lsRequests, range,full) +MAKE_REFLECT_STRUCT(SemanticTokensClientCapabilities, dynamicRegistration, requests, tokenTypes, tokenModifiers, + formats, overlappingTokenSupport, multilineTokenSupport) + +// Text document specific client capabilities. +struct lsTextDocumentClientCapabilities { + + SynchronizationCapabilities synchronization; + + + // Capabilities specific to the `textDocument/completion` + boost::optional<CompletionCapabilities> completion; + + + + // Capabilities specific to the `textDocument/hover` + boost::optional<HoverCapabilities> hover; + + // Capabilities specific to the `textDocument/signatureHelp` + boost::optional<SignatureHelpCapabilities> signatureHelp; + + // Capabilities specific to the `textDocument/references` + boost::optional<DynamicRegistrationCapabilities> references; + + + + + + // Capabilities specific to the `textDocument/documentHighlight` + boost::optional<DynamicRegistrationCapabilities> documentHighlight; + + // Capabilities specific to the `textDocument/documentSymbol` + boost::optional<DocumentSymbolCapabilities> documentSymbol; + + // Capabilities specific to the `textDocument/formatting` + boost::optional<DynamicRegistrationCapabilities> formatting; + + // Capabilities specific to the `textDocument/rangeFormatting` + boost::optional<DynamicRegistrationCapabilities> rangeFormatting; + + // Capabilities specific to the `textDocument/onTypeFormatting` + boost::optional<DynamicRegistrationCapabilities> onTypeFormatting; + + + // + // Capabilities specific to the `textDocument/declaration` + // + // Since 3.14.0 + // + boost::optional< DeclarationCapabilities> declaration; + + + typedef DeclarationCapabilities DefinitionCapabilities; + // Capabilities specific to the `textDocument/definition` + boost::optional<DefinitionCapabilities> definition; + + + + // +// Capabilities specific to the `textDocument/typeDefinition` +// +// Since 3.6.0 +// + typedef DeclarationCapabilities TypeDefinitionCapabilities; + boost::optional<TypeDefinitionCapabilities> typeDefinition; + + + typedef DeclarationCapabilities ImplementationCapabilities; + // Capabilities specific to the `textDocument/implementation` + boost::optional<ImplementationCapabilities> implementation; + + + // Capabilities specific to the `textDocument/codeAction` + boost::optional<CodeActionCapabilities> codeAction; + + + // Capabilities specific to the `textDocument/codeLens` + boost::optional<DynamicRegistrationCapabilities> codeLens; + + // Capabilities specific to the `textDocument/documentLink` + boost::optional<DynamicRegistrationCapabilities> documentLink; + + // + // Capabilities specific to the `textDocument/documentColor` and the + // `textDocument/colorPresentation` request. + // + // Since 3.6.0 + // + boost::optional<DynamicRegistrationCapabilities> colorProvider; + + // Capabilities specific to the `textDocument/rename` + boost::optional<RenameCapabilities> rename; + +// +// Capabilities specific to `textDocument/publishDiagnostics`. +// + boost::optional<PublishDiagnosticsClientCapabilities> publishDiagnostics; + + // +// Capabilities specific to `textDocument/foldingRange` requests. +// +// Since 3.10.0 +// + boost::optional< FoldingRangeCapabilities > foldingRange; + + + // + // Capabilities specific to {@code textDocument/semanticHighlighting}. + // + boost::optional< SemanticHighlightingCapabilities > semanticHighlightingCapabilities; + + // + // Capabilities specific to {@code textDocument/typeHierarchy}. + // + boost::optional< DynamicRegistrationCapabilities > typeHierarchyCapabilities; + + + + // +// Capabilities specific to `textDocument/selectionRange` requests +// + + boost::optional< DynamicRegistrationCapabilities > selectionRange; + + // + // Capabilities specific to the `textDocument/linkedEditingRange` request. + // + // @since 3.16.0 + // + boost::optional< DynamicRegistrationCapabilities > linkedEditingRange; + + // + // Capabilities specific to the various call hierarchy requests. + // + // @since 3.16.0 + // + boost::optional< DynamicRegistrationCapabilities > callHierarchy; + + // + // Capabilities specific to the various semantic token requests. + // + // @since 3.16.0 + // + boost::optional< SemanticTokensClientCapabilities > semanticTokens; + + // + // Capabilities specific to the `textDocument/moniker` request. + // + // @since 3.16.0 + // + boost::optional< DynamicRegistrationCapabilities > moniker; + + MAKE_SWAP_METHOD(lsTextDocumentClientCapabilities, + synchronization, + completion, + hover, + signatureHelp, + implementation, + references, + documentHighlight, + documentSymbol, + formatting, + rangeFormatting, + onTypeFormatting, + declaration, + definition, typeDefinition, implementation, + codeAction, + codeLens, + documentLink, colorProvider, + rename, publishDiagnostics, foldingRange, + semanticHighlightingCapabilities, typeHierarchyCapabilities, + callHierarchy, selectionRange , linkedEditingRange, semanticTokens, moniker) +}; + + +MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, + synchronization, + completion, + hover, + signatureHelp, + implementation, + references, + documentHighlight, + documentSymbol, + formatting, + rangeFormatting, + onTypeFormatting, + declaration, + definition, typeDefinition, implementation, + codeAction, + codeLens, + documentLink, colorProvider, + rename, publishDiagnostics, foldingRange, + semanticHighlightingCapabilities, typeHierarchyCapabilities, + callHierarchy, selectionRange, linkedEditingRange, semanticTokens, moniker) diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h new file mode 100644 index 0000000000..dd37a1af2f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h @@ -0,0 +1,256 @@ +#pragma once +#include "LibLsp/lsp/method_type.h" + + +#include <stdexcept> + +#include "LibLsp/JsonRpc/message.h" +#include "LibLsp/lsp/lsDocumentUri.h" +#include "LibLsp/lsp/lsAny.h" +#include "LibLsp/lsp/extention/jdtls/searchSymbols.h" + +/** + * Capabilities specific to `WorkspaceEdit`s + */ + +//New in version 3.13: ResourceOperationKind and FailureHandlingKind and the client capability workspace.workspaceEdit. +//resourceOperations as well as workspace.workspaceEdit.failureHandling. + +//The capabilities of a workspace edit has evolved over the time. +//Clients can describe their support using the following client capability : + +struct lschangeAnnotationSupport +{ + /** + * Whether the client groups edits with equal labels into tree nodes, + * for instance all edits labelled with "Changes in Strings" would + * be a tree node. + */ + boost::optional<bool> groupsOnLabel; + MAKE_SWAP_METHOD(lschangeAnnotationSupport, groupsOnLabel) +}; +MAKE_REFLECT_STRUCT(lschangeAnnotationSupport, groupsOnLabel) + +struct WorkspaceEditCapabilities { + /** + * The client supports versioned document changes in `WorkspaceEdit`s + */ + boost::optional<bool> documentChanges; + + /** + * The client supports resource changes + * in `WorkspaceEdit`s. + * + * @deprecated Since LSP introduces resource operations, use {link #resourceOperations} + */ + + boost::optional<bool> resourceChanges; + + /** + * The resource operations the client supports. Clients should at least + * support 'create', 'rename' and 'delete' files and folders. + * + * @since 3.13.0 + */ + boost::optional< std::vector<std::string> > resourceOperations; + + /** + * The failure handling strategy of a client if applying the workspace edit + * fails. + * + * See {@link FailureHandlingKind} for allowed values. + */ + boost::optional<std::string > failureHandling; + + /** + * Whether the client normalizes line endings to the client specific + * setting. + * If set to `true` the client will normalize line ending characters + * in a workspace edit to the client specific new line character(s). + * + * @since 3.16.0 + */ + boost::optional<bool> normalizesLineEndings;; + + /** + * Whether the client in general supports change annotations on text edits, + * create file, rename file and delete file changes. + * + * @since 3.16.0 + */ + boost::optional<lschangeAnnotationSupport> changeAnnotationSupport; + + MAKE_SWAP_METHOD(WorkspaceEditCapabilities, documentChanges, resourceChanges, resourceOperations, failureHandling, normalizesLineEndings, changeAnnotationSupport) + +}; +MAKE_REFLECT_STRUCT(WorkspaceEditCapabilities,documentChanges, resourceChanges, resourceOperations, failureHandling, normalizesLineEndings, changeAnnotationSupport) + + +struct DynamicRegistrationCapabilities { + // Did foo notification supports dynamic registration. + boost::optional<bool> dynamicRegistration; + + MAKE_SWAP_METHOD(DynamicRegistrationCapabilities, + dynamicRegistration); +}; + +MAKE_REFLECT_STRUCT(DynamicRegistrationCapabilities, + dynamicRegistration); + + + +// Workspace specific client capabilities. +struct SymbolKindCapabilities +{ + boost::optional< std::vector<lsSymbolKind> > valueSet; + + MAKE_SWAP_METHOD(SymbolKindCapabilities, valueSet) + + +}; +MAKE_REFLECT_STRUCT(SymbolKindCapabilities, valueSet) + + + + +struct SymbolCapabilities :public DynamicRegistrationCapabilities { + /** + * Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. + */ + boost::optional<SymbolKindCapabilities> symbolKind; + + MAKE_SWAP_METHOD(SymbolCapabilities, + symbolKind, dynamicRegistration) +}; +MAKE_REFLECT_STRUCT(SymbolCapabilities, + symbolKind, dynamicRegistration) + + +struct lsFileOperations +{ + /** + * Whether the client supports dynamic registration for file + * requests/notifications. + */ + boost::optional<bool> dynamicRegistration ; + + /** + * The client has support for sending didCreateFiles notifications. + */ + boost::optional<bool>didCreate ; + + /** + * The client has support for sending willCreateFiles requests. + */ + boost::optional<bool>willCreate ; + + /** + * The client has support for sending didRenameFiles notifications. + */ + boost::optional<bool>didRename ; + + /** + * The client has support for sending willRenameFiles requests. + */ + boost::optional<bool>willRename ; + + /** + * The client has support for sending didDeleteFiles notifications. + */ + boost::optional<bool>didDelete ; + + /** + * The client has support for sending willDeleteFiles requests. + */ + boost::optional<bool> willDelete ; + MAKE_SWAP_METHOD(lsFileOperations, dynamicRegistration, didCreate, willCreate, + didRename, willRename, didDelete, willDelete) +}; +MAKE_REFLECT_STRUCT(lsFileOperations, dynamicRegistration, didCreate, willCreate, + didRename, willRename, didDelete, willDelete) + +struct lsWorkspaceClientCapabilites { + // The client supports applying batch edits to the workspace. + boost::optional<bool> applyEdit; + + + + // Capabilities specific to `WorkspaceEdit`s + boost::optional<WorkspaceEditCapabilities> workspaceEdit; + + + + // Capabilities specific to the `workspace/didChangeConfiguration` + // notification. + boost::optional<DynamicRegistrationCapabilities> didChangeConfiguration; + + // Capabilities specific to the `workspace/didChangeWatchedFiles` + // notification. + boost::optional<DynamicRegistrationCapabilities> didChangeWatchedFiles; + + // Capabilities specific to the `workspace/symbol` request. + boost::optional<SymbolCapabilities> symbol; + + // Capabilities specific to the `workspace/executeCommand` request. + boost::optional<DynamicRegistrationCapabilities> executeCommand; + + + /** + * The client has support for workspace folders. + * + * Since 3.6.0 + */ + boost::optional<bool> workspaceFolders; + + /** + * The client supports `workspace/configuration` requests. + * + * Since 3.6.0 + */ + boost::optional<bool> configuration; + + + /** + * Capabilities specific to the semantic token requests scoped to the + * workspace. + * + * @since 3.16.0 + */ + boost::optional<DynamicRegistrationCapabilities> semanticTokens ; + + /** + * Capabilities specific to the code lens requests scoped to the + * workspace. + * + * @since 3.16.0 + */ + boost::optional<DynamicRegistrationCapabilities> codeLens ; + + /** + * The client has support for file requests/notifications. + * + * @since 3.16.0 + */ + boost::optional<lsFileOperations> fileOperations; + + MAKE_SWAP_METHOD(lsWorkspaceClientCapabilites, + applyEdit, + workspaceEdit, + didChangeConfiguration, + didChangeWatchedFiles, + symbol,executeCommand, workspaceFolders, + configuration, semanticTokens, codeLens, fileOperations) +}; + +MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites, + applyEdit, + workspaceEdit, + didChangeConfiguration, + didChangeWatchedFiles, + symbol, + executeCommand,workspaceFolders, + configuration, semanticTokens, codeLens, fileOperations) + + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/progress.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/progress.h new file mode 100644 index 0000000000..01cb18d68d --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/progress.h @@ -0,0 +1,16 @@ +#pragma once + +#include "LibLsp/JsonRpc/NotificationInMessage.h" +#include "LibLsp/lsp/lsAny.h" +//The base protocol offers also support to report progress in a generic fashion. +//This mechanism can be used to report any kind of progress including work done +//progress(usually used to report progress in the user interface using a progress bar) +//and partial result progress to support streaming of results. +struct ProgressParams +{ + std::pair<boost::optional<std::string> , boost::optional<int> > token; + lsp::Any value; + MAKE_SWAP_METHOD(ProgressParams, token, value) +}; +MAKE_REFLECT_STRUCT(ProgressParams, token, value) +DEFINE_NOTIFICATION_TYPE(Notify_Progress, ProgressParams, "$/progress"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/shutdown.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/shutdown.h new file mode 100644 index 0000000000..5366ff89d6 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/general/shutdown.h @@ -0,0 +1,15 @@ +#pragma once + + +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" + +/** + * The shutdown request is sent from the client to the server. It asks the + * server to shutdown, but to not exit (otherwise the response might not be + * delivered correctly to the client). There is a separate exit notification + * that asks the server to exit. + */ + +DEFINE_REQUEST_RESPONSE_TYPE(td_shutdown, boost::optional<JsonNull>, boost::optional<lsp::Any>, "shutdown"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/language/language.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/language/language.h new file mode 100644 index 0000000000..b4c7829e95 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/language/language.h @@ -0,0 +1,170 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/NotificationInMessage.h" + +#include "LibLsp/lsp/lsDocumentUri.h" +#include "LibLsp/lsp/lsCommand.h" + +#ifdef _WIN32 +#include <ppltasks.h> +#endif + +struct StatusReport { + + std::string ToString() const + { + std::string info; + info += "type:" + type + "\n"; + info += "message:" + message + "\n"; + return info; + } + /** + * The message type. See { + * + */ + + std::string type; + /** + * The actual message + * + */ + + std::string message; + MAKE_SWAP_METHOD(StatusReport, type, message); +}; +MAKE_REFLECT_STRUCT(StatusReport, type, message); + +/** + * The show message notification is sent from a server to a client to ask + * the client to display a particular message in the user interface. + */ +DEFINE_NOTIFICATION_TYPE(lang_status, StatusReport, "language/status"); + + +enum class MessageType { + + /** + * An error message. + */ + Error=(1), + + /** + * A warning message. + */ + Warning=(2), + + /** + * An information message. + */ + Info=(3), + + /** + * A log message. + */ + Log=(4) +}; +MAKE_REFLECT_TYPE_PROXY(MessageType); + + +struct ActionableNotification { + + + + /** + * The message type. See { + * + */ + + MessageType severity; + /** + * The actual message + * + */ + + std::string message; + + /** + * Optional data + * + */ + + boost::optional<lsp::Any> data; + + + /** + * Optional commands + * + */ + + std::vector<lsCommandWithAny> commands; + + MAKE_SWAP_METHOD(ActionableNotification, severity, message, data, commands) +}; +MAKE_REFLECT_STRUCT(ActionableNotification, severity, message, data, commands) + + +/** + * The actionable notification is sent from a server to a client to ask the + * client to display a particular message in the user interface, and possible + * commands to execute. The commands must be implemented on the client side. + */ +DEFINE_NOTIFICATION_TYPE(lang_actionableNotification, ActionableNotification, "language/actionableNotification"); + + + +struct ProgressReport { + std::string ToString() const; + + std::string id; + + + std::string task; + + + std::string subTask; + + + std::string status; + + int totalWork = 0; + + + int workDone = 0; + + + bool complete = false; + MAKE_SWAP_METHOD(ProgressReport, id, task, subTask, status, workDone, complete); +}; + + +MAKE_REFLECT_STRUCT(ProgressReport, id, task, subTask, status, workDone, complete); + +/** + * The progress report notification is sent from a server to be handled by the + * client. + */ +DEFINE_NOTIFICATION_TYPE(lang_progressReport, ProgressReport, "language/progressReport"); + +enum EventType { + /** + * classpath updated event. + */ + ClasspathUpdated = (100), + + /** + * projects imported event. + */ + ProjectsImported = (200) +}; + +struct EventNotification +{ + int eventType; + lsp::Any data; + std::string ToString() const; + MAKE_SWAP_METHOD(EventNotification, eventType, data) +}; +MAKE_REFLECT_STRUCT(EventNotification, eventType, data); + +DEFINE_NOTIFICATION_TYPE(lang_eventNotification, EventNotification, "language/eventNotification");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/location_type.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/location_type.h new file mode 100644 index 0000000000..14e130f571 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/location_type.h @@ -0,0 +1,63 @@ +#pragma once + +#include "lsDocumentUri.h" +#include "lsRange.h" +//Represents a location inside a resource, such as a line inside a text file. +struct lsLocation { + lsLocation(); + lsLocation(lsDocumentUri uri, lsRange range); + + bool operator==(const lsLocation& other) const; + bool operator<(const lsLocation& o) const; + + lsDocumentUri uri; + lsRange range; + MAKE_SWAP_METHOD(lsLocation, uri, range) +}; +MAKE_REFLECT_STRUCT(lsLocation, uri, range) + + + +struct LinkLocation :public lsLocation +{ + std::string displayName; + std::string kind; + MAKE_REFLECT_STRUCT(LinkLocation, uri, range, displayName, kind) +}; +MAKE_REFLECT_STRUCT(LinkLocation, uri, range, displayName,kind) + +//Represents a link between a sourceand a target location. +struct LocationLink +{ + /** + * Span of the origin of this link. + * + * Used as the underlined span for mouse interaction. Defaults to the word range at + * the mouse position. + */ + boost::optional<lsRange> originSelectionRange; + + /** + * The target resource identifier of this link. + */ + + lsDocumentUri targetUri; + + /** + * The full target range of this link. If the target for example is a symbol then target range is the + * range enclosing this symbol not including leading/trailing whitespace but everything else + * like comments. This information is typically used to highlight the range in the editor. + */ + + lsRange targetRange; + + /** + * The range that should be selected and revealed when this link is being followed, e.g the name of a function. + * Must be contained by the the `targetRange`. See also `DocumentSymbol#range` + */ + + lsRange targetSelectionRange; + + MAKE_SWAP_METHOD(LocationLink, originSelectionRange, targetUri, targetRange, targetSelectionRange); +}; +MAKE_REFLECT_STRUCT(LocationLink, originSelectionRange, targetUri, targetRange, targetSelectionRange);
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lru_cache.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lru_cache.h new file mode 100644 index 0000000000..f33bc5627a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lru_cache.h @@ -0,0 +1,151 @@ +#pragma once + +#include <algorithm> +#include <cassert> +#include <limits> +#include <memory> +#include <vector> + +// Cache that evicts old entries which have not been used recently. Implemented +// using array/linear search so this works well for small array sizes. +template <typename TKey, typename TValue> +struct LruCache { + explicit LruCache(int max_entries); + + // Fetches an entry for |key|. If it does not exist, |allocator| will be + // invoked to create one. + template <typename TAllocator> + TValue Get(const TKey& key, TAllocator allocator); + // Returns true if there is an entry for |key|. + bool Has(const TKey& key); + // Fetches the entry for |filename| and updates it's usage so it is less + // likely to be evicted. + bool TryGet(const TKey& key, TValue* dest); + // TryGetEntry, except the entry is removed from the cache. + bool TryTake(const TKey& key, TValue* dest); + // Inserts an entry. Evicts the oldest unused entry if there is no space. + void Insert(const TKey& key, const TValue& value); + + // Call |func| on existing entries. If |func| returns false iteration + // terminates early. + template <typename TFunc> + void IterateValues(TFunc func); + + // Empties the cache + void Clear(void); + + private: + // There is a global score counter, when we access an element we increase + // its score to the current global value, so it has the highest overall + // score. This means that the oldest/least recently accessed value has the + // lowest score. + // + // There is a bit of special logic to handle score overlow. + struct Entry { + uint32_t score = 0; + TKey key; + TValue value; + bool operator<(const Entry& other) const { return score < other.score; } + }; + + void IncrementScore(); + + std::vector<Entry> entries_; + int max_entries_ = 1; + uint32_t next_score_ = 0; +}; + +template <typename TKey, typename TValue> +LruCache<TKey, TValue>::LruCache(int max_entries) : max_entries_(max_entries) { + assert(max_entries > 0); +} + +template <typename TKey, typename TValue> +template <typename TAllocator> +TValue LruCache<TKey, TValue>::Get(const TKey& key, TAllocator allocator) { + for (Entry& entry : entries_) { + if (entry.key == key) + return entry.value; + } + + auto result = allocator(); + Insert(key, result); + return result; +} + +template <typename TKey, typename TValue> +bool LruCache<TKey, TValue>::Has(const TKey& key) { + for (Entry& entry : entries_) { + if (entry.key == key) + return true; + } + return false; +} + +template <typename TKey, typename TValue> +bool LruCache<TKey, TValue>::TryGet(const TKey& key, TValue* dest) { + // Assign new score. + for (Entry& entry : entries_) { + if (entry.key == key) { + entry.score = next_score_; + IncrementScore(); + if (dest) + *dest = entry.value; + return true; + } + } + + return false; +} + +template <typename TKey, typename TValue> +bool LruCache<TKey, TValue>::TryTake(const TKey& key, TValue* dest) { + for (size_t i = 0; i < entries_.size(); ++i) { + if (entries_[i].key == key) { + if (dest) + *dest = entries_[i].value; + entries_.erase(entries_.begin() + i); + return true; + } + } + + return false; +} + +template <typename TKey, typename TValue> +void LruCache<TKey, TValue>::Insert(const TKey& key, const TValue& value) { + if ((int)entries_.size() >= max_entries_) + entries_.erase(std::min_element(entries_.begin(), entries_.end())); + + Entry entry; + entry.score = next_score_; + IncrementScore(); + entry.key = key; + entry.value = value; + entries_.push_back(entry); +} + +template <typename TKey, typename TValue> +template <typename TFunc> +void LruCache<TKey, TValue>::IterateValues(TFunc func) { + for (Entry& entry : entries_) { + if (!func(entry.value)) + break; + } +} + +template <typename TKey, typename TValue> +void LruCache<TKey, TValue>::IncrementScore() { + // Overflow. + if (++next_score_ == 0) { + std::sort(entries_.begin(), entries_.end()); + for (Entry& entry : entries_) + entry.score = next_score_++; + } +} + +template <typename TKey, typename TValue> +void LruCache<TKey, TValue>::Clear(void) { + entries_.clear(); + next_score_ = 0; +} diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsAny.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsAny.h new file mode 100644 index 0000000000..3335aa86dc --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsAny.h @@ -0,0 +1,159 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include <string> +#include "LibLsp/JsonRpc/message.h" +namespace lsp +{ + struct Any + { + //! Type of JSON value + enum Type { + kUnKnown=-1, + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number + }; + + + + template <typename T> + bool Get(T& value); + + template <typename T> + void Set(T& value); + + int GuessType(); + int GetType(); + + void Set(std::unique_ptr<LspMessage> value); + + void SetJsonString(std::string&& _data, Type _type); + + void SetJsonString(const std::string& _data, Type _type); + + const std::string& Data()const + { + return data; + } + + void swap(Any& arg) noexcept; + + /* + *Example for GetFromMap + struct A{ + std::string visitor; + bool verbose; + } + REFLECT_MAP_TO_STRUCT(A,visitor,verbose) + + std::string data = "{\"visitor\":\"default\",\"verbose\":\"true\"}; + lsp:Any any; + any.SetJsonString(data, static_cast<lsp::Any::Type>(-1)); + A a_object; + any.GetFromMap(a_object); + */ + template <typename T> + bool GetFromMap(T& value); + + + template <typename T> + bool GetForMapHelper(T& value); + bool GetForMapHelper(std::string& value); + bool GetForMapHelper(boost::optional<std::string>& value); + private: + std::unique_ptr<Reader> GetReader(); + std::unique_ptr<Writer> GetWriter() const; + void SetData(std::unique_ptr<Writer>&); + + std::string data; + int jsonType = kUnKnown; + + }; + +}; + + +extern void Reflect(Reader& visitor, lsp::Any& value); +extern void Reflect(Writer& visitor, lsp::Any& value); + +template <typename T> +void ReflectMember(std::map < std::string, lsp::Any>& visitor, const char* name, T& value) { + + auto it = visitor.find(name); + if (it != visitor.end()) + { + it->second.GetForMapHelper(value); + } +} +template <typename T> +void ReflectMember(std::map < std::string, std::string>& visitor, const char* name, T& value) { + + auto it = visitor.find(name); + if (it != visitor.end()) + { + lsp::Any any; + any.SetJsonString(it->second, static_cast<lsp::Any::Type>(-1)); + any.Get(value); + } +} + +#define REFLECT_MAP_TO_STRUCT(type, ...) \ + template <typename TVisitor> \ + void ReflectMap(TVisitor& visitor, type& value) { \ + MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \ + } + + +namespace lsp +{ + template <typename T> + bool Any::Get(T& value) + { + const auto visitor = GetReader(); + Reflect(*visitor, value); + return true; + } + + template <typename T> + void Any::Set(T& value) + { + auto visitor = GetWriter(); + Reflect(*visitor, value); + SetData(visitor); + } + + template <typename T> + bool Any::GetFromMap(T& value) + { + const auto visitor = GetReader(); + std::map < std::string, lsp::Any> _temp; + Reflect(*visitor, _temp); + ReflectMap(_temp, value); + return true; + } + + template <typename T> + bool Any::GetForMapHelper(T& value) + { + jsonType = GetType(); + if (jsonType == kStringType) + { + auto copy = data; + copy.erase(copy.find_last_not_of('"') + 1); + copy.erase(0, copy.find_first_not_of('"')); + lsp::Any any; + any.SetJsonString(copy, kUnKnown); + any.Get(value); + } + else + { + Get(value); + } + return true; + } +} diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsCodeAction.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsCodeAction.h new file mode 100644 index 0000000000..06a14f1540 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsCodeAction.h @@ -0,0 +1,58 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" + + + +#include <string> +#include <vector> +#include "lsPosition.h" +#include "lsWorkspaceEdit.h" +#include "lsp_diagnostic.h" +#include "lsCommand.h" + +struct CodeAction +{ + /** + * A short, human-readable, title for this code action. + */ + + std::string title; + + /** + * The kind of the code action. + * + * Used to filter code actions. + */ + boost::optional < std::string> kind; + + /** + * The diagnostics that this code action resolves. + */ + boost::optional < std::vector<lsDiagnostic>> diagnostics; + + /** + * The workspace edit this code action performs. + */ + boost::optional < lsWorkspaceEdit >edit; + + /** + * A command this code action executes. If a code action + * provides a edit and a command, first the edit is + * executed and then the command. + */ + boost::optional< lsCommandWithAny > command; + + MAKE_SWAP_METHOD(CodeAction, title, kind, diagnostics, edit, command) +}; +MAKE_REFLECT_STRUCT(CodeAction, title, kind, diagnostics, edit, command) +struct TextDocumentCodeAction + +{ + + typedef std::pair<boost::optional<lsCommandWithAny>, boost::optional<CodeAction> > Either; + +}; + + +extern void Reflect(Reader& visitor, TextDocumentCodeAction::Either& value);
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsCommand.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsCommand.h new file mode 100644 index 0000000000..94307f1479 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsCommand.h @@ -0,0 +1,44 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" + + + +#include <string> +#include <vector> +#include "lsAny.h" +// +//Represents a reference to a command.Provides a title which will be used to represent a command in the UI. +//Commands are identified by a string identifier. +//The recommended way to handle commands is to implement their execution on the server side +//if the clientand server provides the corresponding capabilities.Alternatively the tool +//extension code could handle the command.The protocol currently doesn¡¯t specify a set of well - known commands. +template <typename AnyArray> +struct lsCommand { + // Title of the command (ie, 'save') + std::string title; + // Actual command identifier. + std::string command; + // Arguments to run the command with. + // **NOTE** This must be serialized as an array. Use + // MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY. + boost::optional<AnyArray> arguments; + + void swap(lsCommand<AnyArray>& arg) noexcept + { + title.swap(arg.title); + command.swap(arg.command); + arguments.swap(arg.arguments); + } +}; +template <typename TVisitor, typename T> +void Reflect(TVisitor& visitor, lsCommand<T>& value) { + REFLECT_MEMBER_START(); + REFLECT_MEMBER(title); + REFLECT_MEMBER(command); + REFLECT_MEMBER(arguments); + REFLECT_MEMBER_END(); +} + + +using lsCommandWithAny = lsCommand< std::vector<lsp::Any>>; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsDocumentUri.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsDocumentUri.h new file mode 100644 index 0000000000..5d24f59e3a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsDocumentUri.h @@ -0,0 +1,26 @@ +#pragma once +#include "LibLsp/JsonRpc/serializer.h" +#include <string> +struct lsDocumentUri { + static lsDocumentUri FromPath(const AbsolutePath& path); + + lsDocumentUri(); + + lsDocumentUri(const AbsolutePath& path); + lsDocumentUri(const lsDocumentUri& other);; + bool operator==(const lsDocumentUri& other) const; + bool operator==(const std::string& other) const; + void SetPath(const AbsolutePath& path); + std::string GetRawPath() const; + AbsolutePath GetAbsolutePath() const; + + + std::string raw_uri_; + void swap(lsDocumentUri& arg) noexcept + { + raw_uri_.swap(arg.raw_uri_); + } +}; +extern void Reflect(Writer& visitor, lsDocumentUri& value); +extern void Reflect(Reader& visitor, lsDocumentUri& value); +extern std::string make_file_scheme_uri(const std::string& absolute_path); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsFormattingOptions.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsFormattingOptions.h new file mode 100644 index 0000000000..a92df9b077 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsFormattingOptions.h @@ -0,0 +1,43 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" + +struct lsFormattingOptions { + struct KeyData { + boost::optional<bool> _boolean; + boost::optional<int32_t> _integer; + boost::optional<std::string> _string; + }; + + // Size of a tab in spaces. + int tabSize =4; + // Prefer spaces over tabs. + bool insertSpaces = true; + + /** + * Trim trailing whitespace on a line. + * + * @since 3.15.0 + */ + boost::optional<bool> trimTrailingWhitespace; + + /** + * Insert a newline character at the end of the file if one does not exist. + * + * @since 3.15.0 + */ + boost::optional<bool> insertFinalNewline; + + /** + * Trim all newlines after the final newline at the end of the file. + * + * @since 3.15.0 + */ + boost::optional<bool> trimFinalNewlines; + boost::optional<KeyData> key; + MAKE_SWAP_METHOD(lsFormattingOptions, tabSize, insertSpaces, trimTrailingWhitespace, insertFinalNewline, trimFinalNewlines, key) +}; +MAKE_REFLECT_STRUCT(lsFormattingOptions, tabSize, insertSpaces, trimTrailingWhitespace, insertFinalNewline, trimFinalNewlines, key); + +extern void Reflect(Reader& visitor, lsFormattingOptions::KeyData& value); +extern void Reflect(Writer& visitor, lsFormattingOptions::KeyData& value);
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsMarkedString.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsMarkedString.h new file mode 100644 index 0000000000..9191aa66d1 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsMarkedString.h @@ -0,0 +1,45 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" + +#include <string> +#include <vector> + + +// MarkedString can be used to render human readable text. It is either a +// markdown string or a code-block that provides a language and a code snippet. +// The language identifier is sematically equal to the optional language +// identifier in fenced code blocks in GitHub issues. See +// https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting +// +// The pair of a language and a value is an equivalent to markdown: +// ```${language} +// ${value} +// ``` +// +// Note that markdown strings will be sanitized - that means html will be +// escaped. +struct lsMarkedString { + boost::optional<std::string> language; + std::string value; +}; + +struct MarkupContent { + /** + * The type of the Markup. + */ + + std::string kind; + + /** + * The content itself. + */ + + std::string value; + + MAKE_SWAP_METHOD(MarkupContent, kind, value); +}; +MAKE_REFLECT_STRUCT(MarkupContent,kind,value); + +void Reflect(Writer& visitor, lsMarkedString& value); +void Reflect(Reader& visitor, lsMarkedString& value); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsPosition.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsPosition.h new file mode 100644 index 0000000000..8c2106e16e --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsPosition.h @@ -0,0 +1,40 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" + + + +#include <string> +#include <vector> + +//Position in a text document expressed as zero - based line and zero - based character offset. +//A position is between two characters like an ¡®insert¡¯ cursor in a editor.Special values like +//for example - 1 to denote the end of a line are not supported. +struct lsPosition { + lsPosition(); + lsPosition(int line, int character); + + bool operator==(const lsPosition& other) const; + bool operator<(const lsPosition& other) const; + + std::string ToString() const; + + /** + * Line position in a document (zero-based). + */ + // Note: these are 0-based. + unsigned line = 0; + /** + * Character offset on a line in a document (zero-based). Assuming that + * the line is represented as a string, the `character` value represents + * the gap between the `character` and `character + 1`. + * + * If the character value is greater than the line length it defaults back + * to the line length. + */ + unsigned character = 0; + static const lsPosition kZeroPosition; + + MAKE_SWAP_METHOD(lsPosition, line, character) +}; +MAKE_REFLECT_STRUCT(lsPosition, line, character);
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsRange.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsRange.h new file mode 100644 index 0000000000..6cc01e37a7 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsRange.h @@ -0,0 +1,32 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" + + + +#include <string> +#include <vector> +#include "lsPosition.h" +//A range in a text document expressed as(zero - based) startand end positions. +//A range is comparable to a selection in an editor.Therefore the end position is exclusive. +//If you want to specify a range that contains a line including the line ending character(s) +//then use an end position denoting the start of the next line. +struct lsRange { + lsRange(); + lsRange(lsPosition start, lsPosition end); + + bool operator==(const lsRange& other) const; + bool operator<(const lsRange& other) const; + /** + * The range's start position. + */ + lsPosition start; + /** + * The range's end position. + */ + lsPosition end; + std::string ToString()const; + MAKE_SWAP_METHOD(lsRange, start, end) +}; + +MAKE_REFLECT_STRUCT(lsRange, start, end)
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsResponseError.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsResponseError.h new file mode 100644 index 0000000000..6146d6188f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsResponseError.h @@ -0,0 +1,117 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include <sstream> +#include "LibLsp/lsp/lsAny.h" + +enum class lsErrorCodes:int32_t { + // Defined by JSON RPC + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603, + + /** + * This is the start range of JSON RPC reserved error codes. + * It doesn't denote a real error code. No LSP error codes should + * be defined between the start and end range. For backwards + * compatibility the `ServerNotInitialized` and the `UnknownErrorCode` + * are left in the range. + * + * @since 3.16.0 + */ + jsonrpcReservedErrorRangeStart = -32099, + /** @deprecated use jsonrpcReservedErrorRangeStart */ + serverErrorStart = jsonrpcReservedErrorRangeStart, + + /** + * This is the start range of JSON RPC reserved error codes. + * It doesn't denote a real error code. + * + * @since 3.16.0 + */ + jsonrpcReservedErrorRangeEnd = -32000, + /** @deprecated use jsonrpcReservedErrorRangeEnd */ + serverErrorEnd = jsonrpcReservedErrorRangeEnd, + + /** + * Error code indicating that a server received a notification or + * request before the server has received the `initialize` request. + */ + ServerNotInitialized = -32002, + UnknownErrorCode = -32001, + + /** + * This is the start range of LSP reserved error codes. + * It doesn't denote a real error code. + * + * @since 3.16.0 + */ + lspReservedErrorRangeStart= -32899, + + /** + * The server cancelled the request. This error code should + * only be used for requests that explicitly support being + * server cancellable. + * + * @since 3.17.0 + */ + ServerCancelled = -32802, + + /** + * The server detected that the content of a document got + * modified outside normal conditions. A server should + * NOT send this error code if it detects a content change + * in it unprocessed messages. The result even computed + * on an older state might still be useful for the client. + * + * If a client decides that a result is not of any use anymore + * the client should cancel the request. + */ + ContentModified = -32801, + + /** + * The client has canceled a request and a server as detected + * the cancel. + */ + RequestCancelled = -32800, + + /** + * This is the end range of LSP reserved error codes. + * It doesn't denote a real error code. + * + * @since 3.16.0 + */ + lspReservedErrorRangeEnd = -32800, + + + +}; +MAKE_REFLECT_TYPE_PROXY(lsErrorCodes); +struct lsResponseError { + lsResponseError(): code(lsErrorCodes::UnknownErrorCode) + { + } + + /** + * A number indicating the error type that occurred. + */ + lsErrorCodes code; + // Short description. + /** + * A string providing a short description of the error. + */ + std::string message; + + /** + * A primitive or structured value that contains additional + * information about the error. Can be omitted. + */ + boost::optional<lsp::Any> data; + std::string ToString(); + void Write(Writer& visitor); + + MAKE_SWAP_METHOD(lsResponseError, code, message, data) +}; +MAKE_REFLECT_STRUCT(lsResponseError, code, message, data)
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentEdit.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentEdit.h new file mode 100644 index 0000000000..0bab8bc3d8 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentEdit.h @@ -0,0 +1,24 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include <vector> +#include "LibLsp/JsonRpc/message.h" +#include "lsVersionedTextDocumentIdentifier.h" +#include "lsTextEdit.h" + + +struct lsTextDocumentEdit { + // The text document to change. + lsVersionedTextDocumentIdentifier textDocument; + + /** + * The edits to be applied. + * + * @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the + * client capability `workspace.workspaceEdit.changeAnnotationSupport` + */ + // The edits to be applied. + std::vector< lsAnnotatedTextEdit > edits; + MAKE_SWAP_METHOD(lsTextDocumentEdit, textDocument, edits); +}; +MAKE_REFLECT_STRUCT(lsTextDocumentEdit, textDocument, edits);
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentIdentifier.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentIdentifier.h new file mode 100644 index 0000000000..bb316eae5a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentIdentifier.h @@ -0,0 +1,14 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include "lsDocumentUri.h" +//Text documents are identified using a URI.On the protocol level, +//URIs are passed as strings.The corresponding JSON structure looks like this: +struct lsTextDocumentIdentifier { + /** + * The text document's URI. + */ + lsDocumentUri uri; + MAKE_SWAP_METHOD(lsTextDocumentIdentifier, uri) +}; +MAKE_REFLECT_STRUCT(lsTextDocumentIdentifier, uri)
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentItem.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentItem.h new file mode 100644 index 0000000000..4d9b4ccc9f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentItem.h @@ -0,0 +1,26 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include <string> +#include <vector> +#include "lsDocumentUri.h" + +//An item to transfer a text document from the client to the server. +struct lsTextDocumentItem { + // The text document's URI. + lsDocumentUri uri; + + // The text document's language identifier. + std::string languageId; + + // The version number of this document (it will strictly increase after each + // change, including undo/redo). + int version = 0; + + // The content of the opened text document. + std::string text; + + MAKE_SWAP_METHOD(lsTextDocumentItem, uri, languageId, version, text) +}; + +MAKE_REFLECT_STRUCT(lsTextDocumentItem, uri, languageId, version, text)
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentPositionParams.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentPositionParams.h new file mode 100644 index 0000000000..52d291351e --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextDocumentPositionParams.h @@ -0,0 +1,26 @@ +#pragma once + +#include "LibLsp/JsonRpc/message.h" + +#include "lsTextDocumentIdentifier.h" +#include "lsPosition.h" + +/** + * A parameter literal used in requests to pass a text document and a position inside that document. + */ +struct lsTextDocumentPositionParams { + // The text document. + lsTextDocumentIdentifier textDocument; + + // The position inside the text document. + lsPosition position; + + /** + * Legacy property to support protocol version 1.0 requests. + */ + boost::optional<lsDocumentUri> uri; + + MAKE_SWAP_METHOD(lsTextDocumentPositionParams, textDocument, position, uri); + +}; +MAKE_REFLECT_STRUCT(lsTextDocumentPositionParams, textDocument, position, uri); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextEdit.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextEdit.h new file mode 100644 index 0000000000..8785e0dcbc --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsTextEdit.h @@ -0,0 +1,87 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" + + + +#include <string> +#include "lsRange.h" + + +//Since 3.16.0 there is also the concept of an annotated text edit which supports to add an annotation to a text edit. +//The annotation can add information describing the change to the text edit. +/** + * Additional information that describes document changes. + * + * @since 3.16.0 + */ +struct lsChangeAnnotation +{ + /** + * A human-readable string describing the actual change. The string + * is rendered prominent in the user interface. + */ + std::string label; + + /** + * A flag which indicates that user confirmation is needed + * before applying the change. + */ + boost::optional<bool> needsConfirmation; + + /** + * A human-readable string which is rendered less prominent in + * the user interface. + */ + boost::optional < std::string > description; + MAKE_REFLECT_STRUCT(lsChangeAnnotation, label, needsConfirmation, description) +}; +MAKE_REFLECT_STRUCT(lsChangeAnnotation, label, needsConfirmation, description) + + +//Usually clients provide options to group the changes along the annotations they are associated with. +//To support this in the protocol an edit or resource operation refers to a change annotation +//using an identifier and not the change annotation literal directly.This allows servers to use +//the identical annotation across multiple edits or resource operations which then allows clients +//to group the operations under that change annotation.The actual change annotations together with +//their identifers are managed by the workspace edit via the new property changeAnnotations. + + + +/** + * An identifier referring to a change annotation managed by a workspace + * edit. + * + * @since 3.16.0. + */ +using lsChangeAnnotationIdentifier = std::string; +/** + * A special text edit with an additional change annotation. + * + * @since 3.16.0. + */ + + +//A textual edit applicable to a text document. +struct lsTextEdit { + // The range of the text document to be manipulated. To insert + // text into a document create a range where start === end. + lsRange range; + + // The string to be inserted. For delete operations use an + // empty string. + std::string newText; + + /** + * The actual annotation identifier. + */ + boost::optional<lsChangeAnnotationIdentifier> annotationId; + + + bool operator==(const lsTextEdit& that); + std::string ToString() const; + MAKE_SWAP_METHOD(lsTextEdit, range, newText, annotationId) +}; +MAKE_REFLECT_STRUCT(lsTextEdit, range, newText, annotationId) + +using lsAnnotatedTextEdit = lsTextEdit; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsVersionedTextDocumentIdentifier.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsVersionedTextDocumentIdentifier.h new file mode 100644 index 0000000000..8a858053b1 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsVersionedTextDocumentIdentifier.h @@ -0,0 +1,32 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" + +#include "LibLsp/JsonRpc/message.h" +#include "LibLsp/lsp/lsDocumentUri.h" +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" + +struct lsVersionedTextDocumentIdentifier +{ + lsDocumentUri uri; + // The version number of this document. number | null + boost::optional<int> version; + + lsTextDocumentIdentifier AsTextDocumentIdentifier() const; + + MAKE_SWAP_METHOD(lsVersionedTextDocumentIdentifier, uri, version) +}; +MAKE_REFLECT_STRUCT(lsVersionedTextDocumentIdentifier, uri, version) + +/** + * The version number of this document. If an optional versioned text document + * identifier is sent from the server to the client and the file is not + * open in the editor (the server has not received an open notification + * before) the server can send `null` to indicate that the version is + * known and the content on disk is the master (as specified with document + * content ownership). + * + * The version number of a document will increase after each change, + * including undo/redo. The number doesn't need to be consecutive. + */ +using lsOptionalVersionedTextDocumentIdentifier = lsVersionedTextDocumentIdentifier;
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsWorkspaceEdit.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsWorkspaceEdit.h new file mode 100644 index 0000000000..c7fb73930a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsWorkspaceEdit.h @@ -0,0 +1,57 @@ +#pragma once + +#include "LibLsp/JsonRpc/serializer.h" +#include <vector> +#include "lsTextDocumentEdit.h" +#include "LibLsp/lsp/ResourceOperation.h" +#include "lsAny.h" + +//A workspace edit represents changes to many resources managed in the workspace. +//The edit should either provide changes or documentChanges. +//If the client can handle versioned document edits and if documentChanges are present, the latter are preferred over changes. + +//Since version 3.13.0 a workspace edit can contain resource operations(create, delete or rename files and folders) as well. +//If resource operations are present clients need to execute the operations in the order in which they are provided. +//So a workspace edit for example can consist of the following two changes : (1) create file a.txt and (2) a text document edit which insert text into file a. +//txt.An invalid sequence(e.g. (1) delete file a.txt and (2) insert text into file a.txt) will cause failure of the operation. +//How the client recovers from the failure is described by the client capability : workspace.workspaceEdit.failureHandling + + + +struct lsChangeAnnotations +{ + lsChangeAnnotation id; + MAKE_SWAP_METHOD(lsChangeAnnotations, id) +}; +MAKE_REFLECT_STRUCT(lsChangeAnnotations, id) +struct lsWorkspaceEdit { + // Holds changes to existing resources. + // changes ? : { [uri:string]: TextEdit[]; }; + // std::unordered_map<lsDocumentUri, std::vector<lsTextEdit>> changes; + + // An array of `TextDocumentEdit`s to express changes to specific a specific + // version of a text document. Whether a client supports versioned document + // edits is expressed via `WorkspaceClientCapabilites.versionedWorkspaceEdit`. + // + boost::optional< std::map<std::string, std::vector<lsTextEdit> > > changes; + typedef std::pair < boost::optional<lsTextDocumentEdit>, boost::optional<lsp::Any> > Either; + + boost::optional < std::vector< Either > > documentChanges; + /** + * A map of change annotations that can be referenced in + * `AnnotatedTextEdit`s or create, rename and delete file / folder + * operations. + * + * Whether clients honor this property depends on the client capability + * `workspace.changeAnnotationSupport`. + * + * @since 3.16.0 + */ + boost::optional< lsChangeAnnotations > changeAnnotations; + + MAKE_SWAP_METHOD(lsWorkspaceEdit, changes, documentChanges, changeAnnotations) +}; +MAKE_REFLECT_STRUCT(lsWorkspaceEdit, changes, documentChanges, changeAnnotations) + +extern void Reflect(Reader& visitor, lsWorkspaceEdit::Either& value); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsp_code_action.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsp_code_action.h new file mode 100644 index 0000000000..37acc6ca61 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsp_code_action.h @@ -0,0 +1,64 @@ +#pragma once + + +#include "location_type.h" +#include "lsDocumentUri.h" +#include "lsTextEdit.h" +#include "lsPosition.h" + +// codeAction +struct CommandArgs { + lsDocumentUri textDocumentUri; + std::vector<lsTextEdit> edits; +}; +MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(CommandArgs, textDocumentUri, edits); +inline void Reflect(Reader& visitor, CommandArgs& value) { + int i = 0; + visitor.IterArray([&](Reader& visitor) { + switch (i++) { + case 0: + Reflect(visitor, value.textDocumentUri); + break; + case 1: + Reflect(visitor, value.edits); + break; + + } + }); +} + +// codeLens +struct lsCodeLensUserData {}; +MAKE_REFLECT_EMPTY_STRUCT(lsCodeLensUserData); + +struct lsCodeLensCommandArguments { + lsDocumentUri uri; + lsPosition position; + std::vector<lsLocation> locations; +}; + +// FIXME Don't use array in vscode-cquery +inline void Reflect(Writer& visitor, lsCodeLensCommandArguments& value) { + visitor.StartArray(3); + Reflect(visitor, value.uri); + Reflect(visitor, value.position); + Reflect(visitor, value.locations); + visitor.EndArray(); +} + +inline void Reflect(Reader& visitor, lsCodeLensCommandArguments& value) { + int i = 0; + visitor.IterArray([&](Reader& visitor) { + switch (i++) { + case 0: + Reflect(visitor, value.uri); + break; + case 1: + Reflect(visitor, value.position); + break; + case 2: + Reflect(visitor, value.locations); + break; + } + }); +} diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsp_completion.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsp_completion.h new file mode 100644 index 0000000000..250699a44a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsp_completion.h @@ -0,0 +1,224 @@ +#pragma once +#include "lsTextEdit.h" +#include "lsMarkedString.h" +#include "lsCommand.h" + + +// The kind of a completion entry. +enum class lsCompletionItemKind { + Text = 1, + Method = 2, + Function = 3, + Constructor = 4, + Field = 5, + Variable = 6, + Class = 7, + Interface = 8, + Module = 9, + Property = 10, + Unit = 11, + Value = 12, + Enum = 13, + Keyword = 14, + Snippet = 15, + Color = 16, + File = 17, + Reference = 18, + Folder = 19, + EnumMember = 20, + Constant = 21, + Struct = 22, + Event = 23, + Operator = 24, + TypeParameter = 25, +}; +MAKE_REFLECT_TYPE_PROXY(lsCompletionItemKind); + + + +// Defines whether the insert text in a completion item should be interpreted as +// plain text or a snippet. +enum class lsInsertTextFormat { + // The primary text to be inserted is treated as a plain string. + PlainText = 1, + + // The primary text to be inserted is treated as a snippet. + // + // A snippet can define tab stops and placeholders with `$1`, `$2` + // and `${3:foo}`. `$0` defines the final tab stop, it defaults to + // the end of the snippet. Placeholders with equal identifiers are linked, + // that is typing in one will update others too. + // + // See also: + // https://github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md + Snippet = 2 +}; +MAKE_REFLECT_TYPE_PROXY(lsInsertTextFormat); + +namespace lsp +{ + std::string ToString(lsCompletionItemKind); + std::string ToString(lsInsertTextFormat); +} +/** + * The Completion request is sent from the client to the server to compute completion items at a given cursor position. + * Completion items are presented in the IntelliSense user class. If computing complete completion items is expensive + * servers can additional provide a handler for the resolve completion item request. This request is send when a + * completion item is selected in the user class. + */ +struct lsCompletionItem { + + // The label of this completion item. By default + // also the text that is inserted when selecting + // this completion. + std::string label; + + // The kind of this completion item. Based of the kind + // an icon is chosen by the editor. + boost::optional<lsCompletionItemKind> kind ; + + // A human-readable string with additional information + // about this item, like type or symbol information. + boost::optional < std::string > detail; + + // A human-readable string that represents a doc-comment. + boost::optional< std::pair<boost::optional< std::string> , boost::optional<MarkupContent> > > documentation; + + + /** + * Indicates if this item is deprecated. + */ + boost::optional< bool >deprecated; + + + /** + * Select this item when showing. + * + * *Note* that only one completion item can be selected and that the + * tool / client decides which item that is. The rule is that the *first + * item of those that match best is selected. + */ + boost::optional< bool > preselect; + + + // Internal information to order candidates. + int relevance = 0; + + // A string that shoud be used when comparing this item + // with other items. When `falsy` the label is used. + boost::optional< std::string > sortText; + + // A string that should be used when filtering a set of + // completion items. When `falsy` the label is used. + boost::optional<std::string> filterText; + + // A string that should be inserted a document when selecting + // this completion. When `falsy` the label is used. + boost::optional<std::string> insertText; + + // The format of the insert text. The format applies to both the `insertText` + // property and the `newText` property of a provided `textEdit`. + boost::optional< lsInsertTextFormat> insertTextFormat ; + + // An edit which is applied to a document when selecting this completion. When + // an edit is provided the value of `insertText` is ignored. + // + // *Note:* The range of the edit must be a single line range and it must + // contain the position at which completion has been requested. + boost::optional<lsTextEdit> textEdit; + + // An boost::optional array of additional text edits that are applied when + // selecting this completion. Edits must not overlap with the main edit + // nor with themselves. + // std::vector<TextEdit> additionalTextEdits; + + // An boost::optional command that is executed *after* inserting this completion. + // *Note* that additional modifications to the current document should be + // described with the additionalTextEdits-property. Command command; + + // An data entry field that is preserved on a completion item between + // a completion and a completion resolve request. + // data ? : any + + // Use this helper to figure out what content the completion item will insert + // into the document, as it could live in either |textEdit|, |insertText|, or + // |label|. + const std::string& InsertedContent() const; + + std::string DisplayText(); + /** + * An boost::optional array of additional text edits that are applied when + * selecting this completion. Edits must not overlap (including the same insert position) + * with the main edit nor with themselves. + * + * Additional text edits should be used to change text unrelated to the current cursor position + * (for example adding an import statement at the top of the file if the completion item will + * insert an unqualified type). + */ + boost::optional<std::vector<lsTextEdit> >additionalTextEdits; + + /** +* An boost::optional set of characters that when pressed while this completion is active will accept it first and +* then type that character. *Note* that all commit characters should have `length=1` and that superfluous +* characters will be ignored. +*/ + boost::optional< std::vector<std::string> > commitCharacters; + + /** +* An boost::optional command that is executed *after* inserting this completion. *Note* that +* additional modifications to the current document should be described with the +* additionalTextEdits-property. +*/ + boost::optional<lsCommandWithAny> command; + + /** +* An data entry field that is preserved on a completion item between a completion and a completion resolve request. +*/ + boost::optional<lsp::Any> data; + std::string ToString(); + MAKE_SWAP_METHOD(lsCompletionItem, + label, + kind, + detail, + documentation, + sortText, + insertText, + filterText, + insertTextFormat, + textEdit, + deprecated, preselect, additionalTextEdits, commitCharacters, + command, data); + +}; + + + +MAKE_REFLECT_STRUCT(lsCompletionItem, + label, + kind, + detail, + documentation, + sortText, + insertText, + filterText, + insertTextFormat, + textEdit, + deprecated, preselect, additionalTextEdits, commitCharacters, + command, data); + + + +struct CompletionList { + // This list it not complete. Further typing should result in recomputing + // this list. + bool isIncomplete = false; + // The completion items. + std::vector<lsCompletionItem> items; + + void swap(CompletionList& arg) noexcept + { + items.swap(arg.items); + std::swap(isIncomplete, arg.isIncomplete); + } +}; +MAKE_REFLECT_STRUCT(CompletionList, isIncomplete, items);
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsp_diagnostic.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsp_diagnostic.h new file mode 100644 index 0000000000..d1b1d1ba78 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/lsp_diagnostic.h @@ -0,0 +1,151 @@ +#pragma once +#include "lsRange.h" +#include "lsTextEdit.h" +#include "lsDocumentUri.h" + +#include "lsResponseError.h" +#include "location_type.h" + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +enum class lsDiagnosticSeverity { + // Reports an error. + Error = 1, + // Reports a warning. + Warning = 2, + // Reports an information. + Information = 3, + // Reports a hint. + Hint = 4 +}; +MAKE_REFLECT_TYPE_PROXY(lsDiagnosticSeverity); + +/** + * The diagnostic tags. + * + * @since 3.15.0 + */ +enum class DiagnosticTag :uint8_t { + + /** + * Unused or unnecessary code. + * + * Clients are allowed to render diagnostics with this tag faded out instead of having + * an error squiggle. + */ + Unnecessary=(1), + + /** + * Deprecated or obsolete code. + * + * Clients are allowed to rendered diagnostics with this tag strike through. + */ + Deprecated=(2), +}; +MAKE_REFLECT_TYPE_PROXY(DiagnosticTag); + + + +/** + * Represents a related message and source code location for a diagnostic. This should be + * used to point to code locations that cause or related to a diagnostics, e.g when duplicating + * a symbol in a scope. + * + * Since 3.7.0 + */ + +struct DiagnosticRelatedInformation { + /** + * The location of this related diagnostic information. + */ + + lsLocation location; + + /** + * The message of this related diagnostic information. + */ + + std::string message; + + MAKE_SWAP_METHOD(DiagnosticRelatedInformation, location, message) +}; +MAKE_REFLECT_STRUCT(DiagnosticRelatedInformation, location, message) +/** + * Structure to capture a description for an error code. + * + * @since 3.16.0 + */ +struct DiagnosticCodeDescription { + /** + * An URI to open with more information about the diagnostic error. + */ + std::string href; + MAKE_SWAP_METHOD(DiagnosticCodeDescription, href) +}; +MAKE_REFLECT_STRUCT(DiagnosticCodeDescription, href) + +//Represents a diagnostic, such as a compiler error or warning.Diagnostic objects are only valid in the scope of a resource. +struct lsDiagnostic { + // The range at which the message applies. + lsRange range; + + // The diagnostic's severity. Can be omitted. If omitted it is up to the + // client to interpret diagnostics as error, warning, info or hint. + boost::optional<lsDiagnosticSeverity> severity; + + // The diagnostic's code. Can be omitted. + boost::optional< std::pair<boost::optional<std::string>, boost::optional<int>> > code; + + boost::optional<DiagnosticCodeDescription> codeDescription; + // A human-readable string describing the source of this + // diagnostic, e.g. 'typescript' or 'super lint'. + boost::optional < std::string >source ; + + // The diagnostic's message. + std::string message; + + // Non-serialized set of fixits. + std::vector<lsTextEdit> fixits_; + + /** + * Additional metadata about the diagnostic. + * + * @since 3.15.0 + */ + boost::optional<std::vector<DiagnosticTag>> tags; + + + /** + * An array of related diagnostic information, e.g. when symbol-names within a scope collide + * all definitions can be marked via this property. + * + * Since 3.7.0 + */ + boost::optional<std::vector<DiagnosticRelatedInformation>> relatedInformation; + + /** + * A data entry field that is preserved between a + * `textDocument/publishDiagnostics` notification and + * `textDocument/codeAction` request. + * + * @since 3.16.0 + */ + boost::optional<lsp::Any> data; + bool operator==(const lsDiagnostic& rhs) const; + bool operator!=(const lsDiagnostic& rhs) const; + + MAKE_SWAP_METHOD(lsDiagnostic, range, severity, code, codeDescription, source, message, tags, data) +}; +MAKE_REFLECT_STRUCT(lsDiagnostic, range, severity, code, codeDescription, source, message, tags, data) + + + +struct Rsp_Error : ResponseError<lsResponseError, Rsp_Error> { + + MAKE_SWAP_METHOD(Rsp_Error, jsonrpc, id, error) +}; +MAKE_REFLECT_STRUCT(Rsp_Error, jsonrpc, id, error) + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/method_type.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/method_type.h new file mode 100644 index 0000000000..dcbb4a851a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/method_type.h @@ -0,0 +1,7 @@ +#pragma once +#include <string> + +using MethodType = const char* const; + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/out_list.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/out_list.h new file mode 100644 index 0000000000..36c4aa78ba --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/out_list.h @@ -0,0 +1,22 @@ +#pragma once + + +#include "location_type.h" + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + + + +//DEFINE_RESPONCE_TYPE(Rsp_FindLinkLocationList, std::vector<LinkLocation>); +//DEFINE_RESPONCE_TYPE(Rsp_LocationList, std::vector<lsLocation>); + + +namespace LocationListEither{ + + typedef std::pair< boost::optional<std::vector<lsLocation>> , boost::optional<std::vector<LocationLink> > > Either; + +}; +extern void Reflect(Reader& visitor, LocationListEither::Either& value); +//DEFINE_RESPONCE_TYPE(Rsp_LocationListEither, LocationListEither::Either); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/symbol.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/symbol.h new file mode 100644 index 0000000000..57298b8d7f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/symbol.h @@ -0,0 +1,164 @@ +#pragma once +#include "LibLsp/lsp/location_type.h" + + +enum class lsSymbolKind : uint8_t { + Unknown = 0, + + File = 1, + Module = 2, + Namespace = 3, + Package = 4, + Class = 5, + Method = 6, + Property = 7, + Field = 8, + Constructor = 9, + Enum = 10, + Interface = 11, + Function = 12, + Variable = 13, + Constant = 14, + String = 15, + Number = 16, + Boolean = 17, + Array = 18, + Object = 19, + Key = 20, + Null = 21, + EnumMember = 22, + Struct = 23, + Event = 24, + Operator = 25, + + // For C++, this is interpreted as "template parameter" (including + // non-type template parameters). + TypeParameter = 26, + + // cquery extensions + // See also https://github.com/Microsoft/language-server-protocol/issues/344 + // for new SymbolKind clang/Index/IndexSymbol.h clang::index::SymbolKind + TypeAlias = 252, + Parameter = 253, + StaticMethod = 254, + Macro = 255, +}; +MAKE_REFLECT_TYPE_PROXY(lsSymbolKind); + +typedef lsSymbolKind SymbolKind; + +// A document highlight kind. +enum class lsDocumentHighlightKind { + // A textual occurrence. + Text = 1, + // Read-access of a symbol, like reading a variable. + Read = 2, + // Write-access of a symbol, like writing to a variable. + Write = 3 +}; +MAKE_REFLECT_TYPE_PROXY(lsDocumentHighlightKind); + +// A document highlight is a range inside a text document which deserves +// special attention. Usually a document highlight is visualized by changing +// the background color of its range. +struct lsDocumentHighlight { + // The range this highlight applies to. + lsRange range; + + // The highlight kind, default is DocumentHighlightKind.Text. + boost::optional<lsDocumentHighlightKind> kind ; + + MAKE_SWAP_METHOD(lsDocumentHighlight, range, kind) +}; +MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind); + +struct lsSymbolInformation { + +/** + * The name of this symbol. + */ + std::string name; + /** + * The kind of this symbol. + */ + lsSymbolKind kind; + /** +* Indicates if this symbol is deprecated. +*/ + boost::optional<bool> deprecated; + /** + * The location of this symbol. The location's range is used by a tool + * to reveal the location in the editor. If the symbol is selected in the + * tool the range's start information is used to position the cursor. So + * the range usually spans more then the actual symbol's name and does + * normally include things like visibility modifiers. + * + * The range doesn't have to denote a node range in the sense of a abstract + * syntax tree. It can therefore not be used to re-construct a hierarchy of + * the symbols. + */ + lsLocation location; + /** + * The name of the symbol containing this symbol. This information is for + * user interface purposes (e.g. to render a qualifier in the user interface + * if necessary). It can't be used to re-infer a hierarchy for the document + * symbols. + */ + boost::optional<std::string> containerName; + + + MAKE_SWAP_METHOD(lsSymbolInformation, name, kind, deprecated, location, containerName); +}; +MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, deprecated, location, containerName); + + +struct lsDocumentSymbol { + /** + * The name of this symbol. + */ + + std::string name; + + /** + * The kind of this symbol. + */ + + lsSymbolKind kind = lsSymbolKind::Unknown; + + /** + * The range enclosing this symbol not including leading/trailing whitespace but everything else + * like comments. This information is typically used to determine if the clients cursor is + * inside the symbol to reveal in the symbol in the UI. + */ + + lsRange range; + + /** + * The range that should be selected and revealed when this symbol is being picked, e.g the name of a function. + * Must be contained by the `range`. + */ + + lsRange selectionRange; + + /** + * More detail for this symbol, e.g the signature of a function. If not provided the + * name is used. + */ + boost::optional< std::string > detail; + + /** + * Indicates if this symbol is deprecated. + */ + boost::optional< bool > deprecated; + + /** + * Children of this symbol, e.g. properties of a class. + */ + boost::optional < std::vector<lsDocumentSymbol> > children; + + //internal use + int flags=0; + + MAKE_SWAP_METHOD(lsDocumentSymbol, name, kind, range, selectionRange, detail, deprecated, children, flags); +}; +MAKE_REFLECT_STRUCT(lsDocumentSymbol, name, kind, range, selectionRange, detail, deprecated, children, flags);
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/SemanticTokens.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/SemanticTokens.h new file mode 100644 index 0000000000..612d186f6f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/SemanticTokens.h @@ -0,0 +1,267 @@ +#pragma once + +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" +#include "LibLsp/lsp/lsVersionedTextDocumentIdentifier.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" +enum class HighlightingKind_clangD { + Variable = 0, + LocalVariable, + Parameter, + Function, + Method, + StaticMethod, + Field, + StaticField, + Class, + Interface, + Enum, + EnumConstant, + Typedef, + Type, + Unknown, + Namespace, + TemplateParameter, + Concept, + Primitive, + Macro, + + // This one is different from the other kinds as it's a line style + // rather than a token style. + InactiveCode, + + LastKind = InactiveCode +}; +std::string toSemanticTokenType(HighlightingKind_clangD kind); + +enum class HighlightingModifier_clangD { + Declaration, + Deprecated, + Deduced, + Readonly, + Static, + Abstract, + DependentName, + DefaultLibrary, + + FunctionScope, + ClassScope, + FileScope, + GlobalScope, + + LastModifier = GlobalScope +}; +std::string toSemanticTokenModifier(HighlightingModifier_clangD modifier); + +enum SemanticTokenType { + ls_namespace=0,// 'namespace', + /** + * Represents a generic type. Acts as a fallback for types which + * can't be mapped to a specific type like class or enum. + */ + ls_type,// 'type', + ls_class,// 'class', + ls_enum,// 'enum', + ls_interface,// 'interface', + ls_struct,// 'struct', + ls_typeParameter,// 'typeParameter', + ls_parameter,// 'parameter', + ls_variable,// 'variable', + ls_property,// 'property', + ls_enumMember,// 'enumMember', + ls_event,// 'event', + ls_function,// 'function', + ls_method,// 'method', + ls_macro,// 'macro', + ls_keyword,// 'keyword', + ls_modifier,// 'modifier', + ls_comment,// 'comment', + ls_string,// 'string', + ls_number,// 'number', + ls_regexp,// 'regexp', + ls_operator,// 'operator' + lastKind = ls_operator +}; +std::string to_string(SemanticTokenType); +unsigned toSemanticTokenType(std::vector<SemanticTokenType>& modifiers); + +enum TokenType_JDT { + PACKAGE_JDT=0, + CLASS_JDT, + INTERFACE_JDT, + ENUM_JDT, + ENUM_MEMBER_JDT, + TYPE_JDT, + TYPE_PARAMETER_JDT, + ANNOTATION_JDT, + ANNOTATION_MEMBER_JDT, + METHOD_JDT, + PROPERTY_JDT, + VARIABLE_JDT, + PARAMETER_JDT +}; +std::string to_string(TokenType_JDT); + +enum SemanticTokenModifier { + ls_declaration=0,// 'declaration', + ls_definition,// 'definition', + ls_readonly,// 'readonly', + ls_static,// 'static', + ls_deprecated,// 'deprecated', + ls_abstract,// 'abstract', + ls_async,// 'async', + ls_modification,// 'modification', + ls_documentation,// 'documentation', + ls_defaultLibrary,// 'defaultLibrary' + LastModifier = ls_defaultLibrary +}; +std::string to_string(SemanticTokenModifier); +unsigned toSemanticTokenModifiers(std::vector<SemanticTokenModifier>&); +/// Specifies a single semantic token in the document. +/// This struct is not part of LSP, which just encodes lists of tokens as +/// arrays of numbers directly. +struct SemanticToken { + /// token line number, relative to the previous token + unsigned deltaLine = 0; + /// token start character, relative to the previous token + /// (relative to 0 or the previous token's start if they are on the same line) + unsigned deltaStart = 0; + /// the length of the token. A token cannot be multiline + unsigned length = 0; + /// will be looked up in `SemanticTokensLegend.tokenTypes` + unsigned tokenType = 0; + /// each set bit will be looked up in `SemanticTokensLegend.tokenModifiers` + unsigned tokenModifiers = 0; +}; +bool operator==(const SemanticToken&, const SemanticToken&); +struct SemanticTokens{ + + /** + * Tokens in a file are represented as an array of integers. The position of each token is expressed relative to + * the token before it, because most tokens remain stable relative to each other when edits are made in a file. + * + * --- + * In short, each token takes 5 integers to represent, so a specific token `i` in the file consists of the following array indices: + * - at index `5*i` - `deltaLine`: token line number, relative to the previous token + * - at index `5*i+1` - `deltaStart`: token start character, relative to the previous token (relative to 0 or the previous token's start if they are on the same line) + * - at index `5*i+2` - `length`: the length of the token. A token cannot be multiline. + * - at index `5*i+3` - `tokenType`: will be looked up in `SemanticTokensLegend.tokenTypes`. We currently ask that `tokenType` < 65536. + * - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticTokensLegend.tokenModifiers` + * + * --- + * ### How to encode tokens + * + * Here is an example for encoding a file with 3 tokens in a uint32 array: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: "property", tokenModifiers: ["private", "static"] }, + * { line: 2, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] }, + * { line: 5, startChar: 2, length: 7, tokenType: "class", tokenModifiers: [] } + * ``` + * + * 1. First of all, a legend must be devised. This legend must be provided up-front and capture all possible token types. + * For this example, we will choose the following legend which must be passed in when registering the provider: + * ``` + * tokenTypes: ['property', 'type', 'class'], + * tokenModifiers: ['private', 'static'] + * ``` + * + * 2. The first transformation step is to encode `tokenType` and `tokenModifiers` as integers using the legend. Token types are looked + * up by index, so a `tokenType` value of `1` means `tokenTypes[1]`. Multiple token modifiers can be set by using bit flags, + * so a `tokenModifier` value of `3` is first viewed as binary `0b00000011`, which means `[tokenModifiers[0], tokenModifiers[1]]` because + * bits 0 and 1 are set. Using this legend, the tokens now are: + * ``` + * { line: 2, startChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { line: 2, startChar: 10, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { line: 5, startChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 3. The next step is to represent each token relative to the previous token in the file. In this case, the second token + * is on the same line as the first token, so the `startChar` of the second token is made relative to the `startChar` + * of the first token, so it will be `10 - 5`. The third token is on a different line than the second token, so the + * `startChar` of the third token will not be altered: + * ``` + * { deltaLine: 2, deltaStartChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 }, + * { deltaLine: 0, deltaStartChar: 5, length: 4, tokenType: 1, tokenModifiers: 0 }, + * { deltaLine: 3, deltaStartChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 } + * ``` + * + * 4. Finally, the last step is to inline each of the 5 fields for a token in a single array, which is a memory friendly representation: + * ``` + * // 1st token, 2nd token, 3rd token + * [ 2,5,3,0,3, 0,5,4,1,0, 3,2,7,2,0 ] + * ``` + */ + std::vector<int32_t> data; + static std::vector<int32_t> encodeTokens(std::vector<SemanticToken>& tokens); + + /** + * An optional result id. If provided and clients support delta updating + * the client will include the result id in the next semantic token request. + * A server can then instead of computing all semantic tokens again simply + * send a delta. + */ + boost::optional<std::string> resultId; + MAKE_SWAP_METHOD(SemanticTokens, data, resultId) +}; +MAKE_REFLECT_STRUCT(SemanticTokens, data, resultId) + +/// Body of textDocument/semanticTokens/full request. +struct SemanticTokensParams { + /// The text document. + lsTextDocumentIdentifier textDocument; + MAKE_REFLECT_STRUCT(SemanticTokensParams, textDocument) +}; +MAKE_REFLECT_STRUCT(SemanticTokensParams, textDocument) + + +/// Body of textDocument/semanticTokens/full/delta request. +/// Requests the changes in semantic tokens since a previous response. +struct SemanticTokensDeltaParams { + /// The text document. + lsTextDocumentIdentifier textDocument; + /** + * The result id of a previous response. The result Id can either point to + * a full response or a delta response depending on what was received last. + */ + std::string previousResultId; + + MAKE_REFLECT_STRUCT(SemanticTokensDeltaParams, textDocument, previousResultId) +}; +MAKE_REFLECT_STRUCT(SemanticTokensDeltaParams, textDocument, previousResultId) + +/// Describes a a replacement of a contiguous range of semanticTokens. +struct SemanticTokensEdit { + // LSP specifies `start` and `deleteCount` which are relative to the array + // encoding of the previous tokens. + // We use token counts instead, and translate when serializing this struct. + unsigned startToken = 0; + unsigned deleteTokens = 0; + std::vector<int32_t> tokens; // encoded as a flat integer array + + MAKE_REFLECT_STRUCT(SemanticTokensEdit, startToken, deleteTokens, tokens) +}; +MAKE_REFLECT_STRUCT(SemanticTokensEdit, startToken, deleteTokens, tokens) + + +/// This models LSP SemanticTokensDelta | SemanticTokens, which is the result of +/// textDocument/semanticTokens/full/delta. +struct SemanticTokensOrDelta { + boost::optional<std::string > resultId; + /// Set if we computed edits relative to a previous set of tokens. + boost::optional< std::vector<SemanticTokensEdit> > edits; + /// Set if we computed a fresh set of tokens. + /// Set if we computed edits relative to a previous set of tokens. + boost::optional<std::vector<int32_t>> tokens; // encoded as integer array + MAKE_REFLECT_STRUCT(SemanticTokensOrDelta, resultId, edits, tokens) +}; +MAKE_REFLECT_STRUCT(SemanticTokensOrDelta, resultId, edits, tokens) + + +struct SemanticTokensLegend { + std::vector<std::string> tokenTypes; + std::vector<std::string> tokenModifiers; + MAKE_REFLECT_STRUCT(SemanticTokensLegend, tokenTypes, tokenModifiers) +}; +MAKE_REFLECT_STRUCT(SemanticTokensLegend, tokenTypes, tokenModifiers) + +DEFINE_REQUEST_RESPONSE_TYPE(td_semanticTokens_full, SemanticTokensParams,boost::optional<SemanticTokens >,"textDocument/semanticTokens/full") +DEFINE_REQUEST_RESPONSE_TYPE(td_semanticTokens_full_delta, SemanticTokensDeltaParams, boost::optional<SemanticTokensOrDelta >, "textDocument/semanticTokens/full/delta")
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/callHierarchy.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/callHierarchy.h new file mode 100644 index 0000000000..a005c182e1 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/callHierarchy.h @@ -0,0 +1,121 @@ +#pragma once + +#include "LibLsp/lsp/lsAny.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/lsp/symbol.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" +#include "LibLsp/lsp/lsRange.h" + +enum class SymbolTag { Deprecated = 1 }; +MAKE_REFLECT_TYPE_PROXY(SymbolTag) + +struct CallHierarchyPrepareParams +{ + lsTextDocumentIdentifier textDocument; + lsPosition position; + + MAKE_SWAP_METHOD(CallHierarchyPrepareParams, + textDocument, + position) +}; +MAKE_REFLECT_STRUCT(CallHierarchyPrepareParams, + textDocument, + position) + + + + /// Represents programming constructs like functions or constructors + /// in the context of call hierarchy. +struct CallHierarchyItem { + /// The name of this item. + std::string name; + + /// The kind of this item. + SymbolKind kind; + + /// Tags for this item. + boost::optional<std::vector<SymbolTag>> tags; + + /// More detaill for this item, e.g. the signature of a function. + boost::optional<std::string> detail; + + /// The resource identifier of this item. + lsDocumentUri uri; + + /** + * The range enclosing this symbol not including leading/trailing whitespace + * but everything else, e.g. comments and code. + */ + lsRange range; + + /** + * The range that should be selected and revealed when this symbol is being + * picked, e.g. the name of a function. Must be contained by the + * [`range`](#CallHierarchyItem.range). + */ + lsRange selectionRange; + + /** + * A data entry field that is preserved between a call hierarchy prepare and + * incoming calls or outgoing calls requests. + */ + boost::optional<lsp::Any> data; + MAKE_SWAP_METHOD(CallHierarchyItem, name, kind, tags, detail, uri, range, selectionRange, data) +}; +MAKE_REFLECT_STRUCT(CallHierarchyItem, name, kind, tags, detail, uri, range, selectionRange, data) + + + +/// The parameter of a `callHierarchy/incomingCalls` request. +struct CallHierarchyIncomingCallsParams { + CallHierarchyItem item; + MAKE_SWAP_METHOD(CallHierarchyIncomingCallsParams,item) +}; +MAKE_REFLECT_STRUCT(CallHierarchyIncomingCallsParams, item) + + +/// Represents an incoming call, e.g. a caller of a method or constructor. +struct CallHierarchyIncomingCall { + /// The item that makes the call. + CallHierarchyItem from; + + /// The range at which the calls appear. + /// This is relative to the caller denoted by `From`. + std::vector<lsRange> fromRanges; + MAKE_SWAP_METHOD(CallHierarchyIncomingCall, from, fromRanges) +}; +MAKE_REFLECT_STRUCT(CallHierarchyIncomingCall, from, fromRanges) + + + + +/// The parameter of a `callHierarchy/outgoingCalls` request. +struct CallHierarchyOutgoingCallsParams { + CallHierarchyItem item; + MAKE_SWAP_METHOD(CallHierarchyOutgoingCallsParams, item) +}; +MAKE_REFLECT_STRUCT(CallHierarchyOutgoingCallsParams, item) + +/// Represents an outgoing call, e.g. calling a getter from a method or +/// a method from a constructor etc. +struct CallHierarchyOutgoingCall { + /// The item that is called. + CallHierarchyItem to; + + /// The range at which this item is called. + /// This is the range relative to the caller, and not `To`. + std::vector<lsRange> fromRanges; + MAKE_SWAP_METHOD(CallHierarchyOutgoingCall, to, fromRanges) +}; +MAKE_REFLECT_STRUCT(CallHierarchyOutgoingCall, to, fromRanges) + + +DEFINE_REQUEST_RESPONSE_TYPE(td_prepareCallHierarchy, CallHierarchyPrepareParams, + boost::optional<std::vector<CallHierarchyItem>>, "textDocument/prepareCallHierarchy") + +DEFINE_REQUEST_RESPONSE_TYPE(td_incomingCalls, CallHierarchyIncomingCallsParams, + boost::optional<std::vector<CallHierarchyIncomingCall>>, "callHierarchy/incomingCalls") + +DEFINE_REQUEST_RESPONSE_TYPE(td_outgoingCalls, CallHierarchyOutgoingCallsParams, + boost::optional<std::vector<CallHierarchyOutgoingCall>>, "callHierarchy/CallHierarchyOutgoingCall")
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/code_action.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/code_action.h new file mode 100644 index 0000000000..419fdfbc9b --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/code_action.h @@ -0,0 +1,37 @@ +#pragma once +#include "LibLsp/lsp/method_type.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" +#include "LibLsp/lsp/CodeActionParams.h" + +namespace QuickAssistProcessor { + + extern const char* SPLIT_JOIN_VARIABLE_DECLARATION_ID;//$NON-NLS-1$ + extern const char* CONVERT_FOR_LOOP_ID;// ;// "org.eclipse.jdt.ls.correction.convertForLoop.assist"; //$NON-NLS-1$ + extern const char* ASSIGN_TO_LOCAL_ID ;// "org.eclipse.jdt.ls.correction.assignToLocal.assist"; //$NON-NLS-1$ + extern const char* ASSIGN_TO_FIELD_ID ;// "org.eclipse.jdt.ls.correction.assignToField.assist"; //$NON-NLS-1$ + extern const char* ASSIGN_PARAM_TO_FIELD_ID ;// "org.eclipse.jdt.ls.correction.assignParamToField.assist"; //$NON-NLS-1$ + extern const char* ASSIGN_ALL_PARAMS_TO_NEW_FIELDS_ID ;// "org.eclipse.jdt.ls.correction.assignAllParamsToNewFields.assist"; //$NON-NLS-1$ + extern const char* ADD_BLOCK_ID ;// "org.eclipse.jdt.ls.correction.addBlock.assist"; //$NON-NLS-1$ + extern const char* EXTRACT_LOCAL_ID ;// "org.eclipse.jdt.ls.correction.extractLocal.assist"; //$NON-NLS-1$ + extern const char* EXTRACT_LOCAL_NOT_REPLACE_ID ;// "org.eclipse.jdt.ls.correction.extractLocalNotReplaceOccurrences.assist"; //$NON-NLS-1$ + extern const char* EXTRACT_CONSTANT_ID ;// "org.eclipse.jdt.ls.correction.extractConstant.assist"; //$NON-NLS-1$ + extern const char* INLINE_LOCAL_ID ;// "org.eclipse.jdt.ls.correction.inlineLocal.assist"; //$NON-NLS-1$ + extern const char* CONVERT_LOCAL_TO_FIELD_ID ;// "org.eclipse.jdt.ls.correction.convertLocalToField.assist"; //$NON-NLS-1$ + extern const char* CONVERT_ANONYMOUS_TO_LOCAL_ID ;// "org.eclipse.jdt.ls.correction.convertAnonymousToLocal.assist"; //$NON-NLS-1$ + extern const char* CONVERT_TO_STRING_BUFFER_ID ;// "org.eclipse.jdt.ls.correction.convertToStringBuffer.assist"; //$NON-NLS-1$ + extern const char* CONVERT_TO_MESSAGE_FORMAT_ID ;// "org.eclipse.jdt.ls.correction.convertToMessageFormat.assist"; //$NON-NLS-1$; + extern const char* EXTRACT_METHOD_INPLACE_ID ;// "org.eclipse.jdt.ls.correction.extractMethodInplace.assist"; //$NON-NLS-1$; + + extern const char* CONVERT_ANONYMOUS_CLASS_TO_NESTED_COMMAND ;// "convertAnonymousClassToNestedCommand"; +}; +/** + * The code action request is sent from the client to the server to compute + * commands for a given text document and range. These commands are + * typically code fixes to either fix problems or to beautify/refactor code. + * + * Registration Options: TextDocumentRegistrationOptions + */ + +DEFINE_REQUEST_RESPONSE_TYPE(td_codeAction, lsCodeActionParams, std::vector<lsCommandWithAny>, "textDocument/codeAction"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/code_lens.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/code_lens.h new file mode 100644 index 0000000000..7fd5ae0cf9 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/code_lens.h @@ -0,0 +1,42 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +struct lsDocumentCodeLensParams { + +/** + * The document to request code lens for. + */ + lsTextDocumentIdentifier textDocument; + + MAKE_SWAP_METHOD(lsDocumentCodeLensParams, textDocument); +}; +MAKE_REFLECT_STRUCT(lsDocumentCodeLensParams, textDocument); + + + + +struct lsCodeLens { + // The range in which this code lens is valid. Should only span a single line. + lsRange range; + // The command this code lens represents. + boost::optional<lsCommandWithAny> command; + // A data entry field that is preserved on a code lens item between + // a code lens and a code lens resolve request. + boost::optional< lsp::Any> data; + + MAKE_SWAP_METHOD(lsCodeLens, range, command, data) +}; +MAKE_REFLECT_STRUCT(lsCodeLens, range, command, data) + + + +/** + * The code lens request is sent from the client to the server to compute + * code lenses for a given text document. + * + * Registration Options: CodeLensRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_codeLens, lsDocumentCodeLensParams, std::vector<lsCodeLens>, "textDocument/codeLens") + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/colorPresentation.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/colorPresentation.h new file mode 100644 index 0000000000..22574e3e19 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/colorPresentation.h @@ -0,0 +1,63 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" +#include "LibLsp/lsp/lsRange.h" +#include "documentColor.h" +#include "LibLsp/lsp/lsTextEdit.h" + + +struct ColorPresentationParams { + + /** + * The text document. + */ + lsTextDocumentIdentifier textDocument; + + /** + * The range in the document where this color appers. + */ + + lsRange range; + + /** + * The actual color value for this color range. + */ + + TextDocument::Color color; + MAKE_SWAP_METHOD(ColorPresentationParams, textDocument, range, color) +}; +MAKE_REFLECT_STRUCT(ColorPresentationParams, textDocument, range, color) + + +struct ColorPresentation { + /** + * The label of this color presentation. It will be shown on the color + * picker header. By default this is also the text that is inserted when selecting + * this color presentation. + */ + + std::string label; + + /** + * An edit which is applied to a document when selecting + * this presentation for the color. When `null` the label is used. + */ + lsTextEdit textEdit; + + /** + * An optional array of additional text edits that are applied when + * selecting this color presentation. Edits must not overlap with the main edit nor with themselves. + */ + std::vector<lsTextEdit> additionalTextEdits; + MAKE_SWAP_METHOD(ColorPresentation, label, textEdit, additionalTextEdits) +}; +MAKE_REFLECT_STRUCT(ColorPresentation, label, textEdit, additionalTextEdits) + + + +DEFINE_REQUEST_RESPONSE_TYPE(td_colorPresentation, + ColorPresentationParams, std::vector<ColorPresentation>, "textDocument/colorPresentation")
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/completion.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/completion.h new file mode 100644 index 0000000000..883c5cfe3a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/completion.h @@ -0,0 +1,82 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include <regex> +#include "LibLsp/lsp/lsp_completion.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" + + +// How a completion was triggered +enum class lsCompletionTriggerKind { + // Completion was triggered by typing an identifier (24x7 code + // complete), manual invocation (e.g Ctrl+Space) or via API. + Invoked = 1, + + // Completion was triggered by a trigger character specified by + // the `triggerCharacters` properties of the `CompletionRegistrationOptions`. + TriggerCharacter = 2 +}; +MAKE_REFLECT_TYPE_PROXY(lsCompletionTriggerKind); + + +// Contains additional information about the context in which a completion +// request is triggered. +struct lsCompletionContext { + // How the completion was triggered. + lsCompletionTriggerKind triggerKind = lsCompletionTriggerKind::Invoked; + + // The trigger character (a single character) that has trigger code complete. + // Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter` + boost::optional<std::string> triggerCharacter; + + MAKE_SWAP_METHOD(lsCompletionContext, triggerKind, triggerCharacter); +}; +MAKE_REFLECT_STRUCT(lsCompletionContext, triggerKind, triggerCharacter); + +struct lsCompletionParams : lsTextDocumentPositionParams { + // The completion context. This is only available it the client specifies to + // send this using + // `ClientCapabilities.textDocument.completion.contextSupport === true` + boost::optional<lsCompletionContext> context; + + MAKE_SWAP_METHOD(lsCompletionParams, textDocument, position, context); + +}; +MAKE_REFLECT_STRUCT(lsCompletionParams, textDocument, position, context); + + + + + + + + + +namespace TextDocumentComplete{ + + typedef std::pair< boost::optional<std::vector<lsCompletionItem>>, boost::optional<CompletionList> > Either; + +}; +extern void Reflect(Reader& visitor, TextDocumentComplete::Either& value); + +/** + * The Completion request is sent from the client to the server to compute + * completion items at a given cursor position. Completion items are + * presented in the IntelliSense user interface. If computing complete + * completion items is expensive servers can additional provide a handler + * for the resolve completion item request. This request is sent when a + * completion item is selected in the user interface. + * + * Registration Options: CompletionRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_completion, lsCompletionParams, CompletionList , "textDocument/completion") + + + + + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/declaration_definition.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/declaration_definition.h new file mode 100644 index 0000000000..aa20fce046 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/declaration_definition.h @@ -0,0 +1,29 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" +#include "LibLsp/lsp/out_list.h" + + +/** + * The go to declaration request is sent from the client to the server to resolve + * the declaration location of a symbol at a given text document position. + * + * Registration Options: TextDocumentRegistrationOptions + * + * Since version 3.14.0 + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_declaration, lsTextDocumentPositionParams, LocationListEither::Either, "textDocument/declaration"); + +/** + * The goto definition request is sent from the client to the server to resolve + * the definition location of a symbol at a given text document position. + * + * Registration Options: TextDocumentRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_definition, lsTextDocumentPositionParams, LocationListEither::Either, "textDocument/definition"); + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/didRenameFiles.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/didRenameFiles.h new file mode 100644 index 0000000000..e8a6235a00 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/didRenameFiles.h @@ -0,0 +1,44 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include <string> +#include "LibLsp/lsp/CodeActionParams.h" +#include "LibLsp/lsp/lsWorkspaceEdit.h" + + +class FileRenameEvent { +public: + std::string oldUri; + std::string newUri; + + FileRenameEvent() { + } + + FileRenameEvent(std::string oldUri, std::string newUri) { + this->oldUri = oldUri; + this->newUri = newUri; + } + MAKE_SWAP_METHOD(FileRenameEvent, oldUri, newUri); +}; +MAKE_REFLECT_STRUCT(FileRenameEvent, oldUri, newUri); + +class FileRenameParams { +public: + std::vector <FileRenameEvent> files; + + FileRenameParams() { + } + + FileRenameParams(std::vector<FileRenameEvent>& files) { + this->files = files; + } + MAKE_SWAP_METHOD(FileRenameParams, files); +}; +MAKE_REFLECT_STRUCT(FileRenameParams, files); + + +DEFINE_REQUEST_RESPONSE_TYPE(td_didRenameFiles, FileRenameParams, boost::optional<lsWorkspaceEdit>, "java/didRenameFiles"); + + +DEFINE_REQUEST_RESPONSE_TYPE(td_willRenameFiles, FileRenameParams, boost::optional<lsWorkspaceEdit>, "java/willRenameFiles"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_change.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_change.h new file mode 100644 index 0000000000..0887bf6602 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_change.h @@ -0,0 +1,51 @@ +#pragma once + + +#include "LibLsp/JsonRpc/NotificationInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsVersionedTextDocumentIdentifier.h" +#include "LibLsp/lsp/lsRange.h" +#include "LibLsp/lsp/lsDocumentUri.h" +struct lsTextDocumentContentChangeEvent { + // The range of the document that changed. + boost::optional<lsRange> range; + // The length of the range that got replaced. + boost::optional<int> rangeLength; + // The new text of the range/document. + std::string text; + + MAKE_SWAP_METHOD(lsTextDocumentContentChangeEvent, range, rangeLength, text); +}; +MAKE_REFLECT_STRUCT(lsTextDocumentContentChangeEvent, range, rangeLength, text); + + +struct lsTextDocumentDidChangeParams { + lsVersionedTextDocumentIdentifier textDocument; + std::vector<lsTextDocumentContentChangeEvent> contentChanges; + + /** + * Legacy property to support protocol version 1.0 requests. + */ + + boost::optional<lsDocumentUri> uri; + + void swap(lsTextDocumentDidChangeParams& arg) noexcept + { + uri.swap(arg.uri); + contentChanges.swap(arg.contentChanges); + textDocument.swap(arg.textDocument); + } +}; +MAKE_REFLECT_STRUCT(lsTextDocumentDidChangeParams, + textDocument, + contentChanges, uri); + +/** + * The document change notification is sent from the client to the server to + * signal changes to a text document. + * + * Registration Options: TextDocumentChangeRegistrationOptions + */ +DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentDidChange, lsTextDocumentDidChangeParams, "textDocument/didChange"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_close.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_close.h new file mode 100644 index 0000000000..e2eaa2cfcd --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_close.h @@ -0,0 +1,33 @@ +#pragma once + + + +#include "LibLsp/JsonRpc/NotificationInMessage.h" + + + + +namespace TextDocumentDidClose { + + struct Params { + lsTextDocumentIdentifier textDocument; + void swap(Params& arg) noexcept + { + textDocument.swap(arg.textDocument); + } + + }; + +}; + +MAKE_REFLECT_STRUCT(TextDocumentDidClose::Params, textDocument); + +/** + * The document close notification is sent from the client to the server + * when the document got closed in the client. The document's truth now + * exists where the document's uri points to (e.g. if the document's uri is + * a file uri the truth now exists on disk). + * + * Registration Options: TextDocumentRegistrationOptions + */ +DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentDidClose, TextDocumentDidClose::Params, "textDocument/didClose"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_open.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_open.h new file mode 100644 index 0000000000..7be7a735d6 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_open.h @@ -0,0 +1,39 @@ +#pragma once + + +#include "LibLsp/JsonRpc/NotificationInMessage.h" + +#include "LibLsp/lsp/lsTextDocumentItem.h" + +// Open, view, change, close file +namespace TextDocumentDidOpen { + + struct Params { + lsTextDocumentItem textDocument; + + + + /** + * Legacy property to support protocol version 1.0 requests. + */ + boost::optional<std::string> text; + + MAKE_SWAP_METHOD(TextDocumentDidOpen::Params, textDocument, text); + + }; + +} +MAKE_REFLECT_STRUCT(TextDocumentDidOpen::Params, textDocument, text); + +/** + * The document open notification is sent from the client to the server to + * signal newly opened text documents. The document's truth is now managed + * by the client and the server must not try to read the document's truth + * using the document's uri. + * + * Registration Options: TextDocumentRegistrationOptions + */; + + +DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentDidOpen, TextDocumentDidOpen::Params, "textDocument/didOpen"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_save.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_save.h new file mode 100644 index 0000000000..1ce386c415 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/did_save.h @@ -0,0 +1,31 @@ +#pragma once + + + +#include "LibLsp/JsonRpc/NotificationInMessage.h" + + +namespace TextDocumentDidSave { + + struct Params { + // The document that was saved. + lsTextDocumentIdentifier textDocument; + + // Optional the content when saved. Depends on the includeText value + // when the save notifcation was requested. + boost::optional<std::string> text; + + MAKE_SWAP_METHOD(TextDocumentDidSave::Params, textDocument, text); + }; + +}; +MAKE_REFLECT_STRUCT(TextDocumentDidSave::Params, textDocument, text); + +/** + * The document save notification is sent from the client to the server when + * the document for saved in the client. + * + * Registration Options: TextDocumentSaveRegistrationOptions + */ +DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentDidSave, TextDocumentDidSave::Params, "textDocument/didSave"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/documentColor.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/documentColor.h new file mode 100644 index 0000000000..23a6d08d87 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/documentColor.h @@ -0,0 +1,73 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" +#include "LibLsp/lsp/lsRange.h" +#include <vector> +struct DocumentColorParams { + /** + * The text document. + */ + + lsTextDocumentIdentifier textDocument; + MAKE_SWAP_METHOD(DocumentColorParams, textDocument); +}; +MAKE_REFLECT_STRUCT(DocumentColorParams, textDocument); + +/** + * The document color request is sent from the client to the server to list all color references found in a given text + * document. Along with the range, a color value in RGB is returned. + * + * Clients can use the result to decorate color references in an editor. For example: + * - Color boxes showing the actual color next to the reference + * - Show a color picker when a color reference is edited + * + * Since version 3.6.0 + */ + +namespace TextDocument { + struct Color { + /** + * The red component of this color in the range [0-1]. + */ + double red = 0; + + /** + * The green component of this color in the range [0-1]. + */ + double green = 0; + + /** + * The blue component of this color in the range [0-1]. + */ + double blue = 0; + + /** + * The alpha component of this color in the range [0-1]. + */ + double alpha = 0; + MAKE_SWAP_METHOD(TextDocument::Color, red, green, blue, alpha) + }; +} +MAKE_REFLECT_STRUCT(TextDocument::Color, red, green, blue, alpha) + + +struct ColorInformation { + /** + * The range in the document where this color appers. + */ + + lsRange range; + + /** + * The actual color value for this color range. + */ + + TextDocument::Color color; + MAKE_SWAP_METHOD(ColorInformation, range, color) +}; +MAKE_REFLECT_STRUCT(ColorInformation,range,color) + +DEFINE_REQUEST_RESPONSE_TYPE(td_documentColor, DocumentColorParams,std::vector<ColorInformation>, "textDocument/documentColor");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/document_link.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/document_link.h new file mode 100644 index 0000000000..536a625c4c --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/document_link.h @@ -0,0 +1,44 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + + +namespace TextDocumentDocumentLink { + + struct Params { + // The document to provide document links for. + lsTextDocumentIdentifier textDocument; + MAKE_SWAP_METHOD(Params, textDocument) + }; + +}; +MAKE_REFLECT_STRUCT(TextDocumentDocumentLink::Params, textDocument); + + + + +// A document link is a range in a text document that links to an internal or +// external resource, like another text document or a web site. +struct lsDocumentLink { + // The range this link applies to. + lsRange range; + // The uri this link points to. If missing a resolve request is sent later. + boost::optional<lsDocumentUri> target; + + boost::optional<lsp::Any> data; + + MAKE_SWAP_METHOD(lsDocumentLink, range, target, data) + +}; +MAKE_REFLECT_STRUCT(lsDocumentLink, range, target,data); + + +DEFINE_REQUEST_RESPONSE_TYPE(td_links, TextDocumentDocumentLink::Params, lsDocumentLink, "textDocument/documentLink"); + + +/** + * The document link resolve request is sent from the client to the server to resolve the target of a given document link. + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_linkResolve, std::vector<lsDocumentLink>, lsDocumentLink, "documentLink/resolve"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/document_symbol.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/document_symbol.h new file mode 100644 index 0000000000..8aa6e8b00e --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/document_symbol.h @@ -0,0 +1,55 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/symbol.h" +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" + /** + * The document symbol request is sent from the client to the server to list all symbols found in a given text document. + */ +struct lsDocumentSymbolParams { + lsTextDocumentIdentifier textDocument; + MAKE_SWAP_METHOD(lsDocumentSymbolParams, textDocument) +}; +MAKE_REFLECT_STRUCT(lsDocumentSymbolParams, textDocument); + + + +struct TextDocumentDocumentSymbol{ + typedef std::pair< boost::optional<lsSymbolInformation> , boost::optional<lsDocumentSymbol> > Either; +}; +void Reflect(Reader& visitor, TextDocumentDocumentSymbol::Either& value); + + + +/** + * The document symbol request is sent from the client to the server to list all + * symbols found in a given text document. + * + * Registration Options: {@link TextDocumentRegistrationOptions} + * + * <p> + * <b>Caveat</b>: although the return type allows mixing the + * {@link DocumentSymbol} and {@link SymbolInformation} instances into a list do + * not do it because the clients cannot accept a heterogeneous list. A list of + * {@code DocumentSymbol} instances is only a valid return value if the + * {@link DocumentSymbolCapabilities#getHierarchicalDocumentSymbolSupport() + * textDocument.documentSymbol.hierarchicalDocumentSymbolSupport} is + * {@code true}. More details on this difference between the LSP and the LSP4J + * can be found <a href="https://github.com/eclipse/lsp4j/issues/252">here</a>. + * </p> + */ + +//DEFINE_REQUEST_RESPONSE_TYPE(td_symbol, +// lsDocumentSymbolParams, +// std::vector<TextDocumentDocumentSymbol::Either> ); +// + +DEFINE_REQUEST_RESPONSE_TYPE(td_symbol, + lsDocumentSymbolParams, + std::vector< lsDocumentSymbol >,"textDocument/documentSymbol" ); + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/foldingRange.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/foldingRange.h new file mode 100644 index 0000000000..27977a4517 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/foldingRange.h @@ -0,0 +1,62 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "document_symbol.h" +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" + + +struct FoldingRangeRequestParams { + /** + * The text document. + */ + + lsTextDocumentIdentifier textDocument; + MAKE_SWAP_METHOD(FoldingRangeRequestParams, textDocument) +}; +MAKE_REFLECT_STRUCT(FoldingRangeRequestParams, textDocument) + + +struct FoldingRange { + /** + * The zero-based line number from where the folded range starts. + */ + int startLine; + + /** + * The zero-based line number where the folded range ends. + */ + int endLine; + + /** + * The zero-based character offset from where the folded range starts. If not defined, defaults + * to the length of the start line. + */ + int startCharacter; + + /** + * The zero-based character offset before the folded range ends. If not defined, defaults to the + * length of the end line. + */ + int endCharacter; + + /** + * Describes the kind of the folding range such as `comment' or 'region'. The kind + * is used to categorize folding ranges and used by commands like 'Fold all comments'. See + * FoldingRangeKind for an enumeration of standardized kinds. + */ + std::string kind; + + MAKE_SWAP_METHOD(FoldingRange, startLine, endLine, startCharacter, endCharacter, kind) +}; +MAKE_REFLECT_STRUCT(FoldingRange,startLine,endLine,startCharacter,endCharacter,kind) + + +/** + * The folding range request is sent from the client to the server to return all folding + * ranges found in a given text document. + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_foldingRange, FoldingRangeRequestParams, std::vector<FoldingRange>, "textDocument/foldingRange"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/formatting.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/formatting.h new file mode 100644 index 0000000000..ad54e24bf9 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/formatting.h @@ -0,0 +1,32 @@ +#pragma once +#include "LibLsp/lsp/lsFormattingOptions.h" + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + + +namespace TextDocumentFormatting { + + struct Params { + /** + * The document to format. + */ + lsTextDocumentIdentifier textDocument; + /** + * The format options. + */ + lsFormattingOptions options; + MAKE_SWAP_METHOD(Params, textDocument, options); + }; + +}; +MAKE_REFLECT_STRUCT(TextDocumentFormatting::Params, textDocument, options); +/** + * The document formatting request is sent from the client to the server to + * format a whole document. + * + * Registration Options: TextDocumentRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_formatting, TextDocumentFormatting::Params, + std::vector<lsTextEdit>, "textDocument/formatting"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/highlight.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/highlight.h new file mode 100644 index 0000000000..332baf69e1 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/highlight.h @@ -0,0 +1,18 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" +#include "document_symbol.h" + +/** + * The references request is sent from the client to the server to resolve + * project-wide references for the symbol denoted by the given text document + * position. + * + * Registration Options: TextDocumentRegistrationOptions + */ + +DEFINE_REQUEST_RESPONSE_TYPE(td_highlight, lsTextDocumentPositionParams, + std::vector<lsDocumentHighlight>, "textDocument/documentHighlight"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/hover.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/hover.h new file mode 100644 index 0000000000..5302316c6f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/hover.h @@ -0,0 +1,55 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsMarkedString.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" +#include "LibLsp/lsp/lsRange.h" +/** + * The hover request is sent from the client to the server to request hover + * information at a given text document position. + * + * Registration Options: TextDocumentRegistrationOptions + */ + +namespace TextDocumentHover +{ + typedef boost::optional< std::vector< std::pair<boost::optional<std::string>, boost::optional<lsMarkedString>> > > Left; + typedef std::pair< Left, boost::optional<MarkupContent> > Either; + struct Result { + /** + * The hover's content as markdown + */ + Either contents; + + /** + * An boost::optional range + */ + boost::optional<lsRange> range; + + MAKE_SWAP_METHOD(Result, contents, range) + }; +} +MAKE_REFLECT_STRUCT(TextDocumentHover::Result, contents, range); + +extern void Reflect(Reader& visitor, std::pair<boost::optional<std::string>, boost::optional<lsMarkedString>>& value); +extern void Reflect(Reader& visitor, TextDocumentHover::Either& value); + + +DEFINE_REQUEST_RESPONSE_TYPE(td_hover, lsTextDocumentPositionParams, TextDocumentHover::Result, "textDocument/hover") + +//struct Rsp_TextDocumentHover : ResponseMessage< TextDocumentHover::Result, Rsp_TextDocumentHover> { +// +//}; +//MAKE_REFLECT_STRUCT(Rsp_TextDocumentHover, +// jsonrpc, +// id, +// result); + +//MAKE_REFLECT_STRUCT_OPTIONALS_MANDATORY(Rsp_TextDocumentHover, +// jsonrpc, +// id, +// result); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/implementation.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/implementation.h new file mode 100644 index 0000000000..0d7851cb81 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/implementation.h @@ -0,0 +1,16 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/lsp/out_list.h" + + +/** + * The goto implementation request is sent from the client to the server to resolve + * the implementation location of a symbol at a given text document position. + * + * Registration Options: TextDocumentRegistrationOptions + * + * Since version 3.6.0 + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_implementation, lsTextDocumentPositionParams, LocationListEither::Either, "textDocument/implementation");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/linkedEditingRange.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/linkedEditingRange.h new file mode 100644 index 0000000000..e4055d359f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/linkedEditingRange.h @@ -0,0 +1,51 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/lsp/lsAny.h" +#include "LibLsp/lsp/symbol.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" +#include "LibLsp/lsp/lsRange.h" + + + +struct LinkedEditingRangeParams +{ + lsTextDocumentIdentifier textDocument; + lsPosition position; + + MAKE_SWAP_METHOD(LinkedEditingRangeParams, + textDocument, + position) +}; +MAKE_REFLECT_STRUCT(LinkedEditingRangeParams, + textDocument, + position) + + +struct LinkedEditingRanges +{ + /** + * A list of ranges that can be renamed together. The ranges must have + * identical length and contain identical text content. The ranges cannot overlap. + */ + std::vector<lsRange> ranges; + + /** + * An optional word pattern (regular expression) that describes valid contents for + * the given ranges. If no pattern is provided, the client configuration's word + * pattern will be used. + */ + + boost::optional<std::string> wordPattern; + MAKE_SWAP_METHOD(LinkedEditingRanges, + ranges, + wordPattern) +}; + +MAKE_REFLECT_STRUCT(LinkedEditingRanges, + ranges, + wordPattern) +DEFINE_REQUEST_RESPONSE_TYPE(td_linkedEditingRange, LinkedEditingRangeParams, + boost::optional<std::vector<LinkedEditingRanges >>,"textDocument/linkedEditingRange")
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/onTypeFormatting.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/onTypeFormatting.h new file mode 100644 index 0000000000..df14ea5d3d --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/onTypeFormatting.h @@ -0,0 +1,44 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsFormattingOptions.h" +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" +#include "LibLsp/lsp/lsRange.h" +#include "LibLsp/lsp/lsTextEdit.h" + + +struct lsDocumentOnTypeFormattingParams +{ + lsTextDocumentIdentifier textDocument; + lsFormattingOptions options; + + lsPosition position; + + /** + * The character that has been typed. + */ + + std::string ch; + + MAKE_SWAP_METHOD(lsDocumentOnTypeFormattingParams, + textDocument, + position, + options, ch); +}; +MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingParams, + textDocument, + position, + options,ch); + +/** + * The document range formatting request is sent from the client to the + * server to format a given range in a document. + * + * Registration Options: TextDocumentRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_onTypeFormatting, + lsDocumentOnTypeFormattingParams, std::vector<lsTextEdit>, "textDocument/onTypeFormatting"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/prepareRename.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/prepareRename.h new file mode 100644 index 0000000000..8c653d9864 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/prepareRename.h @@ -0,0 +1,40 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsWorkspaceEdit.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" + +/** + * The rename request is sent from the client to the server to do a + * workspace wide rename of a symbol. + * + * Registration Options: TextDocumentRegistrationOptions + */ +struct PrepareRenameResult{ + /** + * The range of the string to rename + */ + + lsRange range; + +/** + * A placeholder text of the string content to be renamed. + */ + + std::string placeholder; + + MAKE_SWAP_METHOD(PrepareRenameResult, range, placeholder) + +}; +MAKE_REFLECT_STRUCT(PrepareRenameResult,range,placeholder) + + + +typedef std::pair< boost::optional< lsRange>, boost::optional<PrepareRenameResult>> TextDocumentPrepareRenameResult; +extern void Reflect(Reader& visitor, TextDocumentPrepareRenameResult& value); + + +DEFINE_REQUEST_RESPONSE_TYPE(td_prepareRename, + lsTextDocumentPositionParams, TextDocumentPrepareRenameResult, "textDocument/prepareRename");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/publishDiagnostics.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/publishDiagnostics.h new file mode 100644 index 0000000000..bf28104bbb --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/publishDiagnostics.h @@ -0,0 +1,28 @@ +#pragma once + +#include "LibLsp/JsonRpc/NotificationInMessage.h" +#include "LibLsp/lsp/lsp_diagnostic.h" + +// Diagnostics +namespace TextDocumentPublishDiagnostics{ + struct Params { + // The URI for which diagnostic information is reported. + lsDocumentUri uri; + + // An array of diagnostic information items. + std::vector<lsDiagnostic> diagnostics; + MAKE_SWAP_METHOD(Params,uri,diagnostics); + }; + + +}; +MAKE_REFLECT_STRUCT(TextDocumentPublishDiagnostics::Params, + uri, + diagnostics); + +/** + * Diagnostics notifications are sent from the server to the client to + * signal results of validation runs. + */ +DEFINE_NOTIFICATION_TYPE(Notify_TextDocumentPublishDiagnostics, TextDocumentPublishDiagnostics::Params, "textDocument/publishDiagnostics"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/range_formatting.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/range_formatting.h new file mode 100644 index 0000000000..b2fe750af1 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/range_formatting.h @@ -0,0 +1,35 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsFormattingOptions.h" + + +struct lsTextDocumentRangeFormattingParams { + lsTextDocumentIdentifier textDocument; + lsRange range; + lsFormattingOptions options; + + MAKE_SWAP_METHOD(lsTextDocumentRangeFormattingParams, + textDocument, + range, + options) +}; +MAKE_REFLECT_STRUCT(lsTextDocumentRangeFormattingParams, + textDocument, + range, + options); + +/** + * The document range formatting request is sent from the client to the + * server to format a given range in a document. + * + * Registration Options: TextDocumentRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_rangeFormatting, lsTextDocumentRangeFormattingParams, std::vector<lsTextEdit>, + "textDocument/rangeFormatting"); + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/references.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/references.h new file mode 100644 index 0000000000..2376912756 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/references.h @@ -0,0 +1,48 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/symbol.h" + + +namespace TextDocumentReferences { + + struct lsReferenceContext { + // Include the declaration of the current symbol. + boost::optional<bool> includeDeclaration; + MAKE_REFLECT_STRUCT(lsReferenceContext, + includeDeclaration) + }; + struct Params { + lsTextDocumentIdentifier textDocument; + lsPosition position; + lsReferenceContext context; + MAKE_SWAP_METHOD(Params, + textDocument, + position, + context) + + }; + +}; +MAKE_REFLECT_STRUCT(TextDocumentReferences::lsReferenceContext, + includeDeclaration); +MAKE_REFLECT_STRUCT(TextDocumentReferences::Params, + textDocument, + position, + context); + + + + +/** + * The references request is sent from the client to the server to resolve + * project-wide references for the symbol denoted by the given text document + * position. + * + * Registration Options: TextDocumentRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_references, TextDocumentReferences::Params, + std::vector<lsLocation>, "textDocument/references"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/rename.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/rename.h new file mode 100644 index 0000000000..35895f0f4f --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/rename.h @@ -0,0 +1,41 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsWorkspaceEdit.h" +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" + +namespace TextDocumentRename { + + struct Params { + // The document to format. + lsTextDocumentIdentifier textDocument; + + // The position at which this request was sent. + lsPosition position; + + // The new name of the symbol. If the given name is not valid the + // request must return a [ResponseError](#ResponseError) with an + // appropriate message set. + std::string newName; + MAKE_SWAP_METHOD(Params, + textDocument, + position, + newName); + }; + +}; +MAKE_REFLECT_STRUCT(TextDocumentRename::Params, + textDocument, + position, + newName); +/** + * The rename request is sent from the client to the server to do a + * workspace wide rename of a symbol. + * + * Registration Options: TextDocumentRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_rename, TextDocumentRename::Params, lsWorkspaceEdit, "textDocument/rename"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/resolveCodeLens.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/resolveCodeLens.h new file mode 100644 index 0000000000..0723985160 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/resolveCodeLens.h @@ -0,0 +1,10 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "code_lens.h" + +DEFINE_REQUEST_RESPONSE_TYPE(codeLens_resolve, lsCodeLens, lsCodeLens, "codeLens/resolve") + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/resolveCompletionItem.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/resolveCompletionItem.h new file mode 100644 index 0000000000..f5576894ed --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/resolveCompletionItem.h @@ -0,0 +1,21 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include <regex> +#include "LibLsp/lsp/lsp_completion.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" +#include "completion.h" + +/** + * The request is sent from the client to the server to resolve additional + * information for a given completion item. + */ +DEFINE_REQUEST_RESPONSE_TYPE(completionItem_resolve, lsCompletionItem, lsCompletionItem, "completionItem/resolve"); + + + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/resolveTypeHierarchy.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/resolveTypeHierarchy.h new file mode 100644 index 0000000000..eab5f838fc --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/resolveTypeHierarchy.h @@ -0,0 +1,31 @@ +#pragma once + + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/symbol.h" +#include "typeHierarchy.h" + +struct ResolveTypeHierarchyItemParams { + /** + * The hierarchy item to resolve. + */ + + TypeHierarchyItem item; + + /** + * The number of hierarchy levels to resolve. {@code 0} indicates no hierarchy level. + */ + boost::optional<int> resolve; + + /** + * The direction of the type hierarchy resolution. + */ + + TypeHierarchyDirection direction; + MAKE_SWAP_METHOD(ResolveTypeHierarchyItemParams, item, resolve, direction) +}; +MAKE_REFLECT_STRUCT(ResolveTypeHierarchyItemParams,item,resolve,direction) +DEFINE_REQUEST_RESPONSE_TYPE(typeHierarchy_resolve, ResolveTypeHierarchyItemParams, TypeHierarchyItem, "typeHierarchy/resolve") diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/selectionRange.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/selectionRange.h new file mode 100644 index 0000000000..47590e4152 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/selectionRange.h @@ -0,0 +1,52 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsPosition.h" +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" + +struct SelectionRangeParams { + /** + * The text document. + */ + + lsTextDocumentIdentifier textDocument; + + /** + * The positions inside the text document. + */ + + std::vector<lsPosition> positions; + + MAKE_SWAP_METHOD(SelectionRangeParams, textDocument, positions) + +}; +MAKE_REFLECT_STRUCT(SelectionRangeParams, textDocument, positions) + +struct SelectionRange { + /** + * The [range](#Range) of this selection range. + */ + + lsRange range; + + /** + * The parent selection range containing this range. Therefore `parent.range` must contain `this.range`. + */ + boost::optional<SelectionRange*> parent; + MAKE_SWAP_METHOD(SelectionRange, range, parent) +}; + +extern void Reflect(Reader& visitor, boost::optional<SelectionRange*>& value); +extern void Reflect(Writer& visitor, SelectionRange* value); + +MAKE_REFLECT_STRUCT(SelectionRange,range,parent) +/** + * The {@code textDocument/selectionRange} request is sent from the client to the server to return + * suggested selection ranges at an array of given positions. A selection range is a range around + * the cursor position which the user might be interested in selecting. + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_selectionRange, SelectionRangeParams, std::vector<SelectionRange>, "textDocument/selectionRange"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/semanticHighlighting.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/semanticHighlighting.h new file mode 100644 index 0000000000..32bc86f5fb --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/semanticHighlighting.h @@ -0,0 +1,66 @@ +#pragma once +#include "LibLsp/lsp/lsDocumentUri.h" +#include "LibLsp/lsp/lsVersionedTextDocumentIdentifier.h" + +#include "LibLsp/JsonRpc/NotificationInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +/** + * Represents a semantic highlighting information that has to be applied on a specific line of the text document. + */ + +struct SemanticHighlightingInformation { + /** + * The zero-based line position in the text document. + */ + int line = 0; + + /** + * A base64 encoded string representing every single highlighted ranges in the line with its start position, length + * and the "lookup table" index of of the semantic highlighting <a href="https://manual.macromates.com/en/language_grammars"> + * TextMate scopes</a>. If the {@code tokens} is empty or not defined, then no highlighted positions are available for the line. + */ + std::string tokens; + + MAKE_SWAP_METHOD(SemanticHighlightingInformation, line, tokens) +}; + +MAKE_REFLECT_STRUCT(SemanticHighlightingInformation, line, tokens); + +/** + * Parameters for the semantic highlighting (server-side) push notification. + */ + +struct SemanticHighlightingParams { + /** + * The text document that has to be decorated with the semantic highlighting information. + */ + + lsVersionedTextDocumentIdentifier textDocument; + + /** + * An array of semantic highlighting information. + */ + + std::vector<SemanticHighlightingInformation> lines; + + MAKE_SWAP_METHOD(SemanticHighlightingParams, textDocument, lines) + +}; +MAKE_REFLECT_STRUCT(SemanticHighlightingParams, textDocument, lines); +/** + * The {@code textDocument/semanticHighlighting} notification is pushed from the server to the client + * to inform the client about additional semantic highlighting information that has to be applied + * on the text document. It is the server's responsibility to decide which lines are included in + * the highlighting information. In other words, the server is capable of sending only a delta + * information. For instance, after opening the text document ({@code DidOpenTextDocumentNotification}) + * the server sends the semantic highlighting information for the entire document, but if the server + * receives a {@code DidChangeTextDocumentNotification}, it pushes the information only about + * the affected lines in the document. + * + * <p> + * <b>Note:</b> the <a href= + * "https://github.com/Microsoft/vscode-languageserver-node/pull/367">{@code textDocument/semanticHighlighting} + * language feature</a> is not yet part of the official LSP specification. + */ +DEFINE_NOTIFICATION_TYPE(Notify_semanticHighlighting, SemanticHighlightingParams, "textDocument/semanticHighlighting");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/signature_help.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/signature_help.h new file mode 100644 index 0000000000..2a83645901 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/signature_help.h @@ -0,0 +1,92 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/lsp/lsMarkedString.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" + +extern void Reflect(Reader& visitor, + std::pair<boost::optional<std::string>, boost::optional<MarkupContent>>& value); + + + +// Represents a parameter of a callable-signature. A parameter can +// have a label and a doc-comment. +struct lsParameterInformation { + // The label of this parameter. Will be shown in + // the UI. + std::string label; + + // The human-readable doc-comment of this parameter. Will be shown + // in the UI but can be omitted. + boost::optional< std::pair< boost::optional<std::string> , boost::optional <MarkupContent> > > documentation; + + MAKE_SWAP_METHOD(lsParameterInformation, label, documentation) +}; +MAKE_REFLECT_STRUCT(lsParameterInformation, label, documentation); + +// Represents the signature of something callable. A signature +// can have a label, like a function-name, a doc-comment, and +// a set of parameters. +struct lsSignatureInformation { + // The label of this signature. Will be shown in + // the UI. + std::string label; + + // The human-readable doc-comment of this signature. Will be shown + // in the UI but can be omitted. + boost::optional< std::pair< boost::optional<std::string>, boost::optional <MarkupContent> > > documentation; + + // The parameters of this signature. + std::vector<lsParameterInformation> parameters; + + MAKE_SWAP_METHOD(lsSignatureInformation, label, documentation, parameters) +}; +MAKE_REFLECT_STRUCT(lsSignatureInformation, label, documentation, parameters); + +// Signature help represents the signature of something +// callable. There can be multiple signature but only one +// active and only one active parameter. +struct lsSignatureHelp { + // One or more signatures. + std::vector<lsSignatureInformation> signatures; + + // The active signature. If omitted or the value lies outside the + // range of `signatures` the value defaults to zero or is ignored if + // `signatures.length === 0`. Whenever possible implementors should + // make an active decision about the active signature and shouldn't + // rely on a default value. + // In future version of the protocol this property might become + // mandantory to better express this. + boost::optional<int> activeSignature; + + // The active parameter of the active signature. If omitted or the value + // lies outside the range of `signatures[activeSignature].parameters` + // defaults to 0 if the active signature has parameters. If + // the active signature has no parameters it is ignored. + // In future version of the protocol this property might become + // mandantory to better express the active parameter if the + // active signature does have any. + boost::optional<int> activeParameter; + + + MAKE_SWAP_METHOD(lsSignatureHelp, + signatures, + activeSignature, + activeParameter) +}; +MAKE_REFLECT_STRUCT(lsSignatureHelp, + signatures, + activeSignature, + activeParameter); + + + +/** + * The signature help request is sent from the client to the server to + * request signature information at a given cursor position. + * + * Registration Options: SignatureHelpRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_signatureHelp, lsTextDocumentPositionParams, lsSignatureHelp, "textDocument/signatureHelp");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/typeHierarchy.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/typeHierarchy.h new file mode 100644 index 0000000000..b554d751f3 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/typeHierarchy.h @@ -0,0 +1,133 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/lsp/lsTextDocumentPositionParams.h" +#include "LibLsp/lsp/symbol.h" +#include "LibLsp/lsp/lsAny.h" +/** + * The {@code textDocument/typeHierarchy} request is sent from the client to the + * server to retrieve a {@link TypeHierarchyItem type hierarchy item} based on + * the {@link TypeHierarchyParams cursor position in the text document}. This + * request would also allow to specify if the item should be resolved and + * whether sub- or supertypes are to be resolved. If no type hierarchy item can + * be found under the given text document position, resolves to {@code null}. + * + * <p> + * <b>Note:</b> the <a href= + * "https://github.com/Microsoft/vscode-languageserver-node/pull/426">{@code textDocument/typeHierarchy} + * language feature</a> is not yet part of the official LSP specification. + */ +enum class TypeHierarchyDirection : uint32_t{ + + /** + * Flag for retrieving/resolving the subtypes. Value: {@code 0}. + */ + Children = 0, + + /** + * Flag to use when retrieving/resolving the supertypes. Value: {@code 1}. + */ + Parents =1, + + /** + * Flag for resolving both the super- and subtypes. Value: {@code 2}. + */ + Both=2 +}; +void Reflect(Reader& reader, TypeHierarchyDirection& value); + + +void Reflect(Writer& writer, TypeHierarchyDirection& value); + +struct TypeHierarchyParams :public lsTextDocumentPositionParams +{ + boost::optional<int> resolve; + boost::optional<TypeHierarchyDirection> direction ; + + MAKE_SWAP_METHOD(TypeHierarchyParams, textDocument, position, resolve, direction) +}; +MAKE_REFLECT_STRUCT(TypeHierarchyParams, textDocument, position, resolve, direction); + + + + + +/** + * Representation of an item that carries type information (such as class, interface, enumeration, etc) with additional parentage details. + */ + +struct TypeHierarchyItem { + /** + * The human readable name of the hierarchy item. + */ + + std::string name; + + /** + * Optional detail for the hierarchy item. It can be, for instance, the signature of a function or method. + */ + boost::optional<std::string> + detail; + + /** + * The kind of the hierarchy item. For instance, class or interface. + */ + + SymbolKind kind; + + /** + * {@code true} if the hierarchy item is deprecated. Otherwise, {@code false}. It is {@code false} by default. + */ + + boost::optional<bool> deprecated; + + /** + * The URI of the text document where this type hierarchy item belongs to. + */ + + lsDocumentUri uri; + + /** + * The range enclosing this type hierarchy item not including leading/trailing whitespace but everything else + * like comments. This information is typically used to determine if the clients cursor is inside the type + * hierarchy item to reveal in the symbol in the UI. + * + * @see TypeHierarchyItem#selectionRange + */ + + lsRange range; + + /** + * The range that should be selected and revealed when this type hierarchy item is being picked, e.g the name of a function. + * Must be contained by the the {@link TypeHierarchyItem#getRange range}. + * + * @see TypeHierarchyItem#range + */ + + lsRange selectionRange; + + /** + * If this type hierarchy item is resolved, it contains the direct parents. Could be empty if the item does not have any + * direct parents. If not defined, the parents have not been resolved yet. + */ + boost::optional< std::vector<TypeHierarchyItem> > parents; + + /** + * If this type hierarchy item is resolved, it contains the direct children of the current item. + * Could be empty if the item does not have any descendants. If not defined, the children have not been resolved. + */ + boost::optional< std::vector<TypeHierarchyItem> > children; + + /** + * An boost::optional data field can be used to identify a type hierarchy item in a resolve request. + */ + boost::optional<lsp::Any> data; + + MAKE_SWAP_METHOD(TypeHierarchyItem, name, detail, kind, deprecated, uri, range, selectionRange, parents, children, data) +}; +MAKE_REFLECT_STRUCT(TypeHierarchyItem, name, detail, kind, deprecated, uri, range, selectionRange, parents, children, data); + + + +DEFINE_REQUEST_RESPONSE_TYPE(td_typeHierarchy, TypeHierarchyParams, TypeHierarchyItem, "textDocument/typeHierarchy");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/type_definition.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/type_definition.h new file mode 100644 index 0000000000..38ced43b42 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/type_definition.h @@ -0,0 +1,16 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/lsp/out_list.h" + +/** + * The goto type definition request is sent from the client to the server to resolve + * the type definition location of a symbol at a given text document position. + * + * Registration Options: TextDocumentRegistrationOptions + * + * Since version 3.6.0 + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_typeDefinition, + lsTextDocumentPositionParams, LocationListEither::Either, "textDocument/typeDefinition");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/willSave.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/willSave.h new file mode 100644 index 0000000000..84aa0badaa --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/textDocument/willSave.h @@ -0,0 +1,71 @@ +#pragma once + + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" + +namespace WillSaveTextDocumentParams { + + /** + * Represents reasons why a text document is saved. + */ + enum class TextDocumentSaveReason { + + /** + * Manually triggered, e.g. by the user pressing save, by starting debugging, + * or by an API call. + */ + Manual=(1), + + /** + * Automatic after a delay. + */ + AfterDelay=(2), + + /** + * When the editor lost focus. + */ + FocusOut=(3) + }; + + struct Params { + /** + * The document that will be saved. + */ + lsTextDocumentIdentifier textDocument; + + /* + * A reason why a text document is saved. + */ + + boost::optional<TextDocumentSaveReason> reason; + + MAKE_SWAP_METHOD(Params, textDocument, reason); + }; + +}; +MAKE_REFLECT_TYPE_PROXY(WillSaveTextDocumentParams::TextDocumentSaveReason); + +MAKE_REFLECT_STRUCT(WillSaveTextDocumentParams::Params, textDocument, reason); + +/** + * The document save notification is sent from the client to the server when + * the document for saved in the client. + * + * Registration Options: TextDocumentSaveRegistrationOptions + */ +DEFINE_NOTIFICATION_TYPE(td_willSave, WillSaveTextDocumentParams::Params, "textDocument/willSave"); + +/** + * The document will save request is sent from the client to the server before the document is actually saved. + * The request can return an array of TextEdits which will be applied to the text document before it is saved. + * Please note that clients might drop results if computing the text edits took too long or if a server constantly fails on this request. + * This is done to keep the save fast and reliable. + * + * Registration Options: TextDocumentRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_willSaveWaitUntil, + WillSaveTextDocumentParams::Params, std::vector<lsTextEdit>, "textDocument/willSaveWaitUntil"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/utils.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/utils.h new file mode 100644 index 0000000000..796b5d2569 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/utils.h @@ -0,0 +1,141 @@ +#pragma once +#include <algorithm> +#include <codecvt> +#include <functional> +#include <iterator> +#include <locale> +#include <memory> +#include <string> +#include <vector> +#include <boost/optional/optional.hpp> +#include <LibLsp/lsp/AbsolutePath.h> + +#include "lsPosition.h" + + +namespace lsp +{ + + +// Returns true if |value| starts/ends with |start| or |ending|. +bool StartsWith(std::string value, std::string start); +bool EndsWith(std::string value, std::string ending); +bool AnyStartsWith(const std::vector<std::string>& values, + const std::string& start); +bool StartsWithAny(const std::string& value, + const std::vector<std::string>& startings); +bool EndsWithAny(const std::string& value, + const std::vector<std::string>& endings); +bool FindAnyPartial(const std::string& value, + const std::vector<std::string>& values); +// Returns the dirname of |path|, i.e. "foo/bar.cc" => "foo/", "foo" => "./", +// "/foo" => "/". The result always ends in '/'. +std::string GetDirName(std::string path); +// Returns the basename of |path|, ie, "foo/bar.cc" => "bar.cc". +std::string GetBaseName(const std::string& path); +// Returns |path| without the filetype, ie, "foo/bar.cc" => "foo/bar". +std::string StripFileType(const std::string& path); + +std::string ReplaceAll(const std::string& source, + const std::string& from, + const std::string& to); + +std::vector<std::string> SplitString(const std::string& str, + const std::string& delimiter); + +template <typename TValues, typename TMap> +std::string StringJoinMap(const TValues& values, + const TMap& map, + const std::string& sep = ", ") { + std::string result; + bool first = true; + for (auto& entry : values) { + if (!first) + result += sep; + first = false; + result += map(entry); + } + return result; +} + +template <typename TValues> +std::string StringJoin(const TValues& values, const std::string& sep = ", ") { + return StringJoinMap(values, [](const std::string& entry) { return entry; }, + sep); +} + +template <typename TCollection, typename TValue> +bool ContainsValue(const TCollection& collection, const TValue& value) { + return std::find(std::begin(collection), std::end(collection), value) != + std::end(collection); +} + + +// Ensures that |path| ends in a slash. +void EnsureEndsInSlash(std::string& path); + +// Converts a file path to one that can be used as filename. +// e.g. foo/bar.c => foo_bar.c +std::string EscapeFileName(std::string path); + +// FIXME: Move ReadContent into ICacheManager? +bool FileExists(const std::string& filename); +boost::optional<std::string> ReadContent(const AbsolutePath& filename); +std::vector<std::string> ReadLinesWithEnding(const AbsolutePath& filename); + +bool WriteToFile(const std::string& filename, const std::string& content); + + +template <typename T, typename Fn> +void RemoveIf(std::vector<T>* vec, Fn predicate) { + vec->erase(std::remove_if(vec->begin(), vec->end(), predicate), vec->end()); +} + +std::string FormatMicroseconds(long long microseconds); + +// Makes sure all newlines in |output| are in \r\n format. +std::string UpdateToRnNewlines(std::string output); + +// Utility methods to check if |path| is absolute. +bool IsAbsolutePath(const std::string& path); +bool IsUnixAbsolutePath(const std::string& path); +bool IsWindowsAbsolutePath(const std::string& path); + +bool IsDirectory(const std::string& path); + +// string <-> wstring conversion (UTF-16), e.g. for use with Window's wide APIs. + std::string ws2s(std::wstring const& wstr); + std::wstring s2ws(std::string const& str); + +AbsolutePath NormalizePath(const std::string& path, + bool ensure_exists = true, + bool force_lower_on_windows = true); + + +int GetOffsetForPosition(lsPosition position, const std::string& content); + +// Finds the position for an |offset| in |content|. +lsPosition GetPositionForOffset(int offset, const std::string& content); + +// Utility method to find a position for the given character. +lsPosition CharPos(const std::string& search, + char character, + int character_offset = 0); + + + void scanDirsNoRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret); + + void scanFilesUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret, + std::wstring strSuf = L""); + + void scanFileNamesUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret, + std::wstring strSuf = L""); + void scanFileNamesUseRecursive(const std::string& rootPath, std::vector<std::string>& ret, + std::string strSuf = ""); + + void scanFilesUseRecursive(const std::string& rootPath, std::vector<std::string>& ret, + std::string strSuf = ""); + + void scanDirsUseRecursive(const std::wstring& rootPath, std::vector<std::wstring>& ret); + +} diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/windows/MessageNotify.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/windows/MessageNotify.h new file mode 100644 index 0000000000..8499304f55 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/windows/MessageNotify.h @@ -0,0 +1,83 @@ +#pragma once + +#include "LibLsp/JsonRpc/NotificationInMessage.h" +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +// Show a message to the user. +enum class lsMessageType : int { Error = 1, Warning = 2, Info = 3, Log = 4 }; +MAKE_REFLECT_TYPE_PROXY(lsMessageType) +struct MessageParams { +/** + * The message type. + */ + + lsMessageType type = lsMessageType::Error; + +/** + * The actual message. + */ + std::string message; + + void swap(MessageParams& arg) noexcept { + lsMessageType temp = type; + type = arg.type; + arg.type = temp; + message.swap(arg.message); + } +}; +MAKE_REFLECT_STRUCT(MessageParams, type, message) + + /** + * The log message notification is send from the server to the client to ask + * the client to log a particular message. + */ +DEFINE_NOTIFICATION_TYPE(Notify_LogMessage, MessageParams, "window/logMessage") + + +/** + * The show message notification is sent from a server to a client to ask + * the client to display a particular message in the user interface. + */ +DEFINE_NOTIFICATION_TYPE(Notify_ShowMessage, MessageParams, "window/showMessage") + + + +/** + * The show message request is sent from a server to a client to ask the client to display a particular message in the + * user class. In addition to the show message notification the request allows to pass actions and to wait for an + * answer from the client. + */ +struct MessageActionItem { + /** + * A short title like 'Retry', 'Open Log' etc. + */ + + std::string title; + MAKE_SWAP_METHOD(MessageActionItem, title) +}; +MAKE_REFLECT_STRUCT(MessageActionItem, title); + + +struct ShowMessageRequestParams :public MessageParams { + /** + * The message action items to present. + */ + std::vector<MessageActionItem> actions; + + MAKE_SWAP_METHOD(ShowMessageRequestParams, type, message, actions) + +}; +MAKE_REFLECT_STRUCT(ShowMessageRequestParams, type, message, actions) + +/** +* The show message request is sent from a server to a client to ask the +* client to display a particular message in the user interface. In addition +* to the show message notification the request allows to pass actions and +* to wait for an answer from the client. +*/ + +DEFINE_REQUEST_RESPONSE_TYPE(WindowShowMessage, ShowMessageRequestParams, MessageActionItem, "window/showMessage") + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/working_files.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/working_files.h new file mode 100644 index 0000000000..e305fee8d0 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/working_files.h @@ -0,0 +1,72 @@ +#pragma once + +#include "LibLsp/lsp/lsp_diagnostic.h" +#include "LibLsp/lsp/AbsolutePath.h" +#include "LibLsp/lsp/textDocument/did_change.h" +#include "LibLsp/lsp/textDocument/did_close.h" +#include "LibLsp/lsp/textDocument/did_open.h" +#include <mutex> +#include <string> +#include <memory> +#include "Directory.h" + +struct WorkingFiles; +struct WorkingFilesData; +struct WorkingFile { + + int version = 0; + AbsolutePath filename; + Directory directory; + WorkingFiles& parent; + std::atomic<long long> counter; + WorkingFile(WorkingFiles& ,const AbsolutePath& filename, const std::string& buffer_content); + WorkingFile(WorkingFiles&, const AbsolutePath& filename, std::string&& buffer_content); + const std::string& GetContentNoLock() const + { + return buffer_content; + } +protected: + friend struct WorkingFiles; + std::string buffer_content; +}; + +struct WorkingFiles { + + WorkingFiles(); + ~WorkingFiles(); + + void CloseFilesInDirectory(const std::vector<Directory>&); + std::shared_ptr<WorkingFile> OnOpen(lsTextDocumentItem& open); + std::shared_ptr<WorkingFile> OnChange(const lsTextDocumentDidChangeParams& change); + bool OnClose(const lsTextDocumentIdentifier& close); + std::shared_ptr<WorkingFile> OnSave(const lsTextDocumentIdentifier& _save); + + bool GetFileBufferContent(const AbsolutePath& filename, std::wstring& out) + { + auto file = GetFileByFilename(filename); + if(!file) + return false; + return GetFileBufferContent(file, out); + } + bool GetFileBufferContent(const AbsolutePath& filename,std::string& out) + { + auto file = GetFileByFilename(filename); + if (!file) + return false; + return GetFileBufferContent(file, out); + } + bool GetFileBufferContent(std::shared_ptr<WorkingFile>&, std::string& out); + bool GetFileBufferContent(std::shared_ptr<WorkingFile>&, std::wstring& out); + + + // Find the file with the given filename. + std::shared_ptr<WorkingFile> GetFileByFilename(const AbsolutePath& filename); + + void Clear(); +private: + std::shared_ptr<WorkingFile> GetFileByFilenameNoLock(const AbsolutePath& filename); + + WorkingFilesData* d_ptr; + + +}; diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/applyEdit.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/applyEdit.h new file mode 100644 index 0000000000..7e2d8bee0a --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/applyEdit.h @@ -0,0 +1,42 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsDocumentUri.h" +#include "LibLsp/lsp/lsWorkspaceEdit.h" + +struct ApplyWorkspaceEditParams +{ + /** + * The edits to apply. + */ + + lsWorkspaceEdit edit; + + /** + * An optional label of the workspace edit. This label is + * presented in the user interface for example on an undo + * stack to undo the workspace edit. + */ + std::string label; + + MAKE_SWAP_METHOD(ApplyWorkspaceEditParams, edit, label) +}; +/** + * The workspace/applyEdit request is sent from the server to the client to modify resource on the client side. + */ +MAKE_REFLECT_STRUCT(ApplyWorkspaceEditParams, edit, label); + + + +struct ApplyWorkspaceEditResponse +{ + bool applied; + boost::optional<std::string> failureReason; + MAKE_SWAP_METHOD(ApplyWorkspaceEditResponse, applied, failureReason) +}; +MAKE_REFLECT_STRUCT(ApplyWorkspaceEditResponse, applied, failureReason); + + +DEFINE_REQUEST_RESPONSE_TYPE(WorkspaceApply, ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse, "workspace/applyEdit"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/configuration.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/configuration.h new file mode 100644 index 0000000000..f7709aa607 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/configuration.h @@ -0,0 +1,37 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsDocumentUri.h" + + +struct ConfigurationItem { + /** + * The scope to get the configuration section for. + */ + lsDocumentUri scopeUri; + + /** + * The configuration section asked for. + */ + std::string section; + MAKE_SWAP_METHOD(ConfigurationItem, scopeUri, section); +}; +MAKE_REFLECT_STRUCT(ConfigurationItem, scopeUri, section); +struct ConfigurationParams +{ + std::vector<ConfigurationItem> items; + MAKE_SWAP_METHOD(ConfigurationParams, items) +}; + +MAKE_REFLECT_STRUCT(ConfigurationParams, items); + +/** + * The workspace/configuration request is sent from the server to the client to fetch + * configuration settings from the client. The request can fetch n configuration settings + * in one roundtrip. The order of the returned configuration settings correspond to the + * order of the passed ConfigurationItems (e.g. the first item in the response is the + * result for the first configuration item in the params). + */ +DEFINE_REQUEST_RESPONSE_TYPE(WorkspaceConfiguration, ConfigurationParams,std::vector<lsp::Any>, "workspace/configuration");
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/didChangeWorkspaceFolders.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/didChangeWorkspaceFolders.h new file mode 100644 index 0000000000..78f000f30d --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/didChangeWorkspaceFolders.h @@ -0,0 +1,48 @@ +#pragma once +#include "LibLsp/JsonRpc/NotificationInMessage.h" +#include "LibLsp/lsp/workspace/workspaceFolders.h" +/** + * The workspace folder change event. + */ +struct WorkspaceFoldersChangeEvent { + /** + * The array of added workspace folders + */ + + std::vector<WorkspaceFolder> added; + + /** + * The array of the removed workspace folders + */ + + std::vector <WorkspaceFolder> removed; + MAKE_SWAP_METHOD(WorkspaceFoldersChangeEvent, added, removed); + +}; +MAKE_REFLECT_STRUCT(WorkspaceFoldersChangeEvent, added, removed); + +struct DidChangeWorkspaceFoldersParams { + /** + * The actual workspace folder change event. + */ + + WorkspaceFoldersChangeEvent event; + + MAKE_SWAP_METHOD(DidChangeWorkspaceFoldersParams, event); +}; +MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParams, event); + + +/** + * The workspace/didChangeWorkspaceFolders notification is sent from the client + * to the server to inform the server about workspace folder configuration changes. + * The notification is sent by default if both ServerCapabilities/workspaceFolders + * and ClientCapabilities/workspace/workspaceFolders are true; or if the server has + * registered to receive this notification it first. + */ +DEFINE_NOTIFICATION_TYPE(Notify_WorkspaceDidChangeWorkspaceFolders, + DidChangeWorkspaceFoldersParams, "workspace/didChangeWorkspaceFolders"); + + + + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/did_change_configuration.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/did_change_configuration.h new file mode 100644 index 0000000000..8f8acceea4 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/did_change_configuration.h @@ -0,0 +1,25 @@ +#pragma once + +#include "LibLsp/JsonRpc/NotificationInMessage.h" + + +#include "workspaceFolders.h" + + + + +struct lsDidChangeConfigurationParams { + /** + * The actual changed settings. + */ + lsp::Any settings; + MAKE_SWAP_METHOD(lsDidChangeConfigurationParams, settings); +}; + +MAKE_REFLECT_STRUCT(lsDidChangeConfigurationParams, settings); + +/** + * A notification sent from the client to the server to signal the change of + * configuration settings. + */ +DEFINE_NOTIFICATION_TYPE(Notify_WorkspaceDidChangeConfiguration, lsDidChangeConfigurationParams, "workspace/didChangeConfiguration"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/did_change_watched_files.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/did_change_watched_files.h new file mode 100644 index 0000000000..c14a7e0eda --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/did_change_watched_files.h @@ -0,0 +1,46 @@ +#pragma once + +#include "LibLsp/JsonRpc/NotificationInMessage.h" +#include "LibLsp/lsp/lsDocumentUri.h" +enum class lsFileChangeType { + Created = 1, + Changed = 2, + Deleted = 3, +}; + +#ifdef _WIN32 +MAKE_REFLECT_TYPE_PROXY(lsFileChangeType); +#else +//#pragma clang diagnostic push +//#pragma clang diagnostic ignored "-Wunused-function" +MAKE_REFLECT_TYPE_PROXY(lsFileChangeType); +//#pragma clang diagnostic pop +#endif + + +/** + * An event describing a file change. + */ +struct lsFileEvent { + lsDocumentUri uri; + lsFileChangeType type; + + MAKE_SWAP_METHOD(lsFileEvent, uri, type) +}; +MAKE_REFLECT_STRUCT(lsFileEvent, uri, type); + +struct lsDidChangeWatchedFilesParams { + std::vector<lsFileEvent> changes; + MAKE_SWAP_METHOD(lsDidChangeWatchedFilesParams, changes); +}; +MAKE_REFLECT_STRUCT(lsDidChangeWatchedFilesParams, changes); + + /** + * The workspace/didChangeWorkspaceFolders notification is sent from the client + * to the server to inform the server about workspace folder configuration changes. + * The notification is sent by default if both ServerCapabilities/workspaceFolders + * and ClientCapabilities/workspace/workspaceFolders are true; or if the server has + * registered to receive this notification it first. + */ + +DEFINE_NOTIFICATION_TYPE(Notify_WorkspaceDidChangeWatchedFiles, lsDidChangeWatchedFilesParams, "workspace/didChangeWatchedFiles"); diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/execute_command.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/execute_command.h new file mode 100644 index 0000000000..c656ee5ef7 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/execute_command.h @@ -0,0 +1,24 @@ +#pragma once + +#include "LibLsp/lsp/ExecuteCommandParams.h" + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/JsonRpc/NotificationInMessage.h" + + + +/** + * The workspace/executeCommand request is sent from the client to the + * server to trigger command execution on the server. In most cases the + * server creates a WorkspaceEdit structure and applies the changes to the + * workspace using the request workspace/applyEdit which is sent from the + * server to the client. + * + * Registration Options: ExecuteCommandRegistrationOptions + */ +DEFINE_REQUEST_RESPONSE_TYPE(wp_executeCommand, ExecuteCommandParams, lsp::Any, "workspace/executeCommand"); + + +DEFINE_NOTIFICATION_TYPE(Notify_sendNotification, ExecuteCommandParams, "workspace/notify")
\ No newline at end of file diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/symbol.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/symbol.h new file mode 100644 index 0000000000..129fb5e822 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/symbol.h @@ -0,0 +1,16 @@ +#pragma once + +#include "LibLsp/lsp/symbol.h" + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +/** + * The workspace symbol request is sent from the client to the server to + * list project-wide symbols matching the query string. + * + * Registration Options: void + */ + +DEFINE_REQUEST_RESPONSE_TYPE(wp_symbol, WorkspaceSymbolParams, std::vector<lsSymbolInformation>, "workspace/symbol"); + diff --git a/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/workspaceFolders.h b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/workspaceFolders.h new file mode 100644 index 0000000000..7cedcfa5f4 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/LibLsp/lsp/workspace/workspaceFolders.h @@ -0,0 +1,34 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" + +#include "LibLsp/lsp/lsDocumentUri.h" +struct WorkspaceFolder { + /** + * The associated URI for this workspace folder. + */ + + lsDocumentUri uri; + + /** + * The name of the workspace folder. Defaults to the uri's basename. + */ + std::string name; + + MAKE_SWAP_METHOD(WorkspaceFolder, uri, name) +}; +MAKE_REFLECT_STRUCT(WorkspaceFolder, uri, name); + + +/** + * The workspace/workspaceFolders request is sent from the server to the client + * to fetch the current open list of workspace folders. + * + * @return null in the response if only a single file is open in the tool, + * an empty array if a workspace is open but no folders are configured, + * the workspace folders otherwise. + */ +DEFINE_REQUEST_RESPONSE_TYPE(WorkspaceFolders, + boost::optional<JsonNull>, boost::optional<std::vector< WorkspaceFolder>>, "workspace/workspaceFolders"); + diff --git a/graphics/asymptote/LspCpp/include/optional.hpp b/graphics/asymptote/LspCpp/include/optional.hpp new file mode 100644 index 0000000000..86e3b407c6 --- /dev/null +++ b/graphics/asymptote/LspCpp/include/optional.hpp @@ -0,0 +1,1846 @@ +// +// Copyright (c) 2014-2021 Martin Moene +// +// https://github.com/martinmoene/optional-lite +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#ifndef NONSTD_OPTIONAL_LITE_HPP +#define NONSTD_OPTIONAL_LITE_HPP + +#define optional_lite_MAJOR 3 +#define optional_lite_MINOR 5 +#define optional_lite_PATCH 0 + +#define optional_lite_VERSION optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY(optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH) + +#define optional_STRINGIFY( x ) optional_STRINGIFY_( x ) +#define optional_STRINGIFY_( x ) #x + +// optional-lite configuration: + +#define optional_OPTIONAL_DEFAULT 0 +#define optional_OPTIONAL_NONSTD 1 +#define optional_OPTIONAL_STD 2 + +// tweak header support: + +#ifdef __has_include +# if __has_include(<nonstd/optional.tweak.hpp>) +# include <nonstd/optional.tweak.hpp> +# endif +#define optional_HAVE_TWEAK_HEADER 1 +#else +#define optional_HAVE_TWEAK_HEADER 0 +//# pragma message("optional.hpp: Note: Tweak header not supported.") +#endif + +// optional selection and configuration: + +#if !defined( optional_CONFIG_SELECT_OPTIONAL ) +# define optional_CONFIG_SELECT_OPTIONAL ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD ) +#endif + +// Control presence of extensions: + +#ifndef optional_CONFIG_NO_EXTENSIONS +#define optional_CONFIG_NO_EXTENSIONS 0 +#endif + +// Control presence of exception handling (try and auto discover): + +#ifndef optional_CONFIG_NO_EXCEPTIONS +# if defined(_MSC_VER) +# include <cstddef> // for _HAS_EXCEPTIONS +# endif +# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) +# define optional_CONFIG_NO_EXCEPTIONS 0 +# else +# define optional_CONFIG_NO_EXCEPTIONS 1 +# endif +#endif + +// C++ language version detection (C++20 is speculative): +// Note: VC14.0/1900 (VS2015) lacks too much from C++14. + +#ifndef optional_CPLUSPLUS +# if defined(_MSVC_LANG ) && !defined(__clang__) +# define optional_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) +# else +# define optional_CPLUSPLUS __cplusplus +# endif +#endif + +#define optional_CPP98_OR_GREATER ( optional_CPLUSPLUS >= 199711L ) +#define optional_CPP11_OR_GREATER ( optional_CPLUSPLUS >= 201103L ) +#define optional_CPP11_OR_GREATER_ ( optional_CPLUSPLUS >= 201103L ) +#define optional_CPP14_OR_GREATER ( optional_CPLUSPLUS >= 201402L ) +#define optional_CPP17_OR_GREATER ( optional_CPLUSPLUS >= 201703L ) +#define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202000L ) + +// C++ language version (represent 98 as 3): + +#define optional_CPLUSPLUS_V ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) ) + +// Use C++17 std::optional if available and requested: + +#if optional_CPP17_OR_GREATER && defined(__has_include ) +# if __has_include( <optional> ) +# define optional_HAVE_STD_OPTIONAL 1 +# else +# define optional_HAVE_STD_OPTIONAL 0 +# endif +#else +# define optional_HAVE_STD_OPTIONAL 0 +#endif + +#define optional_USES_STD_OPTIONAL ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) ) + +// +// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite: +// + +#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES +#define nonstd_lite_HAVE_IN_PLACE_TYPES 1 + +// C++17 std::in_place in <utility>: + +#if optional_CPP17_OR_GREATER + +#include <utility> + +namespace nonstd { + +using std::in_place; +using std::in_place_type; +using std::in_place_index; +using std::in_place_t; +using std::in_place_type_t; +using std::in_place_index_t; + +#define nonstd_lite_in_place_t( T) std::in_place_t +#define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T> +#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K> + +#define nonstd_lite_in_place( T) std::in_place_t{} +#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{} +#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{} + +} // namespace nonstd + +#else // optional_CPP17_OR_GREATER + +#include <cstddef> + +namespace nonstd { +namespace detail { + +template< class T > +struct in_place_type_tag {}; + +template< std::size_t K > +struct in_place_index_tag {}; + +} // namespace detail + +struct in_place_t {}; + +template< class T > +inline in_place_t in_place( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() ) +{ + return in_place_t(); +} + +template< std::size_t K > +inline in_place_t in_place( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() ) +{ + return in_place_t(); +} + +template< class T > +inline in_place_t in_place_type( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() ) +{ + return in_place_t(); +} + +template< std::size_t K > +inline in_place_t in_place_index( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() ) +{ + return in_place_t(); +} + +// mimic templated typedef: + +#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) +#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) +#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> ) + +#define nonstd_lite_in_place( T) nonstd::in_place_type<T> +#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T> +#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K> + +} // namespace nonstd + +#endif // optional_CPP17_OR_GREATER +#endif // nonstd_lite_HAVE_IN_PLACE_TYPES + +// +// Using std::optional: +// + +#if optional_USES_STD_OPTIONAL + +#include <optional> + +namespace nonstd { + + using std::optional; + using std::bad_optional_access; + using std::hash; + + using std::nullopt; + using std::nullopt_t; + + using std::operator==; + using std::operator!=; + using std::operator<; + using std::operator<=; + using std::operator>; + using std::operator>=; + using std::make_optional; + using std::swap; +} + +#else // optional_USES_STD_OPTIONAL + +#include <cassert> +#include <utility> + +// optional-lite alignment configuration: + +#ifndef optional_CONFIG_MAX_ALIGN_HACK +# define optional_CONFIG_MAX_ALIGN_HACK 0 +#endif + +#ifndef optional_CONFIG_ALIGN_AS +// no default, used in #if defined() +#endif + +#ifndef optional_CONFIG_ALIGN_AS_FALLBACK +# define optional_CONFIG_ALIGN_AS_FALLBACK double +#endif + +// Compiler warning suppression: + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wundef" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wundef" +#elif defined(_MSC_VER ) +# pragma warning( push ) +#endif + +// half-open range [lo..hi): +#define optional_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) + +// Compiler versions: +// +// MSVC++ 6.0 _MSC_VER == 1200 optional_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) +// MSVC++ 7.0 _MSC_VER == 1300 optional_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) +// MSVC++ 7.1 _MSC_VER == 1310 optional_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) +// MSVC++ 8.0 _MSC_VER == 1400 optional_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) +// MSVC++ 9.0 _MSC_VER == 1500 optional_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) +// MSVC++ 10.0 _MSC_VER == 1600 optional_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) +// MSVC++ 11.0 _MSC_VER == 1700 optional_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) +// MSVC++ 12.0 _MSC_VER == 1800 optional_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) +// MSVC++ 14.0 _MSC_VER == 1900 optional_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) +// MSVC++ 14.1 _MSC_VER >= 1910 optional_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) +// MSVC++ 14.2 _MSC_VER >= 1920 optional_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) + +#if defined(_MSC_VER ) && !defined(__clang__) +# define optional_COMPILER_MSVC_VER (_MSC_VER ) +# define optional_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) +#else +# define optional_COMPILER_MSVC_VER 0 +# define optional_COMPILER_MSVC_VERSION 0 +#endif + +#define optional_COMPILER_VERSION( major, minor, patch ) ( 10 * (10 * (major) + (minor) ) + (patch) ) + +#if defined(__GNUC__) && !defined(__clang__) +# define optional_COMPILER_GNUC_VERSION optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#else +# define optional_COMPILER_GNUC_VERSION 0 +#endif + +#if defined(__clang__) +# define optional_COMPILER_CLANG_VERSION optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) +#else +# define optional_COMPILER_CLANG_VERSION 0 +#endif + +#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 ) +# pragma warning( disable: 4345 ) // initialization behavior changed +#endif + +#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 ) +# pragma warning( disable: 4814 ) // in C++14 'constexpr' will not imply 'const' +#endif + +// Presence of language and library features: + +#define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE ) + +#ifdef _HAS_CPP0X +# define optional_HAS_CPP0X _HAS_CPP0X +#else +# define optional_HAS_CPP0X 0 +#endif + +// Unless defined otherwise below, consider VC14 as C++11 for optional-lite: + +#if optional_COMPILER_MSVC_VER >= 1900 +# undef optional_CPP11_OR_GREATER +# define optional_CPP11_OR_GREATER 1 +#endif + +#define optional_CPP11_90 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500) +#define optional_CPP11_100 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600) +#define optional_CPP11_110 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700) +#define optional_CPP11_120 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800) +#define optional_CPP11_140 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900) +#define optional_CPP11_141 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910) + +#define optional_CPP14_000 (optional_CPP14_OR_GREATER) +#define optional_CPP17_000 (optional_CPP17_OR_GREATER) + +// clang >= 2.9, gcc >= 4.9, msvc >= vc14.0/1900 (vs15): +#define optional_CPP11_140_C290_G490 ((optional_CPP11_OR_GREATER_ && (optional_COMPILER_CLANG_VERSION >= 290 || optional_COMPILER_GNUC_VERSION >= 490)) || (optional_COMPILER_MSVC_VER >= 1900)) + +// clang >= 3.5, msvc >= vc11 (vs12): +#define optional_CPP11_110_C350 ( optional_CPP11_110 && !optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) ) + +// clang >= 3.5, gcc >= 5.0, msvc >= vc11 (vs12): +#define optional_CPP11_110_C350_G500 \ + ( optional_CPP11_110 && \ + !( optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) \ + || optional_BETWEEN( optional_COMPILER_GNUC_VERSION , 1, 500 ) ) ) + +// Presence of C++11 language features: + +#define optional_HAVE_CONSTEXPR_11 optional_CPP11_140 +#define optional_HAVE_IS_DEFAULT optional_CPP11_140 +#define optional_HAVE_NOEXCEPT optional_CPP11_140 +#define optional_HAVE_NULLPTR optional_CPP11_100 +#define optional_HAVE_REF_QUALIFIER optional_CPP11_140_C290_G490 +#define optional_HAVE_STATIC_ASSERT optional_CPP11_110 +#define optional_HAVE_INITIALIZER_LIST optional_CPP11_140 + +// Presence of C++14 language features: + +#define optional_HAVE_CONSTEXPR_14 optional_CPP14_000 + +// Presence of C++17 language features: + +#define optional_HAVE_NODISCARD optional_CPP17_000 + +// Presence of C++ library features: + +#define optional_HAVE_CONDITIONAL optional_CPP11_120 +#define optional_HAVE_REMOVE_CV optional_CPP11_120 +#define optional_HAVE_TYPE_TRAITS optional_CPP11_90 + +#define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION ) +#define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION ) + +#define optional_HAVE_IS_ASSIGNABLE optional_CPP11_110_C350 +#define optional_HAVE_IS_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350 +#define optional_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE optional_CPP11_110_C350 +#define optional_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350 +#define optional_HAVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE optional_CPP11_110_C350_G500 +#define optional_HAVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350_G500 + +// C++ feature usage: + +#if optional_HAVE( CONSTEXPR_11 ) +# define optional_constexpr constexpr +#else +# define optional_constexpr /*constexpr*/ +#endif + +#if optional_HAVE( IS_DEFAULT ) +# define optional_is_default = default; +#else +# define optional_is_default {} +#endif + +#if optional_HAVE( CONSTEXPR_14 ) +# define optional_constexpr14 constexpr +#else +# define optional_constexpr14 /*constexpr*/ +#endif + +#if optional_HAVE( NODISCARD ) +# define optional_nodiscard [[nodiscard]] +#else +# define optional_nodiscard /*[[nodiscard]]*/ +#endif + +#if optional_HAVE( NOEXCEPT ) +# define optional_noexcept noexcept +#else +# define optional_noexcept /*noexcept*/ +#endif + +#if optional_HAVE( NULLPTR ) +# define optional_nullptr nullptr +#else +# define optional_nullptr NULL +#endif + +#if optional_HAVE( REF_QUALIFIER ) +// NOLINTNEXTLINE( bugprone-macro-parentheses ) +# define optional_ref_qual & +# define optional_refref_qual && +#else +# define optional_ref_qual /*&*/ +# define optional_refref_qual /*&&*/ +#endif + +#if optional_HAVE( STATIC_ASSERT ) +# define optional_static_assert(expr, text) static_assert(expr, text); +#else +# define optional_static_assert(expr, text) /*static_assert(expr, text);*/ +#endif + +// additional includes: + +#if optional_CONFIG_NO_EXCEPTIONS +// already included: <cassert> +#else +# include <stdexcept> +#endif + +#if optional_CPP11_OR_GREATER +# include <functional> +#endif + +#if optional_HAVE( INITIALIZER_LIST ) +# include <initializer_list> +#endif + +#if optional_HAVE( TYPE_TRAITS ) +# include <type_traits> +#elif optional_HAVE( TR1_TYPE_TRAITS ) +# include <tr1/type_traits> +#endif + +// Method enabling + +#if optional_CPP11_OR_GREATER + +#define optional_REQUIRES_0(...) \ + template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 > + +#define optional_REQUIRES_T(...) \ + , typename std::enable_if< (__VA_ARGS__), int >::type = 0 + +#define optional_REQUIRES_R(R, ...) \ + typename std::enable_if< (__VA_ARGS__), R>::type + +#define optional_REQUIRES_A(...) \ + , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr + +#endif + +// +// optional: +// + +namespace nonstd { namespace optional_lite { + +namespace std11 { + +template< class T, T v > struct integral_constant { enum { value = v }; }; +template< bool B > struct bool_constant : integral_constant<bool, B>{}; + +typedef bool_constant< true > true_type; +typedef bool_constant< false > false_type; + +#if optional_CPP11_OR_GREATER + using std::move; +#else + template< typename T > T & move( T & t ) { return t; } +#endif + +#if optional_HAVE( CONDITIONAL ) + using std::conditional; +#else + template< bool B, typename T, typename F > struct conditional { typedef T type; }; + template< typename T, typename F > struct conditional<false, T, F> { typedef F type; }; +#endif // optional_HAVE_CONDITIONAL + +#if optional_HAVE( IS_ASSIGNABLE ) + using std::is_assignable; +#else + template< class T, class U > struct is_assignable : std11::true_type{}; +#endif + +#if optional_HAVE( IS_MOVE_CONSTRUCTIBLE ) + using std::is_move_constructible; +#else + template< class T > struct is_move_constructible : std11::true_type{}; +#endif + +#if optional_HAVE( IS_NOTHROW_MOVE_ASSIGNABLE ) + using std::is_nothrow_move_assignable; +#else + template< class T > struct is_nothrow_move_assignable : std11::true_type{}; +#endif + +#if optional_HAVE( IS_NOTHROW_MOVE_CONSTRUCTIBLE ) + using std::is_nothrow_move_constructible; +#else + template< class T > struct is_nothrow_move_constructible : std11::true_type{}; +#endif + +#if optional_HAVE( IS_TRIVIALLY_COPY_CONSTRUCTIBLE ) + using std::is_trivially_copy_constructible; +#else + template< class T > struct is_trivially_copy_constructible : std11::true_type{}; +#endif + +#if optional_HAVE( IS_TRIVIALLY_MOVE_CONSTRUCTIBLE ) + using std::is_trivially_move_constructible; +#else + template< class T > struct is_trivially_move_constructible : std11::true_type{}; +#endif + +} // namespace std11 + +#if optional_CPP11_OR_GREATER + +/// type traits C++17: + +namespace std17 { + +#if optional_CPP17_OR_GREATER + +using std::is_swappable; +using std::is_nothrow_swappable; + +#elif optional_CPP11_OR_GREATER + +namespace detail { + +using std::swap; + +struct is_swappable +{ + template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) > + static std11::true_type test( int /*unused*/ ); + + template< typename > + static std11::false_type test(...); +}; + +struct is_nothrow_swappable +{ + // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015): + + template< typename T > + static constexpr bool satisfies() + { + return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) ); + } + + template< typename T > + static auto test( int /*unused*/ ) -> std11::integral_constant<bool, satisfies<T>()>{} + + template< typename > + static auto test(...) -> std11::false_type; +}; + +} // namespace detail + +// is [nothow] swappable: + +template< typename T > +struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){}; + +template< typename T > +struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){}; + +#endif // optional_CPP17_OR_GREATER + +} // namespace std17 + +/// type traits C++20: + +namespace std20 { + +template< typename T > +struct remove_cvref +{ + typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type; +}; + +} // namespace std20 + +#endif // optional_CPP11_OR_GREATER + +/// class optional + +template< typename T > +class optional; + +namespace detail { + +// C++11 emulation: + +struct nulltype{}; + +template< typename Head, typename Tail > +struct typelist +{ + typedef Head head; + typedef Tail tail; +}; + +#if optional_CONFIG_MAX_ALIGN_HACK + +// Max align, use most restricted type for alignment: + +#define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ ) +#define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line ) +#define optional_UNIQUE3( name, line ) name ## line + +#define optional_ALIGN_TYPE( type ) \ + type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st ) + +template< typename T > +struct struct_t { T _; }; + +union max_align_t +{ + optional_ALIGN_TYPE( char ); + optional_ALIGN_TYPE( short int ); + optional_ALIGN_TYPE( int ); + optional_ALIGN_TYPE( long int ); + optional_ALIGN_TYPE( float ); + optional_ALIGN_TYPE( double ); + optional_ALIGN_TYPE( long double ); + optional_ALIGN_TYPE( char * ); + optional_ALIGN_TYPE( short int * ); + optional_ALIGN_TYPE( int * ); + optional_ALIGN_TYPE( long int * ); + optional_ALIGN_TYPE( float * ); + optional_ALIGN_TYPE( double * ); + optional_ALIGN_TYPE( long double * ); + optional_ALIGN_TYPE( void * ); + +#ifdef HAVE_LONG_LONG + optional_ALIGN_TYPE( long long ); +#endif + + struct Unknown; + + Unknown ( * optional_UNIQUE(_) )( Unknown ); + Unknown * Unknown::* optional_UNIQUE(_); + Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown ); + + struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_); + struct_t< Unknown * Unknown::* > optional_UNIQUE(_); + struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_); +}; + +#undef optional_UNIQUE +#undef optional_UNIQUE2 +#undef optional_UNIQUE3 + +#undef optional_ALIGN_TYPE + +#elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK + +// Use user-specified type for alignment: + +#define optional_ALIGN_AS( unused ) \ + optional_CONFIG_ALIGN_AS + +#else // optional_CONFIG_MAX_ALIGN_HACK + +// Determine POD type to use for alignment: + +#define optional_ALIGN_AS( to_align ) \ + typename type_of_size< alignment_types, alignment_of< to_align >::value >::type + +template< typename T > +struct alignment_of; + +template< typename T > +struct alignment_of_hack +{ + char c; + T t; + alignment_of_hack(); +}; + +template< size_t A, size_t S > +struct alignment_logic +{ + enum { value = A < S ? A : S }; +}; + +template< typename T > +struct alignment_of +{ + enum { value = alignment_logic< + sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value }; +}; + +template< typename List, size_t N > +struct type_of_size +{ + typedef typename std11::conditional< + N == sizeof( typename List::head ), + typename List::head, + typename type_of_size<typename List::tail, N >::type >::type type; +}; + +template< size_t N > +struct type_of_size< nulltype, N > +{ + typedef optional_CONFIG_ALIGN_AS_FALLBACK type; +}; + +template< typename T> +struct struct_t { T _; }; + +#define optional_ALIGN_TYPE( type ) \ + typelist< type , typelist< struct_t< type > + +struct Unknown; + +typedef + optional_ALIGN_TYPE( char ), + optional_ALIGN_TYPE( short ), + optional_ALIGN_TYPE( int ), + optional_ALIGN_TYPE( long ), + optional_ALIGN_TYPE( float ), + optional_ALIGN_TYPE( double ), + optional_ALIGN_TYPE( long double ), + + optional_ALIGN_TYPE( char *), + optional_ALIGN_TYPE( short * ), + optional_ALIGN_TYPE( int * ), + optional_ALIGN_TYPE( long * ), + optional_ALIGN_TYPE( float * ), + optional_ALIGN_TYPE( double * ), + optional_ALIGN_TYPE( long double * ), + + optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ), + optional_ALIGN_TYPE( Unknown * Unknown::* ), + optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ), + + nulltype + > > > > > > > > > > > > > > + > > > > > > > > > > > > > > + > > > > > > + alignment_types; + +#undef optional_ALIGN_TYPE + +#endif // optional_CONFIG_MAX_ALIGN_HACK + +/// C++03 constructed union to hold value. + +template< typename T > +union storage_t +{ +//private: +// template< typename > friend class optional; + + typedef T value_type; + + storage_t() optional_is_default + + explicit storage_t( value_type const & v ) + { + construct_value( v ); + } + + void construct_value( value_type const & v ) + { + ::new( value_ptr() ) value_type( v ); + } + +#if optional_CPP11_OR_GREATER + + explicit storage_t( value_type && v ) + { + construct_value( std::move( v ) ); + } + + void construct_value( value_type && v ) + { + ::new( value_ptr() ) value_type( std::move( v ) ); + } + + template< class... Args > + storage_t( nonstd_lite_in_place_t(T), Args&&... args ) + { + emplace( std::forward<Args>(args)... ); + } + + template< class... Args > + void emplace( Args&&... args ) + { + ::new( value_ptr() ) value_type( std::forward<Args>(args)... ); + } + + template< class U, class... Args > + void emplace( std::initializer_list<U> il, Args&&... args ) + { + ::new( value_ptr() ) value_type( il, std::forward<Args>(args)... ); + } + +#endif + + void destruct_value() + { + value_ptr()->~T(); + } + + optional_nodiscard value_type const * value_ptr() const + { + return as<value_type>(); + } + + value_type * value_ptr() + { + return as<value_type>(); + } + + optional_nodiscard value_type const & value() const optional_ref_qual + { + return * value_ptr(); + } + + value_type & value() optional_ref_qual + { + return * value_ptr(); + } + +#if optional_HAVE( REF_QUALIFIER ) + + optional_nodiscard value_type const && value() const optional_refref_qual + { + return std::move( value() ); + } + + value_type && value() optional_refref_qual + { + return std::move( value() ); + } + +#endif + +#if optional_CPP11_OR_GREATER + + using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type; + aligned_storage_t data; + +#elif optional_CONFIG_MAX_ALIGN_HACK + + typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t; + + max_align_t hack; + aligned_storage_t data; + +#else + typedef optional_ALIGN_AS(value_type) align_as_type; + + typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t; + aligned_storage_t data; + +# undef optional_ALIGN_AS + +#endif // optional_CONFIG_MAX_ALIGN_HACK + + optional_nodiscard void * ptr() optional_noexcept + { + return &data; + } + + optional_nodiscard void const * ptr() const optional_noexcept + { + return &data; + } + + template <typename U> + optional_nodiscard U * as() + { + return reinterpret_cast<U*>( ptr() ); + } + + template <typename U> + optional_nodiscard U const * as() const + { + return reinterpret_cast<U const *>( ptr() ); + } +}; + +} // namespace detail + +/// disengaged state tag + +struct nullopt_t +{ + struct init{}; + explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {} +}; + +#if optional_HAVE( CONSTEXPR_11 ) +constexpr nullopt_t nullopt{ nullopt_t::init{} }; +#else +// extra parenthesis to prevent the most vexing parse: +const nullopt_t nullopt(( nullopt_t::init() )); +#endif + +/// optional access error + +#if ! optional_CONFIG_NO_EXCEPTIONS + +class bad_optional_access : public std::logic_error +{ +public: + explicit bad_optional_access() + : logic_error( "bad optional access" ) {} +}; + +#endif //optional_CONFIG_NO_EXCEPTIONS + +/// optional + +template< typename T> +class optional +{ + optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, nullopt_t>::value ), + "T in optional<T> must not be of type 'nullopt_t'.") + + optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, in_place_t>::value ), + "T in optional<T> must not be of type 'in_place_t'.") + + optional_static_assert(( std::is_object<T>::value && std::is_destructible<T>::value && !std::is_array<T>::value ), + "T in optional<T> must meet the Cpp17Destructible requirements.") + +private: + template< typename > friend class optional; + + typedef void (optional::*safe_bool)() const; + +public: + typedef T value_type; + + // x.x.3.1, constructors + + // 1a - default construct + optional_constexpr optional() optional_noexcept + : has_value_( false ) + , contained() + {} + + // 1b - construct explicitly empty + // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions ) + optional_constexpr optional( nullopt_t /*unused*/ ) optional_noexcept + : has_value_( false ) + , contained() + {} + + // 2 - copy-construct +#if optional_CPP11_OR_GREATER + // template< typename U = T + // optional_REQUIRES_T( + // std::is_copy_constructible<U>::value + // || std11::is_trivially_copy_constructible<U>::value + // ) + // > +#endif + optional_constexpr14 optional( optional const & other ) + : has_value_( other.has_value() ) + { + if ( other.has_value() ) + { + contained.construct_value( other.contained.value() ); + } + } + +#if optional_CPP11_OR_GREATER + + // 3 (C++11) - move-construct from optional + template< typename U = T + optional_REQUIRES_T( + std11::is_move_constructible<U>::value + || std11::is_trivially_move_constructible<U>::value + ) + > + optional_constexpr14 optional( optional && other ) + // NOLINTNEXTLINE( performance-noexcept-move-constructor ) + noexcept( std11::is_nothrow_move_constructible<T>::value ) + : has_value_( other.has_value() ) + { + if ( other.has_value() ) + { + contained.construct_value( std::move( other.contained.value() ) ); + } + } + + // 4a (C++11) - explicit converting copy-construct from optional + template< typename U + optional_REQUIRES_T( + std::is_constructible<T, U const &>::value + && !std::is_constructible<T, optional<U> & >::value + && !std::is_constructible<T, optional<U> && >::value + && !std::is_constructible<T, optional<U> const & >::value + && !std::is_constructible<T, optional<U> const && >::value + && !std::is_convertible< optional<U> & , T>::value + && !std::is_convertible< optional<U> && , T>::value + && !std::is_convertible< optional<U> const & , T>::value + && !std::is_convertible< optional<U> const &&, T>::value + && !std::is_convertible< U const & , T>::value /*=> explicit */ + ) + > + explicit optional( optional<U> const & other ) + : has_value_( other.has_value() ) + { + if ( other.has_value() ) + { + contained.construct_value( T{ other.contained.value() } ); + } + } +#endif // optional_CPP11_OR_GREATER + + // 4b (C++98 and later) - non-explicit converting copy-construct from optional + template< typename U +#if optional_CPP11_OR_GREATER + optional_REQUIRES_T( + std::is_constructible<T, U const &>::value + && !std::is_constructible<T, optional<U> & >::value + && !std::is_constructible<T, optional<U> && >::value + && !std::is_constructible<T, optional<U> const & >::value + && !std::is_constructible<T, optional<U> const && >::value + && !std::is_convertible< optional<U> & , T>::value + && !std::is_convertible< optional<U> && , T>::value + && !std::is_convertible< optional<U> const & , T>::value + && !std::is_convertible< optional<U> const &&, T>::value + && std::is_convertible< U const & , T>::value /*=> non-explicit */ + ) +#endif // optional_CPP11_OR_GREATER + > + // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions ) + /*non-explicit*/ optional( optional<U> const & other ) + : has_value_( other.has_value() ) + { + if ( other.has_value() ) + { + contained.construct_value( other.contained.value() ); + } + } + +#if optional_CPP11_OR_GREATER + + // 5a (C++11) - explicit converting move-construct from optional + template< typename U + optional_REQUIRES_T( + std::is_constructible<T, U &&>::value + && !std::is_constructible<T, optional<U> & >::value + && !std::is_constructible<T, optional<U> && >::value + && !std::is_constructible<T, optional<U> const & >::value + && !std::is_constructible<T, optional<U> const && >::value + && !std::is_convertible< optional<U> & , T>::value + && !std::is_convertible< optional<U> && , T>::value + && !std::is_convertible< optional<U> const & , T>::value + && !std::is_convertible< optional<U> const &&, T>::value + && !std::is_convertible< U &&, T>::value /*=> explicit */ + ) + > + explicit optional( optional<U> && other + ) + : has_value_( other.has_value() ) + { + if ( other.has_value() ) + { + contained.construct_value( T{ std::move( other.contained.value() ) } ); + } + } + + // 5a (C++11) - non-explicit converting move-construct from optional + template< typename U + optional_REQUIRES_T( + std::is_constructible<T, U &&>::value + && !std::is_constructible<T, optional<U> & >::value + && !std::is_constructible<T, optional<U> && >::value + && !std::is_constructible<T, optional<U> const & >::value + && !std::is_constructible<T, optional<U> const && >::value + && !std::is_convertible< optional<U> & , T>::value + && !std::is_convertible< optional<U> && , T>::value + && !std::is_convertible< optional<U> const & , T>::value + && !std::is_convertible< optional<U> const &&, T>::value + && std::is_convertible< U &&, T>::value /*=> non-explicit */ + ) + > + // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions ) + /*non-explicit*/ optional( optional<U> && other ) + : has_value_( other.has_value() ) + { + if ( other.has_value() ) + { + contained.construct_value( std::move( other.contained.value() ) ); + } + } + + // 6 (C++11) - in-place construct + template< typename... Args + optional_REQUIRES_T( + std::is_constructible<T, Args&&...>::value + ) + > + optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args ) + : has_value_( true ) + , contained( in_place, std::forward<Args>(args)... ) + {} + + // 7 (C++11) - in-place construct, initializer-list + template< typename U, typename... Args + optional_REQUIRES_T( + std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value + ) + > + optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args ) + : has_value_( true ) + , contained( T( il, std::forward<Args>(args)...) ) + {} + + // 8a (C++11) - explicit move construct from value + template< typename U = T + optional_REQUIRES_T( + std::is_constructible<T, U&&>::value + && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value + && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value + && !std::is_convertible<U&&, T>::value /*=> explicit */ + ) + > + optional_constexpr explicit optional( U && value ) + : has_value_( true ) + , contained( nonstd_lite_in_place(T), std::forward<U>( value ) ) + {} + + // 8b (C++11) - non-explicit move construct from value + template< typename U = T + optional_REQUIRES_T( + std::is_constructible<T, U&&>::value + && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value + && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value + && std::is_convertible<U&&, T>::value /*=> non-explicit */ + ) + > + // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions ) + optional_constexpr /*non-explicit*/ optional( U && value ) + : has_value_( true ) + , contained( nonstd_lite_in_place(T), std::forward<U>( value ) ) + {} + +#else // optional_CPP11_OR_GREATER + + // 8 (C++98) + optional( value_type const & value ) + : has_value_( true ) + , contained( value ) + {} + +#endif // optional_CPP11_OR_GREATER + + // x.x.3.2, destructor + + ~optional() + { + if ( has_value() ) + { + contained.destruct_value(); + } + } + + // x.x.3.3, assignment + + // 1 (C++98and later) - assign explicitly empty + optional & operator=( nullopt_t /*unused*/) optional_noexcept + { + reset(); + return *this; + } + + // 2 (C++98and later) - copy-assign from optional +#if optional_CPP11_OR_GREATER + // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) + optional_REQUIRES_R( + optional &, + true +// std::is_copy_constructible<T>::value +// && std::is_copy_assignable<T>::value + ) + operator=( optional const & other ) + noexcept( + std11::is_nothrow_move_assignable<T>::value + && std11::is_nothrow_move_constructible<T>::value + ) +#else + optional & operator=( optional const & other ) +#endif + { + if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); } + else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( *other ); } + else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = *other; } + return *this; + } + +#if optional_CPP11_OR_GREATER + + // 3 (C++11) - move-assign from optional + // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) + optional_REQUIRES_R( + optional &, + true +// std11::is_move_constructible<T>::value +// && std::is_move_assignable<T>::value + ) + operator=( optional && other ) noexcept + { + if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); } + else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std::move( *other ) ); } + else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = std::move( *other ); } + return *this; + } + + // 4 (C++11) - move-assign from value + template< typename U = T > + // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) + optional_REQUIRES_R( + optional &, + std::is_constructible<T , U>::value + && std11::is_assignable<T&, U>::value + && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value + && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value + && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value) + ) + operator=( U && value ) + { + if ( has_value() ) + { + contained.value() = std::forward<U>( value ); + } + else + { + initialize( T( std::forward<U>( value ) ) ); + } + return *this; + } + +#else // optional_CPP11_OR_GREATER + + // 4 (C++98) - copy-assign from value + template< typename U /*= T*/ > + optional & operator=( U const & value ) + { + if ( has_value() ) contained.value() = value; + else initialize( T( value ) ); + return *this; + } + +#endif // optional_CPP11_OR_GREATER + + // 5 (C++98 and later) - converting copy-assign from optional + template< typename U > +#if optional_CPP11_OR_GREATER + // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) + optional_REQUIRES_R( + optional&, + std::is_constructible< T , U const &>::value + && std11::is_assignable< T&, U const &>::value + && !std::is_constructible<T, optional<U> & >::value + && !std::is_constructible<T, optional<U> && >::value + && !std::is_constructible<T, optional<U> const & >::value + && !std::is_constructible<T, optional<U> const && >::value + && !std::is_convertible< optional<U> & , T>::value + && !std::is_convertible< optional<U> && , T>::value + && !std::is_convertible< optional<U> const & , T>::value + && !std::is_convertible< optional<U> const &&, T>::value + && !std11::is_assignable< T&, optional<U> & >::value + && !std11::is_assignable< T&, optional<U> && >::value + && !std11::is_assignable< T&, optional<U> const & >::value + && !std11::is_assignable< T&, optional<U> const && >::value + ) +#else + optional& +#endif // optional_CPP11_OR_GREATER + operator=( optional<U> const & other ) + { + return *this = optional( other ); + } + +#if optional_CPP11_OR_GREATER + + // 6 (C++11) - converting move-assign from optional + template< typename U > + // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) + optional_REQUIRES_R( + optional&, + std::is_constructible< T , U>::value + && std11::is_assignable< T&, U>::value + && !std::is_constructible<T, optional<U> & >::value + && !std::is_constructible<T, optional<U> && >::value + && !std::is_constructible<T, optional<U> const & >::value + && !std::is_constructible<T, optional<U> const && >::value + && !std::is_convertible< optional<U> & , T>::value + && !std::is_convertible< optional<U> && , T>::value + && !std::is_convertible< optional<U> const & , T>::value + && !std::is_convertible< optional<U> const &&, T>::value + && !std11::is_assignable< T&, optional<U> & >::value + && !std11::is_assignable< T&, optional<U> && >::value + && !std11::is_assignable< T&, optional<U> const & >::value + && !std11::is_assignable< T&, optional<U> const && >::value + ) + operator=( optional<U> && other ) + { + return *this = optional( std::move( other ) ); + } + + // 7 (C++11) - emplace + template< typename... Args + optional_REQUIRES_T( + std::is_constructible<T, Args&&...>::value + ) + > + T& emplace( Args&&... args ) + { + *this = nullopt; + contained.emplace( std::forward<Args>(args)... ); + has_value_ = true; + return contained.value(); + } + + // 8 (C++11) - emplace, initializer-list + template< typename U, typename... Args + optional_REQUIRES_T( + std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value + ) + > + T& emplace( std::initializer_list<U> il, Args&&... args ) + { + *this = nullopt; + contained.emplace( il, std::forward<Args>(args)... ); + has_value_ = true; + return contained.value(); + } + +#endif // optional_CPP11_OR_GREATER + + // x.x.3.4, swap + + void swap( optional & other ) +#if optional_CPP11_OR_GREATER + noexcept( + std11::is_nothrow_move_constructible<T>::value + && std17::is_nothrow_swappable<T>::value + ) +#endif + { + using std::swap; + if ( (has_value() == true ) && (other.has_value() == true ) ) { swap( **this, *other ); } + else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std11::move(*other) ); other.reset(); } + else if ( (has_value() == true ) && (other.has_value() == false) ) { other.initialize( std11::move(**this) ); reset(); } + } + + // x.x.3.5, observers + + optional_constexpr value_type const * operator ->() const + { + return assert( has_value() ), + contained.value_ptr(); + } + + optional_constexpr14 value_type * operator ->() + { + return assert( has_value() ), + contained.value_ptr(); + } + + optional_constexpr value_type const & operator *() const optional_ref_qual + { + return assert( has_value() ), + contained.value(); + } + + optional_constexpr14 value_type & operator *() optional_ref_qual + { + return assert( has_value() ), + contained.value(); + } + +#if optional_HAVE( REF_QUALIFIER ) + + optional_constexpr value_type const && operator *() const optional_refref_qual + { + return std::move( **this ); + } + + optional_constexpr14 value_type && operator *() optional_refref_qual + { + return std::move( **this ); + } + +#endif + +#if optional_CPP11_OR_GREATER + optional_constexpr explicit operator bool() const optional_noexcept + { + return has_value(); + } +#else + optional_constexpr operator safe_bool() const optional_noexcept + { + return has_value() ? &optional::this_type_does_not_support_comparisons : 0; + } +#endif + + // NOLINTNEXTLINE( modernize-use-nodiscard ) + /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept + { + return has_value_; + } + + // NOLINTNEXTLINE( modernize-use-nodiscard ) + /*optional_nodiscard*/ optional_constexpr14 value_type const & value() const optional_ref_qual + { +#if optional_CONFIG_NO_EXCEPTIONS + assert( has_value() ); +#else + if ( ! has_value() ) + { + throw bad_optional_access(); + } +#endif + return contained.value(); + } + + optional_constexpr14 value_type & value() optional_ref_qual + { +#if optional_CONFIG_NO_EXCEPTIONS + assert( has_value() ); +#else + if ( ! has_value() ) + { + throw bad_optional_access(); + } +#endif + return contained.value(); + } + +#if optional_HAVE( REF_QUALIFIER ) && ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 ) + + // NOLINTNEXTLINE( modernize-use-nodiscard ) + /*optional_nodiscard*/ optional_constexpr value_type const && value() const optional_refref_qual + { + return std::move( value() ); + } + + optional_constexpr14 value_type && value() optional_refref_qual + { + return std::move( value() ); + } + +#endif + +#if optional_HAVE( REF_QUALIFIER ) + + template< typename U > + optional_constexpr value_type value_or( U && v ) const optional_ref_qual + { + return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) ); + } + + template< typename U > + optional_constexpr14 value_type value_or( U && v ) optional_refref_qual + { +#if optional_COMPILER_CLANG_VERSION + return has_value() ? /*std::move*/( contained.value() ) : static_cast<T>(std::forward<U>( v ) ); +#else + return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) ); +#endif + } + +#else + + template< typename U > + optional_constexpr value_type value_or( U const & v ) const + { + return has_value() ? contained.value() : static_cast<value_type>( v ); + } + +#endif // optional_HAVE( REF_QUALIFIER ) + +#if !optional_CONFIG_NO_EXTENSIONS +#if optional_HAVE( REF_QUALIFIER ) + + template< typename F > + optional_constexpr value_type value_or_eval( F f ) const & + { + return has_value() ? contained.value() : f(); + } + + template< typename F > + optional_constexpr14 value_type value_or_eval( F f ) && + { + if ( has_value() ) + { + return std::move( contained.value() ); + } + else + { + return f(); + } + } + +#else + + template< typename F > + optional_constexpr value_type value_or_eval( F f ) const + { + return has_value() ? contained.value() : f(); + } + +#endif // optional_HAVE( REF_QUALIFIER ) +#endif // !optional_CONFIG_NO_EXTENSIONS + + // x.x.3.6, modifiers + + void reset() optional_noexcept + { + if ( has_value() ) + { + contained.destruct_value(); + } + + has_value_ = false; + } + +private: + void this_type_does_not_support_comparisons() const {} + + template< typename V > + void initialize( V const & value ) + { + assert( ! has_value() ); + contained.construct_value( value ); + has_value_ = true; + } + +#if optional_CPP11_OR_GREATER + template< typename V > + void initialize( V && value ) + { + assert( ! has_value() ); + contained.construct_value( std::move( value ) ); + has_value_ = true; + } + +#endif + +private: + bool has_value_; + detail::storage_t< value_type > contained; + +}; + +// Relational operators + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y ) +{ + return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y ) +{ + return !(x == y); +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y ) +{ + return (!y) ? false : (!x) ? true : *x < *y; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y ) +{ + return (y < x); +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y ) +{ + return !(y < x); +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y ) +{ + return !(x < y); +} + +// Comparison with nullopt + +template< typename T > +optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept +{ + return (!x); +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept +{ + return (!x); +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept +{ + return bool(x); +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept +{ + return bool(x); +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept +{ + return false; +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept +{ + return bool(x); +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept +{ + return (!x); +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept +{ + return true; +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept +{ + return bool(x); +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept +{ + return false; +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept +{ + return true; +} + +template< typename T > +optional_nodiscard optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept +{ + return (!x); +} + +// Comparison with T + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, U const & v ) +{ + return bool(x) ? *x == v : false; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator==( U const & v, optional<T> const & x ) +{ + return bool(x) ? v == *x : false; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, U const & v ) +{ + return bool(x) ? *x != v : true; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator!=( U const & v, optional<T> const & x ) +{ + return bool(x) ? v != *x : true; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, U const & v ) +{ + return bool(x) ? *x < v : true; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator<( U const & v, optional<T> const & x ) +{ + return bool(x) ? v < *x : false; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, U const & v ) +{ + return bool(x) ? *x <= v : true; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator<=( U const & v, optional<T> const & x ) +{ + return bool(x) ? v <= *x : false; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, U const & v ) +{ + return bool(x) ? *x > v : false; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator>( U const & v, optional<T> const & x ) +{ + return bool(x) ? v > *x : true; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, U const & v ) +{ + return bool(x) ? *x >= v : false; +} + +template< typename T, typename U > +optional_nodiscard optional_constexpr bool operator>=( U const & v, optional<T> const & x ) +{ + return bool(x) ? v >= *x : true; +} + +// Specialized algorithms + +template< typename T +#if optional_CPP11_OR_GREATER + optional_REQUIRES_T( + std11::is_move_constructible<T>::value + && std17::is_swappable<T>::value ) +#endif +> +void swap( optional<T> & x, optional<T> & y ) +#if optional_CPP11_OR_GREATER + noexcept( noexcept( x.swap(y) ) ) +#endif +{ + x.swap( y ); +} + +#if optional_CPP11_OR_GREATER + +template< typename T > +optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value ) +{ + return optional< typename std::decay<T>::type >( std::forward<T>( value ) ); +} + +template< typename T, typename...Args > +optional_constexpr optional<T> make_optional( Args&&... args ) +{ + return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...); +} + +template< typename T, typename U, typename... Args > +optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args ) +{ + return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...); +} + +#else + +template< typename T > +optional<T> make_optional( T const & value ) +{ + return optional<T>( value ); +} + +#endif // optional_CPP11_OR_GREATER + +} // namespace optional_lite + +using optional_lite::optional; +using optional_lite::nullopt_t; +using optional_lite::nullopt; + +#if ! optional_CONFIG_NO_EXCEPTIONS +using optional_lite::bad_optional_access; +#endif + +using optional_lite::make_optional; + +} // namespace nonstd + +#if optional_CPP11_OR_GREATER + +// specialize the std::hash algorithm: + +namespace std { + +template< class T > +struct hash< nonstd::optional<T> > +{ +public: + std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept + { + return bool( v ) ? std::hash<T>{}( *v ) : 0; + } +}; + +} //namespace std + +#endif // optional_CPP11_OR_GREATER + +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#elif defined(_MSC_VER ) +# pragma warning( pop ) +#endif + +#endif // optional_USES_STD_OPTIONAL + +#endif // NONSTD_OPTIONAL_LITE_HPP |