This commit is contained in:
oxalica
2022-12-18 02:04:54 +08:00
parent 1c122ae707
commit d964938598
8 changed files with 114 additions and 10 deletions

View File

@@ -0,0 +1,54 @@
use syntax::TextSize;
use crate::def::{Expr, ResolveResult};
use crate::{DefDatabase, FileRange};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InlayHint {
pub pos: TextSize,
pub kind: InlayKind,
pub label: String,
pub tooltip: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InlayKind {
WithHint,
}
pub(crate) fn inlay_hints(
db: &dyn DefDatabase,
FileRange { file_id, range }: FileRange,
) -> Vec<InlayHint> {
let src = db.file_content(file_id);
let module = db.module(file_id);
let source_map = db.source_map(file_id);
let nameres = db.name_resolution(file_id);
nameres
.iter()
.filter_map(|(expr, res)| {
let ResolveResult::WithExprs(withs) = res else {
return None;
};
let ident_range = source_map.node_for_expr(expr)?.text_range();
ident_range.intersect(range)?;
let label = "^".repeat(withs.len());
let tooltip = withs
.iter()
.rev()
.filter_map(|&with_expr| {
let Expr::With(env_expr, _) = module[with_expr] else { unreachable!() };
let range = source_map.node_for_expr(env_expr)?.text_range();
Some(format!("with {};\n", &src[range]))
})
.collect::<String>();
Some(InlayHint {
pos: ident_range.start(),
kind: InlayKind::WithHint,
label,
tooltip: format!("```\n{tooltip}\n```"),
})
})
.collect()
}

View File

@@ -5,6 +5,7 @@ mod expand_selection;
mod goto_definition;
mod highlight_related;
mod hover;
mod inlay_hints;
mod links;
mod references;
mod rename;
@@ -25,6 +26,7 @@ pub use completion::{CompletionItem, CompletionItemKind};
pub use goto_definition::GotoDefinitionResult;
pub use highlight_related::HlRelated;
pub use hover::HoverResult;
pub use inlay_hints::{InlayHint, InlayKind};
pub use links::{Link, LinkTarget};
pub use rename::RenameResult;
pub use symbol_hierarchy::SymbolTree;
@@ -165,4 +167,8 @@ impl Analysis {
pub fn highlight_related(&self, fpos: FilePos) -> Cancellable<Vec<HlRelated>> {
self.with_db(|db| highlight_related::highlight_related(db, fpos).unwrap_or_default())
}
pub fn inlay_hints(&self, frange: FileRange) -> Cancellable<Vec<InlayHint>> {
self.with_db(|db| inlay_hints::inlay_hints(db, frange))
}
}

View File

@@ -11,7 +11,8 @@ mod tests;
pub use self::ide::{
Analysis, AnalysisHost, Assist, AssistKind, Cancelled, CompletionItem, CompletionItemKind,
GotoDefinitionResult, HlKeyword, HlOperator, HlPunct, HlRange, HlRelated, HlTag, HoverResult,
Link, LinkTarget, NavigationTarget, RenameResult, RootDatabase, SymbolTree,
InlayHint, InlayKind, Link, LinkTarget, NavigationTarget, RenameResult, RootDatabase,
SymbolTree,
};
pub use base::{
Change, FileId, FilePos, FileRange, FileSet, InFile, SourceDatabase, SourceRoot, SourceRootId,

View File

@@ -11,7 +11,7 @@ ide = { path = "../ide" }
indexmap = "1.9.1"
log = "0.4.17"
lsp-server = "0.6.0"
lsp-types = "0.93.0"
lsp-types = { version = "0.93.0", features = ["proposed"] }
serde = "1.0.140"
serde_json = "1.0.82"
text-size = "1.1.0"

View File

@@ -49,6 +49,7 @@ pub(crate) fn server_capabilities() -> ServerCapabilities {
}),
code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
document_highlight_provider: Some(OneOf::Left(true)),
inlay_hint_provider: Some(OneOf::Left(true)),
..Default::default()
}
}

View File

@@ -1,8 +1,10 @@
use crate::{semantic_tokens, LineMap, LspError, Result, Vfs};
use ide::{
Assist, AssistKind, CompletionItem, CompletionItemKind, Diagnostic, FileId, FilePos, FileRange,
HlRange, HlRelated, HoverResult, NameKind, Severity, SymbolTree, TextEdit, WorkspaceEdit,
HlRange, HlRelated, HoverResult, InlayHint, InlayKind, NameKind, Severity, SymbolTree,
TextEdit, WorkspaceEdit,
};
use lsp::{InlayHintLabel, InlayHintTooltip};
use lsp_server::ErrorCode;
use lsp_types::{
self as lsp, CodeAction, CodeActionKind, CodeActionOrCommand, DiagnosticRelatedInformation,
@@ -50,10 +52,15 @@ pub(crate) fn to_location(vfs: &Vfs, frange: FileRange) -> Location {
Location::new(uri, to_range(&line_map, frange.range))
}
pub(crate) fn to_pos(line_map: &LineMap, pos: TextSize) -> Position {
let (line, col) = line_map.line_col_for_pos(pos);
Position::new(line, col)
}
pub(crate) fn to_range(line_map: &LineMap, range: TextRange) -> Range {
let (line1, col1) = line_map.line_col_for_pos(range.start());
let (line2, col2) = line_map.line_col_for_pos(range.end());
Range::new(Position::new(line1, col1), Position::new(line2, col2))
let start = to_pos(line_map, range.start());
let end = to_pos(line_map, range.end());
Range::new(start, end)
}
pub(crate) fn to_diagnostics(
@@ -166,6 +173,7 @@ pub(crate) fn to_completion_item(line_map: &LineMap, item: CompletionItem) -> ls
commit_characters: None,
data: None,
tags: None,
label_details: None,
}
}
@@ -333,3 +341,21 @@ pub(crate) fn to_document_highlight(
})
.collect()
}
pub(crate) fn to_inlay_hint(line_map: &LineMap, hint: InlayHint) -> lsp::InlayHint {
lsp::InlayHint {
position: to_pos(line_map, hint.pos),
label: InlayHintLabel::String(hint.label),
kind: match hint.kind {
InlayKind::WithHint => None,
},
text_edits: None,
tooltip: Some(InlayHintTooltip::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: hint.tooltip,
})),
padding_left: None,
padding_right: None,
data: None,
}
}

View File

@@ -4,10 +4,11 @@ use lsp_types::{
CodeActionParams, CodeActionResponse, CompletionParams, CompletionResponse, Diagnostic,
DocumentFormattingParams, DocumentHighlight, DocumentHighlightParams, DocumentLink,
DocumentLinkParams, DocumentSymbolParams, DocumentSymbolResponse, GotoDefinitionParams,
GotoDefinitionResponse, Hover, HoverParams, Location, Position, PrepareRenameResponse, Range,
ReferenceParams, RenameParams, SelectionRange, SelectionRangeParams, SemanticTokens,
SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult,
SemanticTokensResult, TextDocumentPositionParams, TextEdit, Url, WorkspaceEdit,
GotoDefinitionResponse, Hover, HoverParams, InlayHint, InlayHintParams, Location, Position,
PrepareRenameResponse, Range, ReferenceParams, RenameParams, SelectionRange,
SelectionRangeParams, SemanticTokens, SemanticTokensParams, SemanticTokensRangeParams,
SemanticTokensRangeResult, SemanticTokensResult, TextDocumentPositionParams, TextEdit, Url,
WorkspaceEdit,
};
use std::path::Path;
use std::process;
@@ -328,3 +329,17 @@ pub(crate) fn document_highlight(
let ret = convert::to_document_highlight(&line_map, &ret);
Ok(Some(ret))
}
pub(crate) fn inlay_hints(
snap: StateSnapshot,
params: InlayHintParams,
) -> Result<Option<Vec<InlayHint>>> {
let (file, line_map) = convert::from_file(&snap.vfs(), &params.text_document)?;
let (_, range) = convert::from_range(&snap.vfs(), file, params.range)?;
let hints = snap.analysis.inlay_hints(FileRange::new(file, range))?;
let hints = hints
.into_iter()
.map(|hint| convert::to_inlay_hint(&line_map, hint))
.collect();
Ok(Some(hints))
}

View File

@@ -227,6 +227,7 @@ impl Server {
.on::<req::DocumentLinkRequest>(handler::document_links)
.on::<req::CodeActionRequest>(handler::code_action)
.on::<req::DocumentHighlightRequest>(handler::document_highlight)
.on::<req::InlayHintRequest>(handler::inlay_hints)
.finish();
}