Annotation, AnnotationKind, Assist, AssistKind, CallInfo, Cancellable, CompletionItem,
CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit,
Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, InlayHint,
- InlayKind, Markup, NavigationTarget, ReferenceAccess, RenameError, Runnable, Severity,
+ InlayKind, Markup, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity,
SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
};
use itertools::Itertools;
use crate::{
cargo_target_spec::CargoTargetSpec,
+ config::Config,
global_state::GlobalStateSnapshot,
line_index::{LineEndings, LineIndex, OffsetEncoding},
- lsp_ext, semantic_tokens, Result,
+ lsp_ext,
+ lsp_utils::invalid_params_error,
+ semantic_tokens, Result,
};
pub(crate) fn position(line_index: &LineIndex, offset: TextSize) -> lsp_types::Position {
pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
match symbol_kind {
- SymbolKind::Function => lsp_types::SymbolKind::Function,
- SymbolKind::Struct => lsp_types::SymbolKind::Struct,
- SymbolKind::Enum => lsp_types::SymbolKind::Enum,
- SymbolKind::Variant => lsp_types::SymbolKind::EnumMember,
- SymbolKind::Trait => lsp_types::SymbolKind::Interface,
- SymbolKind::Macro => lsp_types::SymbolKind::Function,
- SymbolKind::Module => lsp_types::SymbolKind::Module,
- SymbolKind::TypeAlias | SymbolKind::TypeParam => lsp_types::SymbolKind::TypeParameter,
- SymbolKind::Field => lsp_types::SymbolKind::Field,
- SymbolKind::Static => lsp_types::SymbolKind::Constant,
- SymbolKind::Const => lsp_types::SymbolKind::Constant,
- SymbolKind::ConstParam => lsp_types::SymbolKind::Constant,
- SymbolKind::Impl => lsp_types::SymbolKind::Object,
+ SymbolKind::Function => lsp_types::SymbolKind::FUNCTION,
+ SymbolKind::Struct => lsp_types::SymbolKind::STRUCT,
+ SymbolKind::Enum => lsp_types::SymbolKind::ENUM,
+ SymbolKind::Variant => lsp_types::SymbolKind::ENUM_MEMBER,
+ SymbolKind::Trait => lsp_types::SymbolKind::INTERFACE,
+ SymbolKind::Macro
+ | SymbolKind::BuiltinAttr
+ | SymbolKind::Attribute
+ | SymbolKind::Derive => lsp_types::SymbolKind::FUNCTION,
+ SymbolKind::Module | SymbolKind::ToolModule => lsp_types::SymbolKind::MODULE,
+ SymbolKind::TypeAlias | SymbolKind::TypeParam => lsp_types::SymbolKind::TYPE_PARAMETER,
+ SymbolKind::Field => lsp_types::SymbolKind::FIELD,
+ SymbolKind::Static => lsp_types::SymbolKind::CONSTANT,
+ SymbolKind::Const => lsp_types::SymbolKind::CONSTANT,
+ SymbolKind::ConstParam => lsp_types::SymbolKind::CONSTANT,
+ SymbolKind::Impl => lsp_types::SymbolKind::OBJECT,
SymbolKind::Local
| SymbolKind::SelfParam
| SymbolKind::LifetimeParam
| SymbolKind::ValueParam
- | SymbolKind::Label => lsp_types::SymbolKind::Variable,
- SymbolKind::Union => lsp_types::SymbolKind::Struct,
+ | SymbolKind::Label => lsp_types::SymbolKind::VARIABLE,
+ SymbolKind::Union => lsp_types::SymbolKind::STRUCT,
}
}
pub(crate) fn structure_node_kind(kind: StructureNodeKind) -> lsp_types::SymbolKind {
match kind {
StructureNodeKind::SymbolKind(symbol) => symbol_kind(symbol),
- StructureNodeKind::Region => lsp_types::SymbolKind::Namespace,
+ StructureNodeKind::Region => lsp_types::SymbolKind::NAMESPACE,
}
}
pub(crate) fn document_highlight_kind(
- reference_access: ReferenceAccess,
+ category: ReferenceCategory,
) -> lsp_types::DocumentHighlightKind {
- match reference_access {
- ReferenceAccess::Read => lsp_types::DocumentHighlightKind::Read,
- ReferenceAccess::Write => lsp_types::DocumentHighlightKind::Write,
+ match category {
+ ReferenceCategory::Read => lsp_types::DocumentHighlightKind::READ,
+ ReferenceCategory::Write => lsp_types::DocumentHighlightKind::WRITE,
}
}
pub(crate) fn diagnostic_severity(severity: Severity) -> lsp_types::DiagnosticSeverity {
match severity {
- Severity::Error => lsp_types::DiagnosticSeverity::Error,
- Severity::WeakWarning => lsp_types::DiagnosticSeverity::Hint,
+ Severity::Error => lsp_types::DiagnosticSeverity::ERROR,
+ Severity::WeakWarning => lsp_types::DiagnosticSeverity::HINT,
}
}
completion_item_kind: CompletionItemKind,
) -> lsp_types::CompletionItemKind {
match completion_item_kind {
- CompletionItemKind::Attribute => lsp_types::CompletionItemKind::EnumMember,
- CompletionItemKind::Binding => lsp_types::CompletionItemKind::Variable,
- CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::Struct,
- CompletionItemKind::Keyword => lsp_types::CompletionItemKind::Keyword,
- CompletionItemKind::Method => lsp_types::CompletionItemKind::Method,
- CompletionItemKind::Snippet => lsp_types::CompletionItemKind::Snippet,
- CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::Reference,
+ CompletionItemKind::Binding => lsp_types::CompletionItemKind::VARIABLE,
+ CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::STRUCT,
+ CompletionItemKind::Keyword => lsp_types::CompletionItemKind::KEYWORD,
+ CompletionItemKind::Method => lsp_types::CompletionItemKind::METHOD,
+ CompletionItemKind::Snippet => lsp_types::CompletionItemKind::SNIPPET,
+ CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::REFERENCE,
CompletionItemKind::SymbolKind(symbol) => match symbol {
- SymbolKind::Const => lsp_types::CompletionItemKind::Constant,
- SymbolKind::ConstParam => lsp_types::CompletionItemKind::TypeParameter,
- SymbolKind::Enum => lsp_types::CompletionItemKind::Enum,
- SymbolKind::Field => lsp_types::CompletionItemKind::Field,
- SymbolKind::Function => lsp_types::CompletionItemKind::Function,
- SymbolKind::Impl => lsp_types::CompletionItemKind::Text,
- SymbolKind::Label => lsp_types::CompletionItemKind::Variable,
- SymbolKind::LifetimeParam => lsp_types::CompletionItemKind::TypeParameter,
- SymbolKind::Local => lsp_types::CompletionItemKind::Variable,
- SymbolKind::Macro => lsp_types::CompletionItemKind::Method,
- SymbolKind::Module => lsp_types::CompletionItemKind::Module,
- SymbolKind::SelfParam => lsp_types::CompletionItemKind::Value,
- SymbolKind::Static => lsp_types::CompletionItemKind::Value,
- SymbolKind::Struct => lsp_types::CompletionItemKind::Struct,
- SymbolKind::Trait => lsp_types::CompletionItemKind::Interface,
- SymbolKind::TypeAlias => lsp_types::CompletionItemKind::Struct,
- SymbolKind::TypeParam => lsp_types::CompletionItemKind::TypeParameter,
- SymbolKind::Union => lsp_types::CompletionItemKind::Struct,
- SymbolKind::ValueParam => lsp_types::CompletionItemKind::Value,
- SymbolKind::Variant => lsp_types::CompletionItemKind::EnumMember,
+ SymbolKind::Attribute => lsp_types::CompletionItemKind::FUNCTION,
+ SymbolKind::Const => lsp_types::CompletionItemKind::CONSTANT,
+ SymbolKind::ConstParam => lsp_types::CompletionItemKind::TYPE_PARAMETER,
+ SymbolKind::Derive => lsp_types::CompletionItemKind::FUNCTION,
+ SymbolKind::Enum => lsp_types::CompletionItemKind::ENUM,
+ SymbolKind::Field => lsp_types::CompletionItemKind::FIELD,
+ SymbolKind::Function => lsp_types::CompletionItemKind::FUNCTION,
+ SymbolKind::Impl => lsp_types::CompletionItemKind::TEXT,
+ SymbolKind::Label => lsp_types::CompletionItemKind::VARIABLE,
+ SymbolKind::LifetimeParam => lsp_types::CompletionItemKind::TYPE_PARAMETER,
+ SymbolKind::Local => lsp_types::CompletionItemKind::VARIABLE,
+ SymbolKind::Macro => lsp_types::CompletionItemKind::FUNCTION,
+ SymbolKind::Module => lsp_types::CompletionItemKind::MODULE,
+ SymbolKind::SelfParam => lsp_types::CompletionItemKind::VALUE,
+ SymbolKind::Static => lsp_types::CompletionItemKind::VALUE,
+ SymbolKind::Struct => lsp_types::CompletionItemKind::STRUCT,
+ SymbolKind::Trait => lsp_types::CompletionItemKind::INTERFACE,
+ SymbolKind::TypeAlias => lsp_types::CompletionItemKind::STRUCT,
+ SymbolKind::TypeParam => lsp_types::CompletionItemKind::TYPE_PARAMETER,
+ SymbolKind::Union => lsp_types::CompletionItemKind::STRUCT,
+ SymbolKind::ValueParam => lsp_types::CompletionItemKind::VALUE,
+ SymbolKind::Variant => lsp_types::CompletionItemKind::ENUM_MEMBER,
+ SymbolKind::BuiltinAttr => lsp_types::CompletionItemKind::FUNCTION,
+ SymbolKind::ToolModule => lsp_types::CompletionItemKind::MODULE,
},
}
}
) -> lsp_ext::SnippetTextEdit {
let text_edit = text_edit(line_index, indel);
let insert_text_format =
- if is_snippet { Some(lsp_types::InsertTextFormat::Snippet) } else { None };
+ if is_snippet { Some(lsp_types::InsertTextFormat::SNIPPET) } else { None };
lsp_ext::SnippetTextEdit {
range: text_edit.range,
new_text: text_edit.new_text,
}
pub(crate) fn completion_items(
- insert_replace_support: bool,
- enable_imports_on_the_fly: bool,
+ config: &Config,
line_index: &LineIndex,
tdpp: lsp_types::TextDocumentPositionParams,
items: Vec<CompletionItem>,
let max_relevance = items.iter().map(|it| it.relevance().score()).max().unwrap_or_default();
let mut res = Vec::with_capacity(items.len());
for item in items {
- completion_item(
- &mut res,
- insert_replace_support,
- enable_imports_on_the_fly,
- line_index,
- &tdpp,
- max_relevance,
- item,
- )
+ completion_item(&mut res, config, line_index, &tdpp, max_relevance, item)
}
res
}
fn completion_item(
acc: &mut Vec<lsp_types::CompletionItem>,
- insert_replace_support: bool,
- enable_imports_on_the_fly: bool,
+ config: &Config,
line_index: &LineIndex,
tdpp: &lsp_types::TextDocumentPositionParams,
max_relevance: u32,
let source_range = item.source_range();
for indel in item.text_edit().iter() {
if indel.delete.contains_range(source_range) {
- let insert_replace_support = insert_replace_support.then(|| tdpp.position);
+ let insert_replace_support = config.insert_replace_support().then(|| tdpp.position);
text_edit = Some(if indel.delete == source_range {
self::completion_text_edit(line_index, insert_replace_support, indel.clone())
} else {
label: item.label().to_string(),
detail: item.detail().map(|it| it.to_string()),
filter_text: Some(item.lookup().to_string()),
- kind: item.kind().map(completion_item_kind),
+ kind: Some(completion_item_kind(item.kind())),
text_edit: Some(text_edit),
additional_text_edits: Some(additional_text_edits),
documentation: item.documentation().map(documentation),
set_score(&mut lsp_item, max_relevance, item.relevance());
if item.deprecated() {
- lsp_item.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated])
+ lsp_item.tags = Some(vec![lsp_types::CompletionItemTag::DEPRECATED])
}
- if item.trigger_call_info() {
+ if item.trigger_call_info() && config.client_commands().trigger_parameter_hints {
lsp_item.command = Some(command::trigger_parameter_hints());
}
if item.is_snippet() {
- lsp_item.insert_text_format = Some(lsp_types::InsertTextFormat::Snippet);
+ lsp_item.insert_text_format = Some(lsp_types::InsertTextFormat::SNIPPET);
}
- if enable_imports_on_the_fly {
- if let Some(import_edit) = item.import_to_add() {
- let import_path = &import_edit.import.import_path;
- if let Some(import_name) = import_path.segments().last() {
- let data = lsp_ext::CompletionResolveData {
- position: tdpp.clone(),
- full_import_path: import_path.to_string(),
- imported_name: import_name.to_string(),
- };
+ if config.completion().enable_imports_on_the_fly {
+ if let imports @ [_, ..] = item.imports_to_add() {
+ let imports: Vec<_> = imports
+ .iter()
+ .filter_map(|import_edit| {
+ let import_path = &import_edit.import.import_path;
+ let import_name = import_path.segments().last()?;
+ Some(lsp_ext::CompletionImport {
+ full_import_path: import_path.to_string(),
+ imported_name: import_name.to_string(),
+ })
+ })
+ .collect();
+ if !imports.is_empty() {
+ let data = lsp_ext::CompletionResolveData { position: tdpp.clone(), imports };
lsp_item.data = Some(to_value(data).unwrap());
}
}
};
lsp_types::SignatureHelp {
signatures: vec![signature],
- active_signature: None,
+ active_signature: Some(0),
active_parameter,
}
}
let mut mods = semantic_tokens::ModifierSet::default();
let type_ = match highlight.tag {
HlTag::Symbol(symbol) => match symbol {
+ SymbolKind::Attribute => semantic_tokens::ATTRIBUTE,
+ SymbolKind::Derive => semantic_tokens::DERIVE,
SymbolKind::Module => lsp_types::SemanticTokenType::NAMESPACE,
SymbolKind::Impl => semantic_tokens::TYPE_ALIAS,
SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,
SymbolKind::TypeAlias => semantic_tokens::TYPE_ALIAS,
SymbolKind::Trait => lsp_types::SemanticTokenType::INTERFACE,
SymbolKind::Macro => lsp_types::SemanticTokenType::MACRO,
+ SymbolKind::BuiltinAttr => semantic_tokens::BUILTIN_ATTRIBUTE,
+ SymbolKind::ToolModule => semantic_tokens::TOOL_MODULE,
},
- HlTag::Attribute => semantic_tokens::ATTRIBUTE,
+ HlTag::AttributeBracket => semantic_tokens::ATTRIBUTE_BRACKET,
HlTag::BoolLiteral => semantic_tokens::BOOLEAN,
- HlTag::BuiltinAttr => semantic_tokens::BUILTIN_ATTRIBUTE,
HlTag::BuiltinType => semantic_tokens::BUILTIN_TYPE,
HlTag::ByteLiteral | HlTag::NumericLiteral => lsp_types::SemanticTokenType::NUMBER,
HlTag::CharLiteral => semantic_tokens::CHAR,
HlPunct::Colon => semantic_tokens::COLON,
HlPunct::Semi => semantic_tokens::SEMICOLON,
HlPunct::Other => semantic_tokens::PUNCTUATION,
+ HlPunct::MacroBang => semantic_tokens::MACRO_BANG,
},
};
for modifier in highlight.mods.iter() {
let modifier = match modifier {
+ HlMod::Associated => continue,
+ HlMod::Async => semantic_tokens::ASYNC,
HlMod::Attribute => semantic_tokens::ATTRIBUTE_MODIFIER,
+ HlMod::Callable => semantic_tokens::CALLABLE,
+ HlMod::Consuming => semantic_tokens::CONSUMING,
+ HlMod::ControlFlow => semantic_tokens::CONTROL_FLOW,
+ HlMod::CrateRoot => semantic_tokens::CRATE_ROOT,
+ HlMod::DefaultLibrary => lsp_types::SemanticTokenModifier::DEFAULT_LIBRARY,
HlMod::Definition => lsp_types::SemanticTokenModifier::DECLARATION,
HlMod::Documentation => lsp_types::SemanticTokenModifier::DOCUMENTATION,
HlMod::Injected => semantic_tokens::INJECTED,
- HlMod::ControlFlow => semantic_tokens::CONTROL_FLOW,
- HlMod::Mutable => semantic_tokens::MUTABLE,
- HlMod::Consuming => semantic_tokens::CONSUMING,
- HlMod::Async => semantic_tokens::ASYNC,
+ HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK,
HlMod::Library => semantic_tokens::LIBRARY,
+ HlMod::Mutable => semantic_tokens::MUTABLE,
HlMod::Public => semantic_tokens::PUBLIC,
- HlMod::Unsafe => semantic_tokens::UNSAFE,
- HlMod::Callable => semantic_tokens::CALLABLE,
+ HlMod::Reference => semantic_tokens::REFERENCE,
HlMod::Static => lsp_types::SemanticTokenModifier::STATIC,
- HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK,
HlMod::Trait => semantic_tokens::TRAIT_MODIFIER,
- HlMod::Associated => continue,
+ HlMod::Unsafe => semantic_tokens::UNSAFE,
};
mods |= modifier;
}
Ok(loc)
}
-/// Perefer using `location_link`, if the client has the cap.
+/// Prefer using `location_link`, if the client has the cap.
pub(crate) fn location_from_nav(
snap: &GlobalStateSnapshot,
nav: NavigationTarget,
let text_edit = lsp_ext::SnippetTextEdit {
range: lsp_types::Range::default(),
new_text: initial_contents,
- insert_text_format: Some(lsp_types::InsertTextFormat::PlainText),
+ insert_text_format: Some(lsp_types::InsertTextFormat::PLAIN_TEXT),
annotation_id: None,
};
let edit_file =
) -> Result<lsp_types::CallHierarchyItem> {
let name = target.name.to_string();
let detail = target.description.clone();
- let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::Function);
+ let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::FUNCTION);
let (uri, range, selection_range) = location_info(snap, target)?;
Ok(lsp_types::CallHierarchyItem {
name,
snap: &GlobalStateSnapshot,
annotation: Annotation,
) -> Result<()> {
+ let client_commands_config = snap.config.client_commands();
match annotation.kind {
AnnotationKind::Runnable(run) => {
let line_index = snap.file_line_index(run.nav.file_id)?;
let r = runnable(snap, run)?;
let lens_config = snap.config.lens();
- if lens_config.run {
+ if lens_config.run && client_commands_config.run_single {
let command = command::run_single(&r, &title);
acc.push(lsp_types::CodeLens {
range: annotation_range,
data: None,
})
}
- if lens_config.debug && can_debug {
+ if lens_config.debug && can_debug && client_commands_config.debug_single {
let command = command::debug_single(&r);
acc.push(lsp_types::CodeLens {
range: annotation_range,
}
}
AnnotationKind::HasImpls { position: file_position, data } => {
+ if !client_commands_config.show_reference {
+ return Ok(());
+ }
let line_index = snap.file_line_index(file_position.file_id)?;
let annotation_range = range(&line_index, annotation.range);
let url = url(snap, file_position.file_id);
})
}
AnnotationKind::HasReferences { position: file_position, data } => {
+ if !client_commands_config.show_reference {
+ return Ok(());
+ }
let line_index = snap.file_line_index(file_position.file_id)?;
let annotation_range = range(&line_index, annotation.range);
let url = url(snap, file_position.file_id);
}
}
-pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent {
+pub(crate) fn markup_content(
+ markup: Markup,
+ kind: ide::HoverDocFormat,
+) -> lsp_types::MarkupContent {
+ let kind = match kind {
+ ide::HoverDocFormat::Markdown => lsp_types::MarkupKind::Markdown,
+ ide::HoverDocFormat::PlainText => lsp_types::MarkupKind::PlainText,
+ };
let value = crate::markdown::format_docs(markup.as_str());
- lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value }
+ lsp_types::MarkupContent { kind, value }
}
pub(crate) fn rename_error(err: RenameError) -> crate::LspError {
- crate::LspError { code: lsp_server::ErrorCode::InvalidParams as i32, message: err.to_string() }
+ // This is wrong, but we don't have a better alternative I suppose?
+ // https://github.com/microsoft/language-server-protocol/issues/1341
+ invalid_params_error(err.to_string())
}
#[cfg(test)]
use std::sync::Arc;
use ide::Analysis;
- use ide_db::helpers::{
- insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
- SnippetCap,
- };
use super::*;
- #[test]
- fn test_completion_with_ref() {
- let fixture = r#"
- struct Foo;
- fn foo(arg: &Foo) {}
- fn main() {
- let arg = Foo;
- foo($0)
- }"#;
-
- let (offset, text) = test_utils::extract_offset(fixture);
- let line_index = LineIndex {
- index: Arc::new(ide::LineIndex::new(&text)),
- endings: LineEndings::Unix,
- encoding: OffsetEncoding::Utf16,
- };
- let (analysis, file_id) = Analysis::from_single_file(text);
-
- let file_position = ide_db::base_db::FilePosition { file_id, offset };
- let mut items = analysis
- .completions(
- &ide::CompletionConfig {
- enable_postfix_completions: true,
- enable_imports_on_the_fly: true,
- enable_self_on_the_fly: true,
- add_call_parenthesis: true,
- add_call_argument_snippets: true,
- snippet_cap: SnippetCap::new(true),
- insert_use: InsertUseConfig {
- granularity: ImportGranularity::Item,
- prefix_kind: PrefixKind::Plain,
- enforce_granularity: true,
- group: true,
- skip_glob_imports: true,
- },
- },
- file_position,
- )
- .unwrap()
- .unwrap();
- items.retain(|c| c.label().ends_with("arg"));
- let items = completion_items(
- false,
- false,
- &line_index,
- lsp_types::TextDocumentPositionParams {
- text_document: lsp_types::TextDocumentIdentifier {
- uri: "file://main.rs".parse().unwrap(),
- },
- position: position(&line_index, file_position.offset),
- },
- items,
- );
- let items: Vec<(String, Option<String>)> =
- items.into_iter().map(|c| (c.label, c.sort_text)).collect();
-
- expect_test::expect![[r#"
- [
- (
- "&arg",
- Some(
- "fffffff9",
- ),
- ),
- (
- "arg",
- Some(
- "fffffffd",
- ),
- ),
- ]
- "#]]
- .assert_debug_eq(&items);
- }
-
#[test]
fn conv_fold_line_folding_only_fixup() {
let text = r#"mod a;