Skip to content

Commit

Permalink
feat: add lsp inaly-hint provider
Browse files Browse the repository at this point in the history
Signed-off-by: shruti2522 <[email protected]>
  • Loading branch information
shruti2522 committed Jun 23, 2024
1 parent dadfd04 commit bac02cd
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 5 deletions.
2 changes: 1 addition & 1 deletion kclvm/tools/src/LSP/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ anyhow = { version = "1.0", default-features = false, features = ["std"] }
crossbeam-channel = { version = "0.5.7", default-features = false }
ra_ap_vfs = "0.0.149"
ra_ap_vfs-notify = "0.0.149"
lsp-types = { version = "0.93.0", default-features = false }
lsp-types = { version = "0.93.0", features = ["proposed"]}
threadpool = { version = "1.8.1", default-features = false }
salsa = { version = "0.16.1", default-features = false }
serde_json = { version = "1.0", default-features = false }
Expand Down
13 changes: 10 additions & 3 deletions kclvm/tools/src/LSP/src/capabilities.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use lsp_types::{
ClientCapabilities, CodeActionKind, CodeActionOptions, CodeActionProviderCapability,
CompletionOptions, HoverProviderCapability, OneOf, SemanticTokensFullOptions,
SemanticTokensLegend, SemanticTokensOptions, ServerCapabilities, TextDocumentSyncCapability,
TextDocumentSyncKind, WorkDoneProgressOptions,
CompletionOptions, HoverProviderCapability, InlayHintOptions, InlayHintServerCapabilities,
OneOf, SemanticTokensFullOptions, SemanticTokensLegend, SemanticTokensOptions,
ServerCapabilities, TextDocumentSyncCapability, TextDocumentSyncKind, WorkDoneProgressOptions,
};

use crate::semantic_token::LEGEND_TYPE;
Expand Down Expand Up @@ -38,6 +38,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
work_done_progress_options: WorkDoneProgressOptions {
work_done_progress: None,
},
completion_item: None,
}),
hover_provider: Some(HoverProviderCapability::Simple(true)),
definition_provider: Some(OneOf::Left(true)),
Expand All @@ -62,6 +63,12 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
document_range_formatting_provider: Some(OneOf::Left(true)),
references_provider: Some(OneOf::Left(true)),
rename_provider: Some(OneOf::Left(true)),
inlay_hint_provider: Some(lsp_types::OneOf::Right(
InlayHintServerCapabilities::Options(InlayHintOptions {
resolve_provider: None,
work_done_progress_options: Default::default(),
}),
)),
..Default::default()
}
}
106 changes: 106 additions & 0 deletions kclvm/tools/src/LSP/src/inlay_hints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use kclvm_error::Position as KCLPos;
use kclvm_sema::core::{global_state::GlobalState, symbol::KCLSymbol};
use kclvm_sema::ty::TypeKind;
use lsp_types::{InlayHint, InlayHintLabelPart, Position as LspPosition, Range};
use std::convert::TryInto;

pub fn inlay_hints(file: &str, gs: &GlobalState) -> Option<Vec<InlayHint>> {
let mut inlay_hints: Vec<InlayHint> = vec![];
let sema_db = gs.get_sema_db();
if let Some(file_sema) = sema_db.get_file_sema(file) {
let symbols = file_sema.get_symbols();
for symbol_ref in symbols {
if let Some(symbol) = gs.get_symbols().get_symbol(*symbol_ref) {
let (start, end) = symbol.get_range();
if let Some(hint) = generate_inlay_hint(symbol, gs, &start, &end) {
inlay_hints.push(hint);
}
}
}
}
Some(inlay_hints)
}

fn generate_inlay_hint(
symbol: &KCLSymbol,
gs: &GlobalState,
start: &KCLPos,
end: &KCLPos,
) -> Option<InlayHint> {
match get_hint_label(symbol, gs) {
Some(label_parts) => {
let range = Range {
start: LspPosition::new(
(start.line - 1).try_into().unwrap(),
start.column.unwrap_or(0).try_into().unwrap(),
),
end: LspPosition::new(
(end.line - 1).try_into().unwrap(),
end.column.unwrap_or(0).try_into().unwrap(),
),
};
Some(InlayHint {
position: range.end,
label: lsp_types::InlayHintLabel::LabelParts(label_parts),
kind: None,
text_edits: None,
tooltip: None,
padding_left: Some(true),
padding_right: Some(true),
data: None,
})
}
None => None,
}
}

fn get_hint_label(symbol: &KCLSymbol, _gs: &GlobalState) -> Option<Vec<InlayHintLabelPart>> {
if let Some(ty) = &symbol.get_sema_info().ty {
let mut label_parts = Vec::new();

match &ty.kind {
TypeKind::Str
| TypeKind::Bool
| TypeKind::Int
| TypeKind::Float
| TypeKind::Any
| TypeKind::None
| TypeKind::Named(_)
| TypeKind::NumberMultiplier(_)
| TypeKind::Union(_)
| TypeKind::Dict(_)
| TypeKind::List(_) => {
label_parts.push(InlayHintLabelPart {
value: format!(": {}", ty.ty_str()),
..Default::default()
});
}
TypeKind::Module(module_ty) => {
label_parts.push(InlayHintLabelPart {
value: format!(": {}", module_ty.pkgpath),
..Default::default()
});
}
TypeKind::Function(_) => {
let symbol_name = symbol.get_name().to_string();
label_parts.push(InlayHintLabelPart {
value: format!("fn {}", symbol_name),
..Default::default()
});
}
TypeKind::Schema(schema_ty) => {
let fully_qualified_ty_name = format!("schema {}", schema_ty.name);
label_parts.push(InlayHintLabelPart {
value: format!(": {}", fully_qualified_ty_name),
..Default::default()
});
}
_ => {
return None;
}
}
Some(label_parts)
} else {
None
}
}
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 @@ -9,6 +9,7 @@ mod formatting;
mod from_lsp;
mod goto_def;
mod hover;
mod inlay_hints;
mod main_loop;
mod notification;
mod quick_fix;
Expand Down
2 changes: 2 additions & 0 deletions kclvm/tools/src/LSP/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod find_refs;
mod from_lsp;
mod goto_def;
mod hover;
mod inlay_hints;
mod main_loop;
mod notification;
mod quick_fix;
Expand Down Expand Up @@ -73,6 +74,7 @@ fn run_server() -> anyhow::Result<()> {
name: String::from("kcl-language-server"),
version: None,
}),
offset_encoding: None,
};

let initialize_result = serde_json::to_value(initialize_result)
Expand Down
27 changes: 26 additions & 1 deletion kclvm/tools/src/LSP/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ use crate::{
formatting::format,
from_lsp::{self, file_path_from_url, kcl_pos},
goto_def::goto_def,
hover, quick_fix,
hover,
inlay_hints::inlay_hints,
quick_fix,
semantic_token::semantic_tokens_full,
state::{log_message, LanguageServerSnapshot, LanguageServerState, Task},
};
Expand Down Expand Up @@ -58,6 +60,7 @@ impl LanguageServerState {
.on::<lsp_types::request::RangeFormatting>(handle_range_formatting)?
.on::<lsp_types::request::Rename>(handle_rename)?
.on::<lsp_types::request::SemanticTokensFullRequest>(handle_semantic_tokens_full)?
.on::<lsp_types::request::InlayHintRequest>(handle_inlay_hint)?
.finish();

Ok(())
Expand Down Expand Up @@ -439,3 +442,25 @@ pub(crate) fn handle_rename(
}
}
}

pub(crate) fn handle_inlay_hint(
snapshot: LanguageServerSnapshot,
params: lsp_types::InlayHintParams,
_sender: Sender<Task>,
) -> anyhow::Result<Option<Vec<lsp_types::InlayHint>>> {
let file = file_path_from_url(&params.text_document.uri)?;
let path = from_lsp::abs_path(&params.text_document.uri)?;
let db = match snapshot.try_get_db(&path.clone().into()) {
Ok(option_db) => match option_db {
Some(db) => db,
None => return Err(anyhow!(LSPError::Retry)),
},
Err(_) => return Ok(None),
};
let res = inlay_hints(&file, &db.gs);

if !snapshot.verify_request_version(db.version, &path)? {
return Err(anyhow!(LSPError::Retry));
}
Ok(res)
}

0 comments on commit bac02cd

Please sign in to comment.