Skip to content

Commit

Permalink
feat: lsp quick fix
Browse files Browse the repository at this point in the history
  • Loading branch information
He1pa committed Aug 10, 2023
1 parent 6481ce5 commit 6b0de71
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 5 deletions.
22 changes: 20 additions & 2 deletions kclvm/tools/src/LSP/src/capabilities.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use lsp_types::{
ClientCapabilities, CompletionOptions, HoverProviderCapability, OneOf, ServerCapabilities,
ClientCapabilities, CodeActionKind, CodeActionOptions, CodeActionProviderCapability,
CompletionOptions, HoverProviderCapability, OneOf, ServerCapabilities,
TextDocumentSyncCapability, TextDocumentSyncKind, WorkDoneProgressOptions,
};

/// Returns the capabilities of this LSP server implementation given the capabilities of the client.
pub fn server_capabilities(_client_caps: &ClientCapabilities) -> ServerCapabilities {
pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabilities {
ServerCapabilities {
text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)),
document_symbol_provider: Some(OneOf::Left(true)),
Expand All @@ -18,6 +19,23 @@ pub fn server_capabilities(_client_caps: &ClientCapabilities) -> ServerCapabilit
}),
hover_provider: Some(HoverProviderCapability::Simple(true)),
definition_provider: Some(OneOf::Left(true)),
code_action_provider: Some(
client_caps
.text_document
.as_ref()
.and_then(|it| it.code_action.as_ref())
.and_then(|it| it.code_action_literal_support.as_ref())
.map_or(CodeActionProviderCapability::Simple(true), |_| {
CodeActionProviderCapability::Options(CodeActionOptions {
// Advertise support for all built-in CodeActionKinds.
// Ideally we would base this off of the client capabilities
// but the client is supposed to fall back gracefully for unknown values.
code_action_kinds: Some(vec![CodeActionKind::QUICKFIX]),
resolve_provider: None,
work_done_progress_options: Default::default(),
})
}),
),
..Default::default()
}
}
1 change: 1 addition & 0 deletions kclvm/tools/src/LSP/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ mod util;
mod document_symbol;
mod goto_def;
mod hover;
mod quick_fix;
mod request;
1 change: 1 addition & 0 deletions kclvm/tools/src/LSP/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod from_lsp;
mod goto_def;
mod hover;
mod notification;
mod quick_fix;
mod request;
mod state;
mod to_lsp;
Expand Down
79 changes: 79 additions & 0 deletions kclvm/tools/src/LSP/src/quick_fix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use std::collections::HashMap;

use kclvm_error::{DiagnosticId, WarningKind};
use lsp_types::{CodeAction, CodeActionKind, CodeActionOrCommand, NumberOrString, TextEdit};

pub(crate) fn quick_fix(
params: lsp_types::CodeActionParams,
) -> Vec<lsp_types::CodeActionOrCommand> {
let diags = params.context.diagnostics;
let mut code_actions: Vec<lsp_types::CodeActionOrCommand> = vec![];
for diag in diags {
if let Some(code) = &diag.code {
if let Some(id) = conver_code_to_kcl_diag_id(code) {
match id {
DiagnosticId::Error(_) => continue,
DiagnosticId::Warning(warn) => match warn {
WarningKind::UnusedImportWarning => {
let mut changes = HashMap::new();
changes.insert(
params.text_document.uri.clone(),
vec![TextEdit {
range: diag.range,
new_text: "".to_string(),
}],
);
code_actions.push(CodeActionOrCommand::CodeAction(CodeAction {
title: WarningKind::UnusedImportWarning.name(),
kind: Some(CodeActionKind::QUICKFIX),
diagnostics: Some(vec![diag.clone()]),
edit: Some(lsp_types::WorkspaceEdit {
changes: Some(changes),
..Default::default()
}),
..Default::default()
}))
}
WarningKind::ReimportWarning => {
let mut changes = HashMap::new();
changes.insert(
params.text_document.uri.clone(),
vec![TextEdit {
range: diag.range,
new_text: "".to_string(),
}],
);
code_actions.push(CodeActionOrCommand::CodeAction(CodeAction {
title: WarningKind::ReimportWarning.name(),
kind: Some(CodeActionKind::QUICKFIX),
diagnostics: Some(vec![diag.clone()]),
edit: Some(lsp_types::WorkspaceEdit {
changes: Some(changes),
..Default::default()
}),
..Default::default()
}))
}
_ => continue,
},
}
}
}
}
code_actions
}

pub(crate) fn conver_code_to_kcl_diag_id(code: &NumberOrString) -> Option<DiagnosticId> {
match code {
NumberOrString::Number(_) => None,
NumberOrString::String(code) => match code.as_str() {
"CompilerWarning" => Some(DiagnosticId::Warning(WarningKind::CompilerWarning)),
"UnusedImportWarning" => Some(DiagnosticId::Warning(WarningKind::UnusedImportWarning)),
"ReimportWarning" => Some(DiagnosticId::Warning(WarningKind::ReimportWarning)),
"ImportPositionWarning" => {
Some(DiagnosticId::Warning(WarningKind::ImportPositionWarning))
}
_ => None,
},
}
}
17 changes: 15 additions & 2 deletions kclvm/tools/src/LSP/src/request.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use std::time::Instant;
use std::{collections::HashMap, time::Instant};

use anyhow::Ok;
use crossbeam_channel::Sender;
use lsp_types::{CodeAction, CodeActionKind, CodeActionOrCommand, TextEdit};

use crate::{
completion::completion,
dispatcher::RequestDispatcher,
document_symbol::document_symbol,
from_lsp::{file_path_from_url, kcl_pos},
goto_def::goto_definition,
hover,
hover, quick_fix,
state::{log_message, LanguageServerSnapshot, LanguageServerState, Task},
util::{parse_param_and_compile, Param},
};
Expand Down Expand Up @@ -44,12 +45,24 @@ impl LanguageServerState {
.on::<lsp_types::request::Completion>(handle_completion)?
.on::<lsp_types::request::HoverRequest>(handle_hover)?
.on::<lsp_types::request::DocumentSymbolRequest>(handle_document_symbol)?
.on::<lsp_types::request::CodeActionRequest>(handle_code_action)?
.finish();

Ok(())
}
}

/// Called when a `GotoDefinition` request was received.
pub(crate) fn handle_code_action(
_snap: LanguageServerSnapshot,
params: lsp_types::CodeActionParams,
_sender: Sender<Task>,
) -> anyhow::Result<Option<lsp_types::CodeActionResponse>> {
let mut code_actions: Vec<lsp_types::CodeActionOrCommand> = vec![];
code_actions.extend(quick_fix::quick_fix(params));
Ok(Some(code_actions))
}

/// Called when a `GotoDefinition` request was received.
pub(crate) fn handle_goto_definition(
snapshot: LanguageServerSnapshot,
Expand Down
4 changes: 3 additions & 1 deletion kclvm/tools/src/LSP/src/test_data/diagnostics.k
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import abc
import aaa
a =
b: str = 1
c: Person = Person {
age: 1
}

d = 1
d = 2
d = 2

2 changes: 2 additions & 0 deletions kclvm/tools/src/LSP/src/test_data/hover_test/hover.k
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ schema Person:
name doc test
age : int, default is False, optional
age doc test

"""

name: str
age?: int

Expand Down

0 comments on commit 6b0de71

Please sign in to comment.