diff --git a/src/completion.rs b/src/completion.rs index f828057..c2d2c02 100644 --- a/src/completion.rs +++ b/src/completion.rs @@ -11,18 +11,21 @@ use serde_json::Value; use std::fmt::Debug; /// Defines how to interpret the insert text in a completion item -#[derive(Debug, Eq, PartialEq, Clone, Copy, Serialize, Deserialize)] +#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)] #[serde(transparent)] pub struct InsertTextFormat(i32); +lsp_enum! { impl InsertTextFormat { pub const PLAIN_TEXT: InsertTextFormat = InsertTextFormat(1); pub const SNIPPET: InsertTextFormat = InsertTextFormat(2); } +} /// The kind of a completion entry. #[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)] #[serde(transparent)] pub struct CompletionItemKind(i32); +lsp_enum! { impl CompletionItemKind { pub const TEXT: CompletionItemKind = CompletionItemKind(1); pub const METHOD: CompletionItemKind = CompletionItemKind(2); @@ -50,38 +53,6 @@ impl CompletionItemKind { pub const OPERATOR: CompletionItemKind = CompletionItemKind(24); pub const TYPE_PARAMETER: CompletionItemKind = CompletionItemKind(25); } - -impl Debug for CompletionItemKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - Self::TEXT => write!(f, "Text"), - Self::METHOD => write!(f, "Method"), - Self::FUNCTION => write!(f, "Function"), - Self::CONSTRUCTOR => write!(f, "Constructor"), - Self::FIELD => write!(f, "Field"), - Self::VARIABLE => write!(f, "Variable"), - Self::CLASS => write!(f, "Class"), - Self::INTERFACE => write!(f, "Interface"), - Self::MODULE => write!(f, "Module"), - Self::PROPERTY => write!(f, "Property"), - Self::UNIT => write!(f, "Unit"), - Self::VALUE => write!(f, "Value"), - Self::ENUM => write!(f, "Enum"), - Self::KEYWORD => write!(f, "Keyword"), - Self::SNIPPET => write!(f, "Snippet"), - Self::COLOR => write!(f, "Color"), - Self::FILE => write!(f, "File"), - Self::REFERENCE => write!(f, "Reference"), - Self::FOLDER => write!(f, "Folder"), - Self::ENUM_MEMBER => write!(f, "EnumMember"), - Self::CONSTANT => write!(f, "Constant"), - Self::STRUCT => write!(f, "Struct"), - Self::EVENT => write!(f, "Event"), - Self::OPERATOR => write!(f, "Operator"), - Self::TYPE_PARAMETER => write!(f, "TypeParameter"), - _ => write!(f, "CompletionItemKind({})", self.0), - } - } } #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] @@ -174,9 +145,10 @@ pub struct InsertTextModeSupport { /// item insertion. /// /// @since 3.16.0 -#[derive(Debug, Eq, PartialEq, Clone, Copy, Serialize, Deserialize)] +#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)] #[serde(transparent)] pub struct InsertTextMode(i32); +lsp_enum! { impl InsertTextMode { /// The insertion or replace strings is taken as it is. If the /// value is multi line the lines below the cursor will be @@ -194,13 +166,16 @@ impl InsertTextMode { /// following lines inserted will be indented using 2 tabs as well. pub const ADJUST_INDENTATION: InsertTextMode = InsertTextMode(2); } +} -#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)] #[serde(transparent)] pub struct CompletionItemTag(i32); +lsp_enum! { impl CompletionItemTag { pub const DEPRECATED: CompletionItemTag = CompletionItemTag(1); } +} #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -398,14 +373,16 @@ pub struct CompletionContext { } /// How a completion was triggered. -#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)] #[serde(transparent)] pub struct CompletionTriggerKind(i32); +lsp_enum! { impl CompletionTriggerKind { pub const INVOKED: CompletionTriggerKind = CompletionTriggerKind(1); pub const TRIGGER_CHARACTER: CompletionTriggerKind = CompletionTriggerKind(2); pub const TRIGGER_FOR_INCOMPLETE_COMPLETIONS: CompletionTriggerKind = CompletionTriggerKind(3); } +} /// Represents a collection of [completion items](#CompletionItem) to be presented /// in the editor. @@ -601,4 +578,13 @@ mod tests { }); test_deserialization(r#"{"tagSupport": {"valueSet": [1]}}"#, &t); } + + #[test] + fn test_debug_enum() { + assert_eq!(format!("{:?}", CompletionItemKind::TEXT), "Text"); + assert_eq!( + format!("{:?}", CompletionItemKind::TYPE_PARAMETER), + "TypeParameter" + ); + } } diff --git a/src/document_highlight.rs b/src/document_highlight.rs index e7b1a63..9a97c10 100644 --- a/src/document_highlight.rs +++ b/src/document_highlight.rs @@ -34,9 +34,10 @@ pub struct DocumentHighlight { } /// A document highlight kind. -#[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Copy, Clone, Deserialize, Serialize)] #[serde(transparent)] pub struct DocumentHighlightKind(i32); +lsp_enum! { impl DocumentHighlightKind { /// A textual occurrance. pub const TEXT: DocumentHighlightKind = DocumentHighlightKind(1); @@ -47,3 +48,4 @@ impl DocumentHighlightKind { /// Write-access of a symbol, like writing to a variable. pub const WRITE: DocumentHighlightKind = DocumentHighlightKind(3); } +} diff --git a/src/lib.rs b/src/lib.rs index 1fb9a75..9eaf1a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,38 @@ use serde::de; use serde::de::Error as Error_; use serde_json::Value; +macro_rules! lsp_enum { + (impl $typ: ty { $( $(#[$attr:meta])* pub const $name: ident : $enum_type: ty = $value: expr; )* }) => { + impl $typ { + $( + $(#[$attr])* + pub const $name: $enum_type = $value; + )* + } + + impl std::fmt::Debug for $typ { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + $( + Self::$name => { + for word in stringify!($name).split('_') { + let mut chars = word.chars(); + let first = chars.next().unwrap(); + write!(f, "{}", first)?; + for rest in chars { + write!(f, "{}", rest.to_lowercase())?; + } + } + } + )* + _ => write!(f, "{}({})", stringify!($typ), self.0)?, + } + Ok(()) + } + } + } +} + pub mod error_codes; pub mod notification; pub mod request; @@ -288,9 +320,10 @@ impl Diagnostic { } /// The protocol currently supports the following diagnostic severities: -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Deserialize, Serialize)] #[serde(transparent)] pub struct DiagnosticSeverity(i32); +lsp_enum! { impl DiagnosticSeverity { /// Reports an error. pub const ERROR: DiagnosticSeverity = DiagnosticSeverity(1); @@ -301,6 +334,7 @@ impl DiagnosticSeverity { /// Reports a hint. pub const HINT: DiagnosticSeverity = DiagnosticSeverity(4); } +} /// 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 @@ -315,9 +349,10 @@ pub struct DiagnosticRelatedInformation { } /// The diagnostic tags. -#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)] #[serde(transparent)] pub struct DiagnosticTag(i32); +lsp_enum! { impl DiagnosticTag { /// Unused or unnecessary code. /// Clients are allowed to render diagnostics with this tag faded out instead of having @@ -328,6 +363,7 @@ impl DiagnosticTag { /// Clients are allowed to rendered diagnostics with this tag strike through. pub const DEPRECATED: DiagnosticTag = DiagnosticTag(2); } +} /// Represents a reference to a command. Provides a title which will be used to represent a command in the UI. /// Commands are identitifed using a string identifier and the protocol currently doesn't specify a set of @@ -1070,6 +1106,7 @@ pub enum FailureHandlingKind { #[derive(Eq, PartialEq, Copy, Clone, Serialize, Deserialize)] #[serde(transparent)] pub struct SymbolKind(i32); +lsp_enum! { impl SymbolKind { pub const FILE: SymbolKind = SymbolKind(1); pub const MODULE: SymbolKind = SymbolKind(2); @@ -1098,39 +1135,6 @@ impl SymbolKind { pub const OPERATOR: SymbolKind = SymbolKind(25); pub const TYPE_PARAMETER: SymbolKind = SymbolKind(26); } - -impl Debug for SymbolKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - Self::FILE => write!(f, "File"), - Self::MODULE => write!(f, "Module"), - Self::NAMESPACE => write!(f, "Namespace"), - Self::PACKAGE => write!(f, "Package"), - Self::CLASS => write!(f, "Class"), - Self::METHOD => write!(f, "Method"), - Self::PROPERTY => write!(f, "Property"), - Self::FIELD => write!(f, "Field"), - Self::CONSTRUCTOR => write!(f, "Constructor"), - Self::ENUM => write!(f, "Enum"), - Self::INTERFACE => write!(f, "Interface"), - Self::FUNCTION => write!(f, "Function"), - Self::VARIABLE => write!(f, "Variable"), - Self::CONSTANT => write!(f, "Constant"), - Self::STRING => write!(f, "String"), - Self::NUMBER => write!(f, "Number"), - Self::BOOLEAN => write!(f, "Boolean"), - Self::ARRAY => write!(f, "Array"), - Self::OBJECT => write!(f, "Object"), - Self::KEY => write!(f, "Key"), - Self::NULL => write!(f, "Null"), - Self::ENUM_MEMBER => write!(f, "EnumMember"), - Self::STRUCT => write!(f, "Struct"), - Self::EVENT => write!(f, "Event"), - Self::OPERATOR => write!(f, "Operator"), - Self::TYPE_PARAMETER => write!(f, "TypeParameter"), - _ => write!(f, "SymbolKind({})", self.0), - } - } } /// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. @@ -1537,9 +1541,10 @@ pub struct InitializeError { // The server can signal the following capabilities: /// Defines how the host (editor) should sync document changes to the language server. -#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)] #[serde(transparent)] pub struct TextDocumentSyncKind(i32); +lsp_enum! { impl TextDocumentSyncKind { /// Documents should not be synced at all. pub const NONE: TextDocumentSyncKind = TextDocumentSyncKind(0); @@ -1551,6 +1556,7 @@ impl TextDocumentSyncKind { /// incremental updates to the document are sent. pub const INCREMENTAL: TextDocumentSyncKind = TextDocumentSyncKind(2); } +} pub type ExecuteCommandClientCapabilities = DynamicRegistrationClientCapabilities; @@ -2040,9 +2046,10 @@ pub struct WillSaveTextDocumentParams { } /// Represents reasons why a text document is saved. -#[derive(Copy, Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[derive(Copy, Eq, PartialEq, Clone, Deserialize, Serialize)] #[serde(transparent)] pub struct TextDocumentSaveReason(i32); +lsp_enum! { impl TextDocumentSaveReason { /// Manually triggered, e.g. by the user pressing save, by starting debugging, /// or by an API call. @@ -2054,6 +2061,7 @@ impl TextDocumentSaveReason { /// When the editor lost focus. pub const FOCUS_OUT: TextDocumentSaveReason = TextDocumentSaveReason(3); } +} #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] @@ -2094,9 +2102,10 @@ pub struct DidChangeWatchedFilesParams { } /// The file event type. -#[derive(Debug, Eq, PartialEq, Copy, Clone, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Copy, Clone, Deserialize, Serialize)] #[serde(transparent)] pub struct FileChangeType(i32); +lsp_enum! { impl FileChangeType { /// The file got created. pub const CREATED: FileChangeType = FileChangeType(1); @@ -2107,6 +2116,7 @@ impl FileChangeType { /// The file got deleted. pub const DELETED: FileChangeType = FileChangeType(3); } +} /// An event describing a file change. #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] @@ -2391,13 +2401,15 @@ pub struct PartialResultParams { /// Symbol tags are extra annotations that tweak the rendering of a symbol. /// Since 3.15 -#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)] #[serde(transparent)] pub struct SymbolTag(i32); +lsp_enum! { impl SymbolTag { /// Render a symbol as obsolete, usually using a strike-out. pub const DEPRECATED: SymbolTag = SymbolTag(1); } +} #[cfg(test)] mod tests { diff --git a/src/rename.rs b/src/rename.rs index f7b2b84..b84bdcf 100644 --- a/src/rename.rs +++ b/src/rename.rs @@ -61,14 +61,16 @@ pub struct RenameClientCapabilities { pub honors_change_annotations: Option, } -#[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize, Deserialize)] +#[derive(Eq, PartialEq, Copy, Clone, Serialize, Deserialize)] #[serde(transparent)] pub struct PrepareSupportDefaultBehavior(i32); +lsp_enum! { impl PrepareSupportDefaultBehavior { /// The client's default behavior is to select the identifier /// according the to language's syntax rule pub const IDENTIFIER: PrepareSupportDefaultBehavior = PrepareSupportDefaultBehavior(1); } +} #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] #[serde(untagged)] diff --git a/src/signature_help.rs b/src/signature_help.rs index 6b5075e..151f3bf 100644 --- a/src/signature_help.rs +++ b/src/signature_help.rs @@ -83,9 +83,10 @@ pub struct SignatureHelpRegistrationOptions { } /// Signature help options. -#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)] #[serde(transparent)] pub struct SignatureHelpTriggerKind(i32); +lsp_enum! { impl SignatureHelpTriggerKind { /// Signature help was invoked manually by the user or by a command. pub const INVOKED: SignatureHelpTriggerKind = SignatureHelpTriggerKind(1); @@ -94,6 +95,7 @@ impl SignatureHelpTriggerKind { /// Signature help was triggered by the cursor moving or by the document content changing. pub const CONTENT_CHANGE: SignatureHelpTriggerKind = SignatureHelpTriggerKind(3); } +} #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] diff --git a/src/window.rs b/src/window.rs index c5adc1c..89d28aa 100644 --- a/src/window.rs +++ b/src/window.rs @@ -8,9 +8,10 @@ use url::Url; use crate::Range; -#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)] +#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)] #[serde(transparent)] pub struct MessageType(i32); +lsp_enum! { impl MessageType { /// An error message. pub const ERROR: MessageType = MessageType(1); @@ -21,6 +22,7 @@ impl MessageType { /// A log message. pub const LOG: MessageType = MessageType(4); } +} /// Window specific client capabilities. #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]