diff --git a/CMakeLists.txt b/CMakeLists.txt index 9619f371..49b0012e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.22) project(clice) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_RELEASE} -g -O0 -fno-rtti ") diff --git a/include/LSP/Protocol.h b/include/LSP/Protocol.h index ad4d32ba..919b79ec 100644 --- a/include/LSP/Protocol.h +++ b/include/LSP/Protocol.h @@ -5,6 +5,8 @@ #include #include +#include "SemanticTokens.h" + namespace clice { // Defined by JSON RPC. @@ -473,6 +475,22 @@ struct DocumentOnTypeFormattingOptions { /// moreTriggerCharacter?: string[]; }; +struct SemanticTokensOptions { + /// The legend used by the server + SemanticTokensLegend legend; + + /// Server supports providing semantic tokens for a specific range of a document. + bool range = false; // TODO: further check + + struct Full { + /// Server supports providing semantic tokens for a full document. + bool delta = true; + }; + + /// Server supports providing semantic tokens for a full document. + Full full; +}; + struct ServerCapabilities { /// The position encoding the server picked from the encodings offered /// by the client via the client capability `general.positionEncodings`. @@ -567,7 +585,7 @@ struct ServerCapabilities { bool callHierarchyProvider = true; /// The server provides semantic tokens support. - // TODO: semanticTokensProvider?: SemanticTokensOptions + SemanticTokensOptions semanticTokensProvider; /// Whether server provides moniker support. bool monikerProvider = false; // TODO: further discussion @@ -607,4 +625,85 @@ struct InitializeResult { ServerInfo serverInfo; }; +/*===================================================/ +/ / +/======= Text Document Synchronization ==========/ +/ / +/===================================================*/ + +/// An item to transfer a text document from the client to the server. +struct TextDocumentItem { + /// The text document's URI. + std::string_view uri; + + /// The text document's language identifier. + std::string_view languageId; + + /// he version number of this document (it will increase after each change, including undo/redo). + int version; + + /// The content of the opened text document. + std::string_view text; +}; + +/// Text documents are identified using a URI. On the protocol level, URIs are passed as strings. +struct TextDocumentIdentifier { + /// The text document's URI. + std::string_view uri; +}; + +struct VersionedTextDocumentIdentifier { + /// The text document's URI. + std::string_view uri; + + /// The version number of this document. + /// + /// The version number of a document will increase after each change, + /// including undo/redo. The number doesn't need to be consecutive. + int version; +}; + +struct DidOpenTextDocumentParams { + /// The document that was opened. + TextDocumentItem textDocument; +}; + +struct TextDocumentContentChangeEvent { + // TODO: +}; + +struct DidChangeTextDocumentParams { + /// The document that did change. The version number points + /// to the version after all provided content changes have + /// been applied. + VersionedTextDocumentIdentifier textDocument; + + /// The actual content changes. The content changes describe single state + /// changes to the document. So if there are two content changes c1 (at + /// array index 0) and c2 (at array index 1) for a document in state S then + /// c1 moves the document from S to S' and c2 from S' to S''. So c1 is + /// computed on the state S and c2 is computed on the state S'. + /// + /// To mirror the content of a document using change events use the following + /// approach: + /// - start with the same initial content + /// - apply the 'textDocument/didChange' notifications in the order you receive them. + /// - apply the `TextDocumentContentChangeEvent`s in a single notification in the order you receive them. + std::vector contentChanges; +}; + +struct DidCloseTextDocumentParams { + /// The document that was closed. + TextDocumentIdentifier textDocument; +}; + +struct DidSaveTextDocumentParams { + /// The document that was saved. + TextDocumentIdentifier textDocument; + + /// Optional the content when saved. Depends on the includeText value + /// when the save notification was requested. + std::optional text; +}; + } // namespace clice diff --git a/include/LSP/SemanticTokens.h b/include/LSP/SemanticTokens.h index abf15194..6ed1c86f 100644 --- a/include/LSP/SemanticTokens.h +++ b/include/LSP/SemanticTokens.h @@ -45,4 +45,9 @@ enum SemanticTokenModifiers { DefaultLibrary }; +struct SemanticTokensLegend { + std::vector tokenTypes; + std::vector tokenModifiers; +}; + } // namespace clice diff --git a/include/LSP/Server.h b/include/LSP/Server.h index 4dae3107..7e206871 100644 --- a/include/LSP/Server.h +++ b/include/LSP/Server.h @@ -25,9 +25,13 @@ public: /===================================================*/ // Server lifecycle - void initialize(InitializeParams& params); + void initialize(const InitializeParams& params); // Text Document Synchronization + void didOpen(this Server& self, const DidOpenTextDocumentParams& params); + void didChange(this Server& self, const DidChangeTextDocumentParams& params); + void didClose(this Server& self, const DidCloseTextDocumentParams& params); + void didSave(this Server& self, const DidSaveTextDocumentParams& params); // Language Features void declaration(); diff --git a/include/LSP/Uri.h b/include/LSP/Uri.h new file mode 100644 index 00000000..e69de29b diff --git a/src/LSP/Server.cpp b/src/LSP/Server.cpp index 21e09a91..c89f6a94 100644 --- a/src/LSP/Server.cpp +++ b/src/LSP/Server.cpp @@ -36,6 +36,10 @@ void Server::handle_message(std::string_view message) { {"result", clice::serialize(InitializeResult{})} }; transport->send(json.dump()); + } else if(method == "textDocument/didOpen") { + // didOpen(); + auto params = deserialize(input["params"]); + logger::info("serialize successfully: {}", serialize(params).dump()); } } catch(std::exception& e) { logger::error("failed to parse JSON: {}", e.what());