use std::collections::HashMap;
pub type DocumentUri = String;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum RequestId {
Number(i64),
String(String),
}
impl From<i64> for RequestId {
fn from(n: i64) -> Self {
RequestId::Number(n)
}
}
impl From<String> for RequestId {
fn from(s: String) -> Self {
RequestId::String(s)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Position {
pub line: u32,
pub character: u32,
}
impl Position {
pub fn new(line: u32, character: u32) -> Self {
Self { line, character }
}
}
impl PartialOrd for Position {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Position {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self.line.cmp(&other.line) {
std::cmp::Ordering::Equal => self.character.cmp(&other.character),
ord => ord,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Range {
pub start: Position,
pub end: Position,
}
impl Range {
pub fn new(start: Position, end: Position) -> Self {
Self { start, end }
}
pub fn point(pos: Position) -> Self {
Self {
start: pos,
end: pos,
}
}
pub fn contains(&self, pos: Position) -> bool {
self.start <= pos && pos < self.end
}
pub fn overlaps(&self, other: &Range) -> bool {
self.start < other.end && other.start < self.end
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Location {
pub uri: DocumentUri,
pub range: Range,
}
impl Location {
pub fn new(uri: DocumentUri, range: Range) -> Self {
Self { uri, range }
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LocationLink {
pub origin_selection_range: Option<Range>,
pub target_uri: DocumentUri,
pub target_range: Range,
pub target_selection_range: Range,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TextDocumentIdentifier {
pub uri: DocumentUri,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VersionedTextDocumentIdentifier {
pub uri: DocumentUri,
pub version: i32,
}
#[derive(Debug, Clone)]
pub struct TextDocumentPositionParams {
pub text_document: TextDocumentIdentifier,
pub position: Position,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TextEdit {
pub range: Range,
pub new_text: String,
}
impl TextEdit {
pub fn new(range: Range, new_text: String) -> Self {
Self { range, new_text }
}
pub fn insert(pos: Position, text: String) -> Self {
Self {
range: Range::point(pos),
new_text: text,
}
}
pub fn replace(range: Range, text: String) -> Self {
Self {
range,
new_text: text,
}
}
pub fn delete(range: Range) -> Self {
Self {
range,
new_text: String::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct AnnotatedTextEdit {
pub text_edit: TextEdit,
pub annotation_id: String,
}
#[derive(Debug, Clone)]
pub struct TextDocumentItem {
pub uri: DocumentUri,
pub language_id: String,
pub version: i32,
pub text: String,
}
#[derive(Debug, Clone)]
pub struct TextDocumentContentChangeEvent {
pub range: Option<Range>,
pub text: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum DiagnosticSeverity {
Error = 1,
Warning = 2,
Information = 3,
Hint = 4,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum DiagnosticTag {
Unnecessary = 1,
Deprecated = 2,
}
#[derive(Debug, Clone)]
pub struct DiagnosticRelatedInformation {
pub location: Location,
pub message: String,
}
#[derive(Debug, Clone)]
pub struct Diagnostic {
pub range: Range,
pub severity: Option<DiagnosticSeverity>,
pub code: Option<DiagnosticCode>,
pub source: Option<String>,
pub message: String,
pub tags: Vec<DiagnosticTag>,
pub related_information: Vec<DiagnosticRelatedInformation>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DiagnosticCode {
Number(i32),
String(String),
}
impl Diagnostic {
pub fn error(range: Range, message: impl Into<String>) -> Self {
Self {
range,
severity: Some(DiagnosticSeverity::Error),
code: None,
source: Some("quantalang".to_string()),
message: message.into(),
tags: Vec::new(),
related_information: Vec::new(),
}
}
pub fn warning(range: Range, message: impl Into<String>) -> Self {
Self {
range,
severity: Some(DiagnosticSeverity::Warning),
code: None,
source: Some("quantalang".to_string()),
message: message.into(),
tags: Vec::new(),
related_information: Vec::new(),
}
}
pub fn hint(range: Range, message: impl Into<String>) -> Self {
Self {
range,
severity: Some(DiagnosticSeverity::Hint),
code: None,
source: Some("quantalang".to_string()),
message: message.into(),
tags: Vec::new(),
related_information: Vec::new(),
}
}
pub fn with_code(mut self, code: impl Into<DiagnosticCode>) -> Self {
self.code = Some(code.into());
self
}
pub fn with_tag(mut self, tag: DiagnosticTag) -> Self {
self.tags.push(tag);
self
}
}
impl From<i32> for DiagnosticCode {
fn from(n: i32) -> Self {
DiagnosticCode::Number(n)
}
}
impl From<String> for DiagnosticCode {
fn from(s: String) -> Self {
DiagnosticCode::String(s)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum CompletionItemKind {
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,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum CompletionItemTag {
Deprecated = 1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum InsertTextFormat {
PlainText = 1,
Snippet = 2,
}
#[derive(Debug, Clone)]
pub struct CompletionItem {
pub label: String,
pub kind: Option<CompletionItemKind>,
pub tags: Vec<CompletionItemTag>,
pub detail: Option<String>,
pub documentation: Option<MarkupContent>,
pub deprecated: bool,
pub preselect: bool,
pub sort_text: Option<String>,
pub filter_text: Option<String>,
pub insert_text: Option<String>,
pub insert_text_format: Option<InsertTextFormat>,
pub text_edit: Option<TextEdit>,
pub additional_text_edits: Vec<TextEdit>,
pub commit_characters: Vec<String>,
pub data: Option<String>,
}
impl CompletionItem {
pub fn new(label: impl Into<String>) -> Self {
Self {
label: label.into(),
kind: None,
tags: Vec::new(),
detail: None,
documentation: None,
deprecated: false,
preselect: false,
sort_text: None,
filter_text: None,
insert_text: None,
insert_text_format: None,
text_edit: None,
additional_text_edits: Vec::new(),
commit_characters: Vec::new(),
data: None,
}
}
pub fn keyword(label: impl Into<String>) -> Self {
Self::new(label).with_kind(CompletionItemKind::Keyword)
}
pub fn function(label: impl Into<String>) -> Self {
Self::new(label).with_kind(CompletionItemKind::Function)
}
pub fn variable(label: impl Into<String>) -> Self {
Self::new(label).with_kind(CompletionItemKind::Variable)
}
pub fn field(label: impl Into<String>) -> Self {
Self::new(label).with_kind(CompletionItemKind::Field)
}
pub fn method(label: impl Into<String>) -> Self {
Self::new(label).with_kind(CompletionItemKind::Method)
}
pub fn type_item(label: impl Into<String>) -> Self {
Self::new(label).with_kind(CompletionItemKind::Class)
}
pub fn snippet(label: impl Into<String>, snippet: impl Into<String>) -> Self {
Self::new(label)
.with_kind(CompletionItemKind::Snippet)
.with_insert_text(snippet)
.with_insert_text_format(InsertTextFormat::Snippet)
}
pub fn with_kind(mut self, kind: CompletionItemKind) -> Self {
self.kind = Some(kind);
self
}
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
}
pub fn with_documentation(mut self, docs: impl Into<String>) -> Self {
self.documentation = Some(MarkupContent::markdown(docs));
self
}
pub fn with_insert_text(mut self, text: impl Into<String>) -> Self {
self.insert_text = Some(text.into());
self
}
pub fn with_insert_text_format(mut self, format: InsertTextFormat) -> Self {
self.insert_text_format = Some(format);
self
}
pub fn with_sort_text(mut self, text: impl Into<String>) -> Self {
self.sort_text = Some(text.into());
self
}
pub fn deprecated(mut self) -> Self {
self.deprecated = true;
self.tags.push(CompletionItemTag::Deprecated);
self
}
pub fn preselect(mut self) -> Self {
self.preselect = true;
self
}
}
#[derive(Debug, Clone)]
pub struct CompletionList {
pub is_incomplete: bool,
pub items: Vec<CompletionItem>,
}
impl CompletionList {
pub fn new(items: Vec<CompletionItem>) -> Self {
Self {
is_incomplete: false,
items,
}
}
pub fn incomplete(items: Vec<CompletionItem>) -> Self {
Self {
is_incomplete: true,
items,
}
}
}
#[derive(Debug, Clone)]
pub struct MarkupContent {
pub kind: MarkupKind,
pub value: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MarkupKind {
PlainText,
Markdown,
}
impl MarkupContent {
pub fn plain_text(value: impl Into<String>) -> Self {
Self {
kind: MarkupKind::PlainText,
value: value.into(),
}
}
pub fn markdown(value: impl Into<String>) -> Self {
Self {
kind: MarkupKind::Markdown,
value: value.into(),
}
}
}
#[derive(Debug, Clone)]
pub struct Hover {
pub contents: MarkupContent,
pub range: Option<Range>,
}
impl Hover {
pub fn new(contents: MarkupContent) -> Self {
Self {
contents,
range: None,
}
}
pub fn with_range(mut self, range: Range) -> Self {
self.range = Some(range);
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum SymbolKind {
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,
TypeParameter = 26,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum SymbolTag {
Deprecated = 1,
}
#[derive(Debug, Clone)]
pub struct DocumentSymbol {
pub name: String,
pub detail: Option<String>,
pub kind: SymbolKind,
pub tags: Vec<SymbolTag>,
pub range: Range,
pub selection_range: Range,
pub children: Vec<DocumentSymbol>,
}
impl DocumentSymbol {
pub fn new(
name: impl Into<String>,
kind: SymbolKind,
range: Range,
selection_range: Range,
) -> Self {
Self {
name: name.into(),
detail: None,
kind,
tags: Vec::new(),
range,
selection_range,
children: Vec::new(),
}
}
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
}
pub fn with_children(mut self, children: Vec<DocumentSymbol>) -> Self {
self.children = children;
self
}
}
#[derive(Debug, Clone)]
pub struct SymbolInformation {
pub name: String,
pub kind: SymbolKind,
pub tags: Vec<SymbolTag>,
pub location: Location,
pub container_name: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CodeActionKind(pub String);
impl CodeActionKind {
pub const EMPTY: &'static str = "";
pub const QUICK_FIX: &'static str = "quickfix";
pub const REFACTOR: &'static str = "refactor";
pub const REFACTOR_EXTRACT: &'static str = "refactor.extract";
pub const REFACTOR_INLINE: &'static str = "refactor.inline";
pub const REFACTOR_REWRITE: &'static str = "refactor.rewrite";
pub const SOURCE: &'static str = "source";
pub const SOURCE_ORGANIZE_IMPORTS: &'static str = "source.organizeImports";
pub const SOURCE_FIX_ALL: &'static str = "source.fixAll";
pub fn quick_fix() -> Self {
Self(Self::QUICK_FIX.to_string())
}
pub fn refactor() -> Self {
Self(Self::REFACTOR.to_string())
}
pub fn refactor_extract() -> Self {
Self(Self::REFACTOR_EXTRACT.to_string())
}
pub fn source() -> Self {
Self(Self::SOURCE.to_string())
}
pub fn organize_imports() -> Self {
Self(Self::SOURCE_ORGANIZE_IMPORTS.to_string())
}
}
#[derive(Debug, Clone)]
pub struct CodeAction {
pub title: String,
pub kind: Option<CodeActionKind>,
pub diagnostics: Vec<Diagnostic>,
pub is_preferred: bool,
pub edit: Option<WorkspaceEdit>,
pub command: Option<Command>,
pub data: Option<String>,
}
impl CodeAction {
pub fn new(title: impl Into<String>) -> Self {
Self {
title: title.into(),
kind: None,
diagnostics: Vec::new(),
is_preferred: false,
edit: None,
command: None,
data: None,
}
}
pub fn quick_fix(title: impl Into<String>) -> Self {
Self::new(title).with_kind(CodeActionKind::quick_fix())
}
pub fn refactor(title: impl Into<String>) -> Self {
Self::new(title).with_kind(CodeActionKind::refactor())
}
pub fn with_kind(mut self, kind: CodeActionKind) -> Self {
self.kind = Some(kind);
self
}
pub fn with_edit(mut self, edit: WorkspaceEdit) -> Self {
self.edit = Some(edit);
self
}
pub fn preferred(mut self) -> Self {
self.is_preferred = true;
self
}
}
#[derive(Debug, Clone, Default)]
pub struct WorkspaceEdit {
pub changes: HashMap<DocumentUri, Vec<TextEdit>>,
pub document_changes: Vec<TextDocumentEdit>,
}
impl WorkspaceEdit {
pub fn new() -> Self {
Self::default()
}
pub fn add_edit(&mut self, uri: DocumentUri, edit: TextEdit) {
self.changes.entry(uri).or_default().push(edit);
}
pub fn with_edit(mut self, uri: DocumentUri, edit: TextEdit) -> Self {
self.add_edit(uri, edit);
self
}
}
#[derive(Debug, Clone)]
pub struct TextDocumentEdit {
pub text_document: VersionedTextDocumentIdentifier,
pub edits: Vec<TextEdit>,
}
#[derive(Debug, Clone)]
pub struct Command {
pub title: String,
pub command: String,
pub arguments: Vec<String>,
}
impl Command {
pub fn new(title: impl Into<String>, command: impl Into<String>) -> Self {
Self {
title: title.into(),
command: command.into(),
arguments: Vec::new(),
}
}
pub fn with_args(mut self, args: Vec<String>) -> Self {
self.arguments = args;
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum TextDocumentSyncKind {
None = 0,
Full = 1,
Incremental = 2,
}
#[derive(Debug, Clone, Default)]
pub struct ServerCapabilities {
pub text_document_sync: Option<TextDocumentSyncKind>,
pub completion_provider: Option<CompletionOptions>,
pub hover_provider: bool,
pub signature_help_provider: Option<SignatureHelpOptions>,
pub definition_provider: bool,
pub type_definition_provider: bool,
pub implementation_provider: bool,
pub references_provider: bool,
pub document_highlight_provider: bool,
pub document_symbol_provider: bool,
pub workspace_symbol_provider: bool,
pub code_action_provider: Option<CodeActionOptions>,
pub code_lens_provider: Option<CodeLensOptions>,
pub document_formatting_provider: bool,
pub document_range_formatting_provider: bool,
pub rename_provider: Option<RenameOptions>,
pub folding_range_provider: bool,
pub semantic_tokens_provider: Option<SemanticTokensOptions>,
}
impl ServerCapabilities {
pub fn full() -> Self {
Self {
text_document_sync: Some(TextDocumentSyncKind::Incremental),
completion_provider: Some(CompletionOptions {
trigger_characters: vec![".".to_string(), ":".to_string()],
resolve_provider: true,
}),
hover_provider: true,
signature_help_provider: Some(SignatureHelpOptions {
trigger_characters: vec!["(".to_string(), ",".to_string()],
retrigger_characters: vec![",".to_string()],
}),
definition_provider: true,
type_definition_provider: true,
implementation_provider: true,
references_provider: true,
document_highlight_provider: true,
document_symbol_provider: true,
workspace_symbol_provider: true,
code_action_provider: Some(CodeActionOptions {
code_action_kinds: vec![
CodeActionKind::QUICK_FIX.to_string(),
CodeActionKind::REFACTOR.to_string(),
CodeActionKind::SOURCE_ORGANIZE_IMPORTS.to_string(),
],
resolve_provider: false,
}),
code_lens_provider: Some(CodeLensOptions {
resolve_provider: true,
}),
document_formatting_provider: true,
document_range_formatting_provider: true,
rename_provider: Some(RenameOptions {
prepare_provider: true,
}),
folding_range_provider: true,
semantic_tokens_provider: None, }
}
}
#[derive(Debug, Clone)]
pub struct CompletionOptions {
pub trigger_characters: Vec<String>,
pub resolve_provider: bool,
}
#[derive(Debug, Clone)]
pub struct SignatureHelpOptions {
pub trigger_characters: Vec<String>,
pub retrigger_characters: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct CodeActionOptions {
pub code_action_kinds: Vec<String>,
pub resolve_provider: bool,
}
#[derive(Debug, Clone)]
pub struct CodeLensOptions {
pub resolve_provider: bool,
}
#[derive(Debug, Clone)]
pub struct RenameOptions {
pub prepare_provider: bool,
}
#[derive(Debug, Clone)]
pub struct SemanticTokensOptions {
pub legend: SemanticTokensLegend,
pub range: bool,
pub full: bool,
}
#[derive(Debug, Clone)]
pub struct SemanticTokensLegend {
pub token_types: Vec<String>,
pub token_modifiers: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FoldingRangeKind {
Comment,
Imports,
Region,
}
#[derive(Debug, Clone)]
pub struct FoldingRange {
pub start_line: u32,
pub start_character: Option<u32>,
pub end_line: u32,
pub end_character: Option<u32>,
pub kind: Option<FoldingRangeKind>,
}
#[derive(Debug, Clone)]
pub struct SignatureInformation {
pub label: String,
pub documentation: Option<MarkupContent>,
pub parameters: Vec<ParameterInformation>,
pub active_parameter: Option<u32>,
}
#[derive(Debug, Clone)]
pub struct ParameterInformation {
pub label: String,
pub documentation: Option<MarkupContent>,
}
#[derive(Debug, Clone)]
pub struct SignatureHelp {
pub signatures: Vec<SignatureInformation>,
pub active_signature: Option<u32>,
pub active_parameter: Option<u32>,
}