diff --git a/Cargo.lock b/Cargo.lock index c6e58e530cee..e0f051908cb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -699,9 +699,9 @@ dependencies = [ [[package]] name = "gen-lsp-types" -version = "0.4.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b8ec601e62362b666a3def1fed667ee87b10a4507402618376d142a05373c6" +checksum = "4cd635c5206acd03ea024d6b5902539e5c903de3afa220fdb5c94b583af77f4f" dependencies = [ "serde", "serde_json", @@ -2571,9 +2571,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "indexmap", "itoa", diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 08c1dc5f3d70..5c81ec7ece11 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -2731,7 +2731,7 @@ impl<'db> ExprCollector<'db> { pats.push(self.collect_pat(first, binding_list)); binding_list.reject_new = true; for rest in it { - for (_, it) in binding_list.is_used.iter_mut() { + for it in binding_list.is_used.values_mut() { *it = false; } pats.push(self.collect_pat(rest, binding_list)); diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 03c7ebd69355..6f916c83ef17 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -397,7 +397,10 @@ impl UseTreeLowering<'_> { Some(path) => { match ModPath::from_src(self.db, path, span_for_range) { Some(it) => Some(it), - None => return None, // FIXME: report errors somewhere + None => { + // FIXME: report errors somewhere + return None; + } } } }; diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs index 00457ad44b30..22413e7851db 100644 --- a/crates/hir-expand/src/eager.rs +++ b/crates/hir-expand/src/eager.rs @@ -232,7 +232,7 @@ fn eager_macro_recur( let syntax_node = parse.syntax_node(); ExpandResult { value: Some(( - syntax_node.clone_for_update(), + syntax_node.clone(), offset + syntax_node.text_range().len(), )), err: err.clone().or_else(|| err2.clone()), diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs index a8ed4126abea..ea0881923cb7 100644 --- a/crates/hir-ty/src/autoderef.rs +++ b/crates/hir-ty/src/autoderef.rs @@ -207,11 +207,10 @@ where } else { (AutoderefKind::Builtin, ty) } - } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) { + } else { + let ty = self.overloaded_deref_ty(self.state.cur_ty)?; // The overloaded deref check already normalizes the pointee type. (AutoderefKind::Overloaded, ty) - } else { - return None; }; self.state.steps.push(self.state.cur_ty, kind); diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs index 08860e1e456c..0a4d016c6a9c 100644 --- a/crates/hir-ty/src/drop.rs +++ b/crates/hir-ty/src/drop.rs @@ -28,10 +28,7 @@ pub fn destructor(db: &dyn HirDatabase, adt: AdtId) -> Option { let interner = DbInterner::new_with(db, module.krate(db)); let drop_trait = interner.lang_items().Drop?; let impls = match module.block(db) { - Some(block) => match TraitImpls::for_block(db, block) { - Some(it) => &**it, - None => return None, - }, + Some(block) => TraitImpls::for_block(db, block)?, None => TraitImpls::for_crate(db, module.krate(db)), }; impls.for_trait_and_self_ty(drop_trait, &SimplifiedType::Adt(adt.into())).0.first().copied() diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index b68f664d512e..2772663ec9ff 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -678,7 +678,7 @@ impl TraitImpls { Arc::new(result) } - #[salsa::tracked(returns(ref))] + #[salsa::tracked(returns(as_deref))] pub fn for_block(db: &dyn HirDatabase, block: BlockId) -> Option> { let _p = tracing::info_span!("inherent_impls_in_block_query").entered(); @@ -687,7 +687,7 @@ impl TraitImpls { if result.map.is_empty() { None } else { Some(Box::new(result)) } } - #[salsa::tracked(returns(ref))] + #[salsa::tracked(returns(deref))] pub fn for_crate_and_deps(db: &dyn HirDatabase, krate: Crate) -> Box<[Arc]> { krate.transitive_deps(db).iter().map(|&dep| Self::for_crate(db, dep).clone()).collect() } @@ -830,7 +830,7 @@ impl TraitImpls { for_each: &mut dyn FnMut(&TraitImpls), ) { let blocks = std::iter::successors(block, |block| block.loc(db).module.block(db)); - blocks.filter_map(|block| Self::for_block(db, block).as_deref()).for_each(&mut *for_each); + blocks.filter_map(|block| Self::for_block(db, block)).for_each(&mut *for_each); Self::for_crate_and_deps(db, krate).iter().map(|it| &**it).for_each(for_each); } @@ -858,11 +858,11 @@ impl TraitImpls { .take_while(move |&block| { other_block.is_none_or(|other_block| other_block != block) }) - .filter_map(move |block| TraitImpls::for_block(db, block).as_deref()) + .filter_map(move |block| TraitImpls::for_block(db, block)) }; if trait_block == type_block { blocks_iter(trait_block) - .filter_map(|block| TraitImpls::for_block(db, block).as_deref()) + .filter_map(|block| TraitImpls::for_block(db, block)) .for_each(for_each); } else { for_each_block(trait_block, type_block).for_each(&mut *for_each); diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index d1277762eb14..ab7e6df3f515 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1404,11 +1404,14 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { expr_id: ExprId, ) -> Result<'db, ()> { if let Expr::Field { expr, name } = &self.store[expr_id] { - if let TyKind::Tuple(..) = self.expr_ty_after_adjustments(*expr).kind() { + if let TyKind::Tuple(tys) = self.expr_ty_after_adjustments(*expr).kind() { let index = name.as_tuple_index().ok_or(MirLowerError::TypeError("named field on tuple"))? as u32; - *place = place.project(ProjectionElem::Field(FieldIndex(index))) + if tys.get(index as usize).is_none() { + return Err(MirLowerError::TypeError("tuple field index out of range")); + } + *place = place.project(ProjectionElem::Field(FieldIndex(index))); } else { let field = self .infer diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index f273a823ba18..66b51a0e95b5 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -137,7 +137,8 @@ impl<'db> MirLowerCtx<'_, 'db> { } Pat::Wild => (current, current_else), Pat::Tuple { args, ellipsis } => { - let subst = match self.infer.pat_ty(pattern).kind() { + let place_ty = cond_place.ty(&self.result, &self.infcx, self.env).ty; + let subst = match place_ty.kind() { TyKind::Tuple(s) => s, _ => { return Err(MirLowerError::TypeError( diff --git a/crates/hir-ty/src/mir/lower/tests.rs b/crates/hir-ty/src/mir/lower/tests.rs index 8e10284cc1f8..d8f7d549d6bf 100644 --- a/crates/hir-ty/src/mir/lower/tests.rs +++ b/crates/hir-ty/src/mir/lower/tests.rs @@ -108,3 +108,29 @@ pub struct AssocTy { "#, ); } + +#[test] +fn borrowck_tuple_field_projection_recovery_does_not_panic() { + check_borrowck( + r#" +//- minicore: sized +fn tuple_field() { + let t = (1,); + let x = t.1; +} + "#, + ); +} + +#[test] +fn borrowck_alias_projection_recovery_does_not_panic() { + check_borrowck( + r#" +//- minicore: sized +trait Tr { type A; } +fn alias(x: T::A) { + let (a, b) = x; +} + "#, + ); +} diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 998c1b8b9153..96fb65882c6a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -4715,7 +4715,7 @@ impl Impl { &mut |impls| extend_with_impls(Either::Left(impls.for_self_ty(&simplified_ty))), ); iter::successors(module.block(db), |block| block.loc(db).module.block(db)) - .filter_map(|block| TraitImpls::for_block(db, block).as_deref()) + .filter_map(|block| TraitImpls::for_block(db, block)) .for_each(|impls| impls.for_self_ty(&simplified_ty, &mut extend_with_impls)); for &krate in &*all_crates(db) { TraitImpls::for_crate(db, krate) diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 9e4d825ab229..21830f9d0d78 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -1427,11 +1427,10 @@ impl<'db> SourceAnalyzer<'db> { let ty = if let Some(expr) = ast::Expr::cast(parent.clone()) { let expr_id = self.expr_id(expr)?; self.infer()?.type_of_expr_or_pat(expr_id)? - } else if let Some(pat) = ast::Pat::cast(parent) { + } else { + let pat = ast::Pat::cast(parent)?; let pat_id = self.pat_id(&pat)?; self.infer()?.expr_or_pat_ty(pat_id) - } else { - return None; }; let (subst, expected_resolution) = match ty.kind() { TyKind::Adt(adt_def, subst) => { diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 632fe0d72cfa..8e39cfc49c16 100644 --- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -573,7 +573,7 @@ fn resolve_tuple_of_enum_def( }) }) .collect::>>() - .and_then(|list| if list.is_empty() { None } else { Some(list) }) + .filter(|list| !list.is_empty()) } fn resolve_array_of_enum_def( diff --git a/crates/ide-assists/src/handlers/change_visibility.rs b/crates/ide-assists/src/handlers/change_visibility.rs index f17197a75055..18d7faeb2b02 100644 --- a/crates/ide-assists/src/handlers/change_visibility.rs +++ b/crates/ide-assists/src/handlers/change_visibility.rs @@ -67,14 +67,13 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> Option<()> { } check_is_not_variant(&field)?; (vis_offset(field.syntax()), field_name.syntax().text_range()) - } else if let Some(field) = ctx.find_node_at_offset::() { + } else { + let field = ctx.find_node_at_offset::()?; if field.visibility().is_some() { return None; } check_is_not_variant(&field)?; (vis_offset(field.syntax()), field.syntax().text_range()) - } else { - return None; }; acc.add( diff --git a/crates/ide-assists/src/handlers/extract_variable.rs b/crates/ide-assists/src/handlers/extract_variable.rs index 86dbf20facb6..0bd9d1a23aef 100644 --- a/crates/ide-assists/src/handlers/extract_variable.rs +++ b/crates/ide-assists/src/handlers/extract_variable.rs @@ -72,13 +72,11 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_, '_>) - let node = if ctx.has_empty_selection() { if let Some(t) = ctx.token_at_offset().find(|it| it.kind() == T![;]) { t.parent().and_then(ast::ExprStmt::cast)?.syntax().clone() - } else if let Some(expr) = ancestors_at_offset(ctx.source_file().syntax(), ctx.offset()) - .next() - .and_then(ast::Expr::cast) - { - expr.syntax().ancestors().find_map(valid_target_expr(ctx))?.syntax().clone() } else { - return None; + let expr = ancestors_at_offset(ctx.source_file().syntax(), ctx.offset()) + .next() + .and_then(ast::Expr::cast)?; + expr.syntax().ancestors().find_map(valid_target_expr(ctx))?.syntax().clone() } } else { match ctx.covering_element() { diff --git a/crates/ide-assists/src/handlers/generate_enum_is_method.rs b/crates/ide-assists/src/handlers/generate_enum_is_method.rs index 867eaf4c2987..53e77b49474c 100644 --- a/crates/ide-assists/src/handlers/generate_enum_is_method.rs +++ b/crates/ide-assists/src/handlers/generate_enum_is_method.rs @@ -141,7 +141,7 @@ impl Method { }; let variant_name = variant.name()?; - let fn_name = format!("is_{}", &to_lower_snake_case(&variant_name.text())); + let fn_name = format!("is_{}", to_lower_snake_case(&variant_name.text())); Some(Method { pattern_suffix, fn_name, variant_name }) } } diff --git a/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/crates/ide-assists/src/handlers/generate_enum_projection_method.rs index 4cdc801ec19d..8a194ae02bff 100644 --- a/crates/ide-assists/src/handlers/generate_enum_projection_method.rs +++ b/crates/ide-assists/src/handlers/generate_enum_projection_method.rs @@ -219,7 +219,7 @@ impl Method { fn new(variant: &ast::Variant, fn_name_prefix: &str) -> Option { use itertools::Itertools as _; let variant_name = variant.name()?; - let fn_name = format!("{fn_name_prefix}_{}", &to_lower_snake_case(&variant_name.text())); + let fn_name = format!("{fn_name_prefix}_{}", to_lower_snake_case(&variant_name.text())); match variant.kind() { ast::StructKind::Record(record) => { diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index 14dd4061e72f..3c3fde80f99e 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -491,7 +491,7 @@ fn get_fn_target( let mut file = ctx.vfs_file_id(); let target = match target_module { Some(target_module) => { - let (in_file, target) = next_space_for_fn_in_module(ctx.db(), target_module); + let (in_file, target) = next_space_for_fn_in_module(ctx.db(), target_module)?; file = in_file; target } @@ -1310,7 +1310,7 @@ fn next_space_for_fn_after_call_site(expr: ast::CallableExpr) -> Option (FileId, GeneratedFunctionTarget) { +) -> Option<(FileId, GeneratedFunctionTarget)> { let module_source = target_module.definition_source(db); let file = module_source.file_id.original_file(db); let assist_item = match &module_source.value { @@ -1318,14 +1318,13 @@ fn next_space_for_fn_in_module( Some(last_item) => GeneratedFunctionTarget::AfterItem(last_item.syntax().clone()), None => GeneratedFunctionTarget::AfterItem(it.syntax().clone()), }, - hir::ModuleSource::Module(it) => match it.item_list().and_then(|it| it.items().last()) { - Some(last_item) => GeneratedFunctionTarget::AfterItem(last_item.syntax().clone()), - None => { - let item_list = - it.item_list().expect("module definition source should have an item list"); - GeneratedFunctionTarget::InEmptyItemList(item_list.syntax().clone()) + hir::ModuleSource::Module(it) => { + let item_list = it.item_list()?; + match item_list.items().last() { + Some(last_item) => GeneratedFunctionTarget::AfterItem(last_item.syntax().clone()), + None => GeneratedFunctionTarget::InEmptyItemList(item_list.syntax().clone()), } - }, + } hir::ModuleSource::BlockExpr(it) => { if let Some(last_item) = it.statements().take_while(|stmt| matches!(stmt, ast::Stmt::Item(_))).last() @@ -1337,7 +1336,7 @@ fn next_space_for_fn_in_module( } }; - (file.file_id(db), assist_item) + Some((file.file_id(db), assist_item)) } #[derive(Clone, Copy)] @@ -2459,6 +2458,20 @@ pub(crate) fn bar() { ) } + #[test] + fn add_function_not_applicable_in_unresolved_module() { + check_assist_not_applicable( + generate_function, + r" +mod foo; + +fn main() { + foo::bar$0(); +} +", + ) + } + #[test] fn add_function_with_return_type() { check_assist( diff --git a/crates/ide-assists/src/handlers/merge_imports.rs b/crates/ide-assists/src/handlers/merge_imports.rs index c0356337057b..2d3b1b05400c 100644 --- a/crates/ide-assists/src/handlers/merge_imports.rs +++ b/crates/ide-assists/src/handlers/merge_imports.rs @@ -824,6 +824,17 @@ mod top { } use top::{a::A, b::{B as D, B as C}}; +", + ); + } + + #[test] + fn test_merge_with_trailing_path_separator() { + check_assist_not_applicable( + merge_imports, + r" +use foo::bar; +use foo::$0; ", ); } diff --git a/crates/ide-assists/src/handlers/remove_underscore.rs b/crates/ide-assists/src/handlers/remove_underscore.rs index 1ccdcda52d97..1b65e78378f2 100644 --- a/crates/ide-assists/src/handlers/remove_underscore.rs +++ b/crates/ide-assists/src/handlers/remove_underscore.rs @@ -37,7 +37,8 @@ pub(crate) fn remove_underscore(acc: &mut Assists, ctx: &AssistContext<'_, '_>) _ => return None, }; (text.to_owned(), name_ref.syntax().text_range(), def) - } else if let Some(name_ref) = ctx.find_node_at_offset::() { + } else { + let name_ref = ctx.find_node_at_offset::()?; let text = name_ref.text(); if !text.starts_with('_') { return None; @@ -48,8 +49,6 @@ pub(crate) fn remove_underscore(acc: &mut Assists, ctx: &AssistContext<'_, '_>) _ => return None, }; (text.to_owned(), name_ref.syntax().text_range(), def) - } else { - return None; }; if !def.usages(&ctx.sema).at_least_one() { diff --git a/crates/ide-completion/src/snippet.rs b/crates/ide-completion/src/snippet.rs index 67ca9db2304f..ee47c84708b4 100644 --- a/crates/ide-completion/src/snippet.rs +++ b/crates/ide-completion/src/snippet.rs @@ -181,10 +181,7 @@ fn import_edits( }; let mut res = Vec::with_capacity(requires.len()); for import in requires { - match resolve(import) { - Some(first) => res.extend(first), - None => return None, - } + res.extend(resolve(import)?) } Some(res) } diff --git a/crates/ide-db/src/imports/merge_imports.rs b/crates/ide-db/src/imports/merge_imports.rs index 9b68c27ae344..17fae61da613 100644 --- a/crates/ide-db/src/imports/merge_imports.rs +++ b/crates/ide-db/src/imports/merge_imports.rs @@ -827,7 +827,10 @@ fn split_prefix( make.use_tree(self_path, None, use_tree.rename(), false) } } else { - let suffix_segments = path.segments().skip(prefix.segments().count()); + let suffix_segments: Vec<_> = path.segments().skip(prefix.segments().count()).collect(); + if suffix_segments.is_empty() { + return None; + } let suffix_path = make.path_from_segments(suffix_segments, false); make.use_tree( suffix_path, diff --git a/crates/ide-db/src/syntax_helpers/suggest_name.rs b/crates/ide-db/src/syntax_helpers/suggest_name.rs index 15920595a827..42bfc7fe4b21 100644 --- a/crates/ide-db/src/syntax_helpers/suggest_name.rs +++ b/crates/ide-db/src/syntax_helpers/suggest_name.rs @@ -447,10 +447,9 @@ fn name_of_type<'db>( name } else if let Some((inner_ty, _)) = ty.as_reference() { return name_of_type(&inner_ty, db, edition); - } else if let Some(inner_ty) = ty.as_slice() { - return Some(sequence_name(Some(&inner_ty), db, edition)); } else { - return None; + let inner_ty = ty.as_slice()?; + return Some(sequence_name(Some(&inner_ty), db, edition)); }; normalize(&name, edition) } diff --git a/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs index 49d7d454dfe7..c6c8806ac989 100644 --- a/crates/ide/src/inlay_hints/closing_brace.rs +++ b/crates/ide/src/inlay_hints/closing_brace.rs @@ -139,7 +139,8 @@ pub(super) fn hints( _ => return None, } } - } else if let Some(mac) = ast::MacroCall::cast(node.clone()) { + } else { + let mac = ast::MacroCall::cast(node.clone())?; let last_token = mac.syntax().last_token()?; if last_token.kind() != T![;] && last_token.kind() != SyntaxKind::R_CURLY { return None; @@ -150,8 +151,6 @@ pub(super) fn hints( format!("{}!", mac.path()?), mac.path().and_then(|it| it.segment()).map(|it| it.syntax().text_range()), ) - } else { - return None; }; if let Some(mut next) = closing_token.next_token() { diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs index a49a85fe7804..b06079d8acd1 100644 --- a/crates/ide/src/typing.rs +++ b/crates/ide/src/typing.rs @@ -326,10 +326,8 @@ fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option { // Make sure dot is a part of call chain let receiver = if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { field_expr.expr()? - } else if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent.clone()) { - method_call_expr.receiver()? } else { - return None; + ast::MethodCallExpr::cast(parent.clone())?.receiver()? }; let receiver_is_multiline = receiver.syntax().text().find_char('\n').is_some(); diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index dd8649e09529..ae0c9571210a 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -29,7 +29,7 @@ ide-completion.workspace = true indexmap.workspace = true itertools.workspace = true scip = "0.7.1" -lsp-types = { version = "0.4.0", package = "gen-lsp-types", features=["url"] } +lsp-types = { version = "0.10.0", package = "gen-lsp-types", features = ["url"] } parking_lot = "0.12.4" xflags = "0.3.2" oorandom = "11.1.5" diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs index f690e38585a7..fdeb75bcef88 100644 --- a/crates/rust-analyzer/src/diagnostics.rs +++ b/crates/rust-analyzer/src/diagnostics.rs @@ -363,7 +363,7 @@ pub(crate) fn convert_diagnostic( href: lsp_types::Uri::parse(&d.code.url()).unwrap(), }), source: Some("rust-analyzer".to_owned()), - message: d.message, + message: lsp_types::Message::String(d.message), related_information: None, tags: d.unused.then(|| vec![lsp_types::DiagnosticTag::Unnecessary]), data: None, diff --git a/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs b/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs index 8568f4798c03..59ab748c2f62 100644 --- a/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/flycheck_to_proto.rs @@ -375,7 +375,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( if needs_primary_span_label && let Some(primary_span_label) = &primary_span.label { format_to!(message, "\n{}", primary_span_label); } - message + lsp_types::Message::String(message) }; let mut related_info_macro_calls = vec![]; @@ -475,7 +475,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( code: code.map(ToOwned::to_owned).map(lsp_types::Code::String), code_description: code_description.clone(), source: Some(source.to_owned()), - message: sub.related.message.clone(), + message: sub.related.message.clone().into(), related_information: Some(vec![back_ref.clone()]), tags: None, // don't apply modifiers again data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt b/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt index 71f99874b173..4f6d2009d2c6 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/clippy_pass_by_ref.txt @@ -54,7 +54,9 @@ source: Some( "clippy", ), - message: "this argument is passed by reference, but would be more efficient if passed by value\n#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref", + message: String( + "this argument is passed by reference, but would be more efficient if passed by value\n#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref", + ), tags: None, related_information: Some( [ @@ -171,7 +173,9 @@ source: Some( "clippy", ), - message: "lint level defined here", + message: String( + "lint level defined here", + ), tags: None, related_information: Some( [ @@ -262,7 +266,9 @@ source: Some( "clippy", ), - message: "consider passing by value instead: `self`", + message: String( + "consider passing by value instead: `self`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt b/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt index bd1abfe92118..f1bcc06991c6 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/handles_macro_location.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "can't compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`", + message: String( + "can't compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`", + ), tags: None, related_information: None, data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt b/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt index cc870c48af74..2405831682a7 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt @@ -30,7 +30,9 @@ source: Some( "rustc", ), - message: "Please register your known path in the path module", + message: String( + "Please register your known path in the path module", + ), tags: None, related_information: Some( [ @@ -97,7 +99,9 @@ source: Some( "rustc", ), - message: "Please register your known path in the path module", + message: String( + "Please register your known path in the path module", + ), tags: None, related_information: Some( [ @@ -164,7 +168,9 @@ source: Some( "rustc", ), - message: "Please register your known path in the path module", + message: String( + "Please register your known path in the path module", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt b/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt index 176d7198ac20..8500e61d300b 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "`main` function not found in crate `current`\nconsider adding a `main` function to `src/bin/current.rs`", + message: String( + "`main` function not found in crate `current`\nconsider adding a `main` function to `src/bin/current.rs`", + ), tags: None, related_information: None, data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt index e78ac4b27dab..909bbe2f6a2f 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_incompatible_type_for_trait.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "method `next` has an incompatible type for trait\nexpected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref>`", + message: String( + "method `next` has an incompatible type for trait\nexpected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref>`", + ), tags: None, related_information: None, data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt index add343d24566..39941652fda3 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_mismatched_type.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "mismatched types\nexpected usize, found u32", + message: String( + "mismatched types\nexpected usize, found u32", + ), tags: None, related_information: None, data: None, diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt index a510943965b4..3c10dacafb41 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_range_map_lsp_position.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "mismatched types\nexpected `u32`, found `&str`", + message: String( + "mismatched types\nexpected `u32`, found `&str`", + ), tags: None, related_information: Some( [ @@ -145,7 +147,9 @@ source: Some( "rustc", ), - message: "expected due to this", + message: String( + "expected due to this", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt index f5bf2dce3057..7410e1497287 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable.txt @@ -34,7 +34,9 @@ source: Some( "rustc", ), - message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", + message: String( + "unused variable: `foo`\n#[warn(unused_variables)] on by default", + ), tags: Some( [ Unnecessary, @@ -109,7 +111,9 @@ source: Some( "rustc", ), - message: "consider prefixing with an underscore: `_foo`", + message: String( + "consider prefixing with an underscore: `_foo`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt index 5f4aa7157644..0cff5ebba802 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_hint.txt @@ -34,7 +34,9 @@ source: Some( "rustc", ), - message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", + message: String( + "unused variable: `foo`\n#[warn(unused_variables)] on by default", + ), tags: Some( [ Unnecessary, @@ -109,7 +111,9 @@ source: Some( "rustc", ), - message: "consider prefixing with an underscore: `_foo`", + message: String( + "consider prefixing with an underscore: `_foo`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt index 26adf5311857..23797634ae05 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_unused_variable_as_info.txt @@ -34,7 +34,9 @@ source: Some( "rustc", ), - message: "unused variable: `foo`\n#[warn(unused_variables)] on by default", + message: String( + "unused variable: `foo`\n#[warn(unused_variables)] on by default", + ), tags: Some( [ Unnecessary, @@ -109,7 +111,9 @@ source: Some( "rustc", ), - message: "consider prefixing with an underscore: `_foo`", + message: String( + "consider prefixing with an underscore: `_foo`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt b/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt index cd3c24f0c3cf..900f99701b2b 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/rustc_wrong_number_of_parameters.txt @@ -54,7 +54,9 @@ source: Some( "rustc", ), - message: "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters", + message: String( + "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters", + ), tags: None, related_information: Some( [ @@ -145,7 +147,9 @@ source: Some( "rustc", ), - message: "defined here", + message: String( + "defined here", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt index a977d14cf784..bb8612f43ecf 100644 --- a/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt +++ b/crates/rust-analyzer/src/diagnostics/test_data/snap_multi_line_fix.txt @@ -54,7 +54,9 @@ source: Some( "clippy", ), - message: "returning the result of a let binding from a block\n`#[warn(clippy::let_and_return)]` on by default\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return", + message: String( + "returning the result of a let binding from a block\n`#[warn(clippy::let_and_return)]` on by default\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return", + ), tags: None, related_information: Some( [ @@ -171,7 +173,9 @@ source: Some( "clippy", ), - message: "unnecessary let binding", + message: String( + "unnecessary let binding", + ), tags: None, related_information: Some( [ @@ -262,7 +266,9 @@ source: Some( "clippy", ), - message: "return the expression directly: `(0..10).collect()`", + message: String( + "return the expression directly: `(0..10).collect()`", + ), tags: None, related_information: Some( [ diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs index 16dd9bee1fc0..f73ffb24eea3 100644 --- a/crates/rust-analyzer/src/flycheck.rs +++ b/crates/rust-analyzer/src/flycheck.rs @@ -494,33 +494,24 @@ impl<'a> Substitutions<'a> { let mut cmd = toolchain::command(&template.program, &template.cwd, extra_env); for arg in &template.args { if let Some(ix) = arg.find(LABEL_INLINE) { - if let Some(label) = self.label { - let mut arg = arg.to_string(); - arg.replace_range(ix..ix + LABEL_INLINE.len(), label); - cmd.arg(arg); - continue; - } else { - return None; - } + let label = self.label?; + let mut arg = arg.to_string(); + arg.replace_range(ix..ix + LABEL_INLINE.len(), label); + cmd.arg(arg); + continue; } if let Some(ix) = arg.find(SAVED_FILE_INLINE) { - if let Some(saved_file) = self.saved_file { - let mut arg = arg.to_string(); - arg.replace_range(ix..ix + SAVED_FILE_INLINE.len(), saved_file); - cmd.arg(arg); - continue; - } else { - return None; - } + let saved_file = self.saved_file?; + let mut arg = arg.to_string(); + arg.replace_range(ix..ix + SAVED_FILE_INLINE.len(), saved_file); + cmd.arg(arg); + continue; } // Legacy syntax: full argument match if arg == SAVED_FILE_PLACEHOLDER_DOLLAR { - if let Some(saved_file) = self.saved_file { - cmd.arg(saved_file); - continue; - } else { - return None; - } + let saved_file = self.saved_file?; + cmd.arg(saved_file); + continue; } cmd.arg(arg); } diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 2d01aa4d515e..5388f68f0219 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -661,17 +661,28 @@ impl GlobalState { // See https://github.com/rust-lang/rust-analyzer/issues/11404 // See https://github.com/rust-lang/rust-analyzer/issues/13130 - let patch_empty = |message: &mut String| { - if message.is_empty() { - " ".clone_into(message); + let patch_empty = |message: &mut lsp_types::Message| match message { + lsp_types::Message::String(m) if m.is_empty() => { + " ".clone_into(m); } + lsp_types::Message::MarkupContent(lsp_types::MarkupContent { + value, + kind: _, + }) if value.is_empty() => { + " ".clone_into(value); + } + _ => {} }; for d in &mut diagnostics { patch_empty(&mut d.message); if let Some(dri) = &mut d.related_information { for dri in dri { - patch_empty(&mut dri.message); + // The LSP does not (yet?) specify that related diagnostic messages can + // be in Markdown format (in addition to plain text). + if dri.message.is_empty() { + " ".clone_into(&mut dri.message); + } } } } diff --git a/crates/rust-analyzer/src/lsp/ext.rs b/crates/rust-analyzer/src/lsp/ext.rs index 3a1945c88170..8e0bb285c231 100644 --- a/crates/rust-analyzer/src/lsp/ext.rs +++ b/crates/rust-analyzer/src/lsp/ext.rs @@ -35,7 +35,7 @@ impl Request for InternalTestingFetchConfigRequest { type Params = InternalTestingFetchConfigParams; // Option is solely to circumvent Default bound. type Result = Option; - const METHOD: LspRequestMethod = + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer-internal/internalTestingFetchConfig"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -51,7 +51,7 @@ pub enum AnalyzerStatusRequest {} impl Request for AnalyzerStatusRequest { type Params = AnalyzerStatusParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/analyzerStatus"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/analyzerStatus"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -73,7 +73,7 @@ pub enum FetchDependencyListRequest {} impl Request for FetchDependencyListRequest { type Params = FetchDependencyListParams; type Result = FetchDependencyListResult; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/fetchDependencyList"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/fetchDependencyList"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -92,7 +92,7 @@ pub enum MemoryUsageRequest {} impl Request for MemoryUsageRequest { type Params = (); type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/memoryUsage"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/memoryUsage"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -101,7 +101,7 @@ pub enum ReloadWorkspaceRequest {} impl Request for ReloadWorkspaceRequest { type Params = (); type Result = (); - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/reloadWorkspace"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/reloadWorkspace"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -110,7 +110,7 @@ pub enum RebuildProcMacrosRequest {} impl Request for RebuildProcMacrosRequest { type Params = (); type Result = (); - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/rebuildProcMacros"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/rebuildProcMacros"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -119,7 +119,7 @@ pub enum ViewSyntaxTreeRequest {} impl Request for ViewSyntaxTreeRequest { type Params = ViewSyntaxTreeParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewSyntaxTree"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewSyntaxTree"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -134,7 +134,7 @@ pub enum ViewHirRequest {} impl Request for ViewHirRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewHir"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewHir"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -143,7 +143,7 @@ pub enum ViewMirRequest {} impl Request for ViewMirRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewMir"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewMir"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -152,7 +152,7 @@ pub enum InterpretFunctionRequest {} impl Request for InterpretFunctionRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/interpretFunction"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/interpretFunction"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -161,7 +161,7 @@ pub enum ViewFileTextRequest {} impl Request for ViewFileTextRequest { type Params = lsp_types::TextDocumentIdentifier; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewFileText"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewFileText"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -177,7 +177,7 @@ pub enum ViewCrateGraphRequest {} impl Request for ViewCrateGraphRequest { type Params = ViewCrateGraphParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewCrateGraph"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewCrateGraph"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -192,7 +192,7 @@ pub enum ViewItemTreeRequest {} impl Request for ViewItemTreeRequest { type Params = ViewItemTreeParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/viewItemTree"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewItemTree"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -236,7 +236,7 @@ pub enum DiscoverTestRequest {} impl Request for DiscoverTestRequest { type Params = DiscoverTestParams; type Result = DiscoverTestResults; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/discoverTest"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/discoverTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -244,7 +244,7 @@ pub enum DiscoveredTestsNotification {} impl Notification for DiscoveredTestsNotification { type Params = DiscoverTestResults; - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("experimental/discoveredTests"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -261,7 +261,7 @@ pub enum RunTestRequest {} impl Request for RunTestRequest { type Params = RunTestParams; type Result = (); - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/runTest"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/runTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -269,7 +269,7 @@ pub enum EndRunTestNotification {} impl Notification for EndRunTestNotification { type Params = (); - const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/endRunTest"); + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("experimental/endRunTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -277,7 +277,7 @@ pub enum AppendOutputToRunTestNotification {} impl Notification for AppendOutputToRunTestNotification { type Params = String; - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("experimental/appendOutputToRunTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -286,7 +286,8 @@ pub enum AbortRunTestNotification {} impl Notification for AbortRunTestNotification { type Params = (); - const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/abortRunTest"); + const METHOD: LspNotificationMethod<'_> = + LspNotificationMethod::new("experimental/abortRunTest"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -311,7 +312,7 @@ pub enum ChangeTestStateNotification {} impl Notification for ChangeTestStateNotification { type Params = ChangeTestStateParams; - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("experimental/changeTestState"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -321,7 +322,7 @@ pub enum ExpandMacroRequest {} impl Request for ExpandMacroRequest { type Params = ExpandMacroParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/expandMacro"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/expandMacro"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -344,7 +345,7 @@ pub enum ViewRecursiveMemoryLayoutRequest {} impl Request for ViewRecursiveMemoryLayoutRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option; - const METHOD: LspRequestMethod = + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/viewRecursiveMemoryLayout"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -372,7 +373,7 @@ pub enum CancelFlycheckNotification {} impl Notification for CancelFlycheckNotification { type Params = (); - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("rust-analyzer/cancelFlycheck"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -381,7 +382,8 @@ pub enum RunFlycheckNotification {} impl Notification for RunFlycheckNotification { type Params = RunFlycheckParams; - const METHOD: LspNotificationMethod = LspNotificationMethod::new("rust-analyzer/runFlycheck"); + const METHOD: LspNotificationMethod<'_> = + LspNotificationMethod::new("rust-analyzer/runFlycheck"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -389,7 +391,8 @@ pub enum ClearFlycheckNotification {} impl Notification for ClearFlycheckNotification { type Params = (); - const METHOD: LspNotificationMethod = LspNotificationMethod::new("rust-analyzer/clearFlycheck"); + const METHOD: LspNotificationMethod<'_> = + LspNotificationMethod::new("rust-analyzer/clearFlycheck"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -397,7 +400,7 @@ pub enum OpenServerLogsNotification {} impl Notification for OpenServerLogsNotification { type Params = (); - const METHOD: LspNotificationMethod = + const METHOD: LspNotificationMethod<'_> = LspNotificationMethod::new("rust-analyzer/openServerLogs"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -413,7 +416,7 @@ pub enum MatchingBraceRequest {} impl Request for MatchingBraceRequest { type Params = MatchingBraceParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/matchingBrace"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/matchingBrace"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -429,7 +432,7 @@ pub enum ParentModuleRequest {} impl Request for ParentModuleRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/parentModule"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/parentModule"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -438,7 +441,7 @@ pub enum ChildModulesRequest {} impl Request for ChildModulesRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/childModules"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/childModules"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -447,7 +450,7 @@ pub enum JoinLinesRequest {} impl Request for JoinLinesRequest { type Params = JoinLinesParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/joinLines"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/joinLines"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -463,7 +466,7 @@ pub enum OnEnterRequest {} impl Request for OnEnterRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Option>; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/onEnter"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/onEnter"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -472,7 +475,7 @@ pub enum RunnablesRequest {} impl Request for RunnablesRequest { type Params = RunnablesParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/runnables"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/runnables"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -531,7 +534,7 @@ pub enum RelatedTestsRequest {} impl Request for RelatedTestsRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/relatedTests"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/relatedTests"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -545,7 +548,7 @@ pub enum SsrRequest {} impl Request for SsrRequest { type Params = SsrParams; type Result = lsp_types::WorkspaceEdit; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/ssr"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/ssr"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -568,7 +571,8 @@ pub enum ServerStatusNotification {} impl Notification for ServerStatusNotification { type Params = ServerStatusParams; - const METHOD: LspNotificationMethod = LspNotificationMethod::new("experimental/serverStatus"); + const METHOD: LspNotificationMethod<'_> = + LspNotificationMethod::new("experimental/serverStatus"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -603,7 +607,7 @@ pub enum CodeActionRequest {} impl Request for CodeActionRequest { type Params = lsp_types::CodeActionParams; type Result = Option>; - const METHOD: LspRequestMethod = LspRequestMethod::new("textDocument/codeAction"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::TextDocumentCodeAction; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -612,7 +616,7 @@ pub enum CodeActionResolveRequest {} impl Request for CodeActionResolveRequest { type Params = CodeAction; type Result = CodeAction; - const METHOD: LspRequestMethod = LspRequestMethod::new("codeAction/resolve"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::CodeActionResolve; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -690,7 +694,7 @@ pub enum HoverRequest {} impl Request for HoverRequest { type Params = HoverParams; type Result = Option; - const METHOD: LspRequestMethod = lsp_types::HoverRequest::METHOD; + const METHOD: LspRequestMethod<'_> = lsp_types::HoverRequest::METHOD; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -740,7 +744,7 @@ pub enum ExternalDocsRequest {} impl Request for ExternalDocsRequest { type Params = lsp_types::TextDocumentPositionParams; type Result = ExternalDocsResponse; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/externalDocs"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/externalDocs"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -769,7 +773,7 @@ pub enum OpenCargoTomlRequest {} impl Request for OpenCargoTomlRequest { type Params = OpenCargoTomlParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/openCargoToml"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/openCargoToml"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -799,7 +803,7 @@ pub enum MoveItemRequest {} impl Request for MoveItemRequest { type Params = MoveItemParams; type Result = Vec; - const METHOD: LspRequestMethod = LspRequestMethod::new("experimental/moveItem"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("experimental/moveItem"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -823,7 +827,7 @@ pub enum WorkspaceSymbolRequest {} impl Request for WorkspaceSymbolRequest { type Params = WorkspaceSymbolParams; type Result = Option; - const METHOD: LspRequestMethod = LspRequestMethod::new("workspace/symbol"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::WorkspaceSymbol; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -868,7 +872,7 @@ pub enum DocumentOnTypeFormattingRequest {} impl Request for DocumentOnTypeFormattingRequest { type Params = DocumentOnTypeFormattingParams; type Result = Option>; - const METHOD: LspRequestMethod = LspRequestMethod::new("textDocument/onTypeFormatting"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::TextDocumentOnTypeFormatting; const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -938,7 +942,7 @@ pub enum PredicateEvaluationStatus { impl Request for EvaluatePredicateRequest { type Params = EvaluatePredicateParams; type Result = EvaluatePredicateResult; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/evaluatePredicate"); + const METHOD: LspRequestMethod<'_> = LspRequestMethod::new("rust-analyzer/evaluatePredicate"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } @@ -954,7 +958,8 @@ pub struct GetFailedObligationsParams { impl Request for GetFailedObligationsRequest { type Params = GetFailedObligationsParams; type Result = String; - const METHOD: LspRequestMethod = LspRequestMethod::new("rust-analyzer/getFailedObligations"); + const METHOD: LspRequestMethod<'_> = + LspRequestMethod::new("rust-analyzer/getFailedObligations"); const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer; } diff --git a/crates/rust-analyzer/src/lsp/semantic_tokens.rs b/crates/rust-analyzer/src/lsp/semantic_tokens.rs index 78198064238c..fcfe3fb27c29 100644 --- a/crates/rust-analyzer/src/lsp/semantic_tokens.rs +++ b/crates/rust-analyzer/src/lsp/semantic_tokens.rs @@ -344,10 +344,11 @@ pub(crate) fn diff_tokens( // The lsp data field is actually a byte-diff but we // travel in tokens so `start` and `delete_count` are in multiples of the // serialized size of `SemanticToken`. + let data = new.iter().copied().flat_map(<[u32; 5]>::from).collect(); vec![SemanticTokensEdit { start: 5 * offset as u32, delete_count: 5 * old.len() as u32, - data: Some(new.into()), + data: Some(data), }] } } @@ -378,11 +379,7 @@ mod tests { let edits = diff_tokens(&before, &after); assert_eq!( edits[0], - SemanticTokensEdit { - start: 10, - delete_count: 0, - data: Some(vec![from((11, 12, 13, 14, 15))]) - } + SemanticTokensEdit { start: 10, delete_count: 0, data: Some(vec![11, 12, 13, 14, 15]) } ); } @@ -394,11 +391,7 @@ mod tests { let edits = diff_tokens(&before, &after); assert_eq!( edits[0], - SemanticTokensEdit { - start: 0, - delete_count: 0, - data: Some(vec![from((11, 12, 13, 14, 15))]) - } + SemanticTokensEdit { start: 0, delete_count: 0, data: Some(vec![11, 12, 13, 14, 15]) } ); } @@ -418,7 +411,7 @@ mod tests { SemanticTokensEdit { start: 5, delete_count: 0, - data: Some(vec![from((10, 20, 30, 40, 50)), from((60, 70, 80, 90, 100))]) + data: Some(vec![10, 20, 30, 40, 50, 60, 70, 80, 90, 100]) } ); } diff --git a/crates/rust-analyzer/src/lsp/utils.rs b/crates/rust-analyzer/src/lsp/utils.rs index ebec0f990a17..00e94fb50c85 100644 --- a/crates/rust-analyzer/src/lsp/utils.rs +++ b/crates/rust-analyzer/src/lsp/utils.rs @@ -48,6 +48,7 @@ impl GlobalState { message, actions: Some(vec![lsp_types::MessageActionItem { title: "Open server logs".to_owned(), + properties: Default::default(), }]), }, |this, resp| { diff --git a/crates/rust-analyzer/tests/slow-tests/flycheck.rs b/crates/rust-analyzer/tests/slow-tests/flycheck.rs index c6f1f81139d2..7700643f03e7 100644 --- a/crates/rust-analyzer/tests/slow-tests/flycheck.rs +++ b/crates/rust-analyzer/tests/slow-tests/flycheck.rs @@ -2,6 +2,13 @@ use test_utils::skip_slow_tests; use crate::support::Project; +fn message_contains(message: &lsp_types::Message, p: &str) -> bool { + match message { + lsp_types::Message::String(s) => s.contains(p), + lsp_types::Message::MarkupContent(mc) => mc.value.contains(p), + } +} + #[test] fn test_flycheck_diagnostics_for_unused_variable() { if skip_slow_tests() { @@ -29,7 +36,7 @@ fn main() { let diagnostics = server.wait_for_diagnostics(); assert!( - diagnostics.diagnostics.iter().any(|d| d.message.contains("unused variable")), + diagnostics.diagnostics.iter().any(|d| message_contains(&d.message, "unused variable")), "expected unused variable diagnostic, got: {:?}", diagnostics.diagnostics, ); @@ -63,7 +70,7 @@ fn main() { // Wait for the unused variable diagnostic to appear. let diagnostics = server.wait_for_diagnostics(); assert!( - diagnostics.diagnostics.iter().any(|d| d.message.contains("unused variable")), + diagnostics.diagnostics.iter().any(|d| message_contains(&d.message, "unused variable")), "expected unused variable diagnostic, got: {:?}", diagnostics.diagnostics, ); @@ -105,7 +112,7 @@ fn main() {} let diagnostics = server.wait_for_diagnostics(); assert!( - diagnostics.diagnostics.iter().any(|d| d.message.contains("unused variable")), + diagnostics.diagnostics.iter().any(|d| message_contains(&d.message, "unused variable")), "expected unused variable diagnostic, got: {:?}", diagnostics.diagnostics, ); @@ -143,7 +150,7 @@ fn main() {} let diags = server.wait_for_diagnostics(); assert!( - diags.diagnostics.iter().any(|d| d.message.contains("unused variable")), + diags.diagnostics.iter().any(|d| message_contains(&d.message, "unused variable")), "expected unused variable diagnostic, got: {:?}", diags.diagnostics, ); diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index 95ff3aebd8db..16aa49e3578f 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -1373,7 +1373,6 @@ pub fn token(kind: SyntaxKind) -> SyntaxToken { tokens::SOURCE_FILE .tree() .syntax() - .clone_for_update() .descendants_with_tokens() .filter_map(|it| it.into_token()) .find(|it| it.kind() == kind) @@ -1394,43 +1393,10 @@ pub mod tokens { ) }); - pub fn semicolon() -> SyntaxToken { - SOURCE_FILE - .tree() - .syntax() - .clone_for_update() - .descendants_with_tokens() - .filter_map(|it| it.into_token()) - .find(|it| it.kind() == SEMICOLON) - .unwrap() - } - - pub fn single_space() -> SyntaxToken { - SOURCE_FILE - .tree() - .syntax() - .clone_for_update() - .descendants_with_tokens() - .filter_map(|it| it.into_token()) - .find(|it| it.kind() == WHITESPACE && it.text() == " ") - .unwrap() - } - - pub fn crate_kw() -> SyntaxToken { - SOURCE_FILE - .tree() - .syntax() - .clone_for_update() - .descendants_with_tokens() - .filter_map(|it| it.into_token()) - .find(|it| it.kind() == CRATE_KW) - .unwrap() - } - pub fn whitespace(text: &str) -> SyntaxToken { assert!(text.trim().is_empty()); let sf = SourceFile::parse(text, Edition::CURRENT).ok().unwrap(); - sf.syntax().clone_for_update().first_child_or_token().unwrap().into_token().unwrap() + sf.syntax().first_child_or_token().unwrap().into_token().unwrap() } pub fn doc_comment(text: &str) -> SyntaxToken { @@ -1454,41 +1420,6 @@ pub mod tokens { .find(|it| it.kind() == IDENT) .unwrap() } - - pub fn single_newline() -> SyntaxToken { - let res = SOURCE_FILE - .tree() - .syntax() - .clone_for_update() - .descendants_with_tokens() - .filter_map(|it| it.into_token()) - .find(|it| it.kind() == WHITESPACE && it.text() == "\n") - .unwrap(); - res.detach(); - res - } - - pub fn blank_line() -> SyntaxToken { - SOURCE_FILE - .tree() - .syntax() - .clone_for_update() - .descendants_with_tokens() - .filter_map(|it| it.into_token()) - .find(|it| it.kind() == WHITESPACE && it.text() == "\n\n") - .unwrap() - } - - pub struct WsBuilder(SourceFile); - - impl WsBuilder { - pub fn new(text: &str) -> WsBuilder { - WsBuilder(SourceFile::parse(text, Edition::CURRENT).ok().unwrap()) - } - pub fn ws(&self) -> SyntaxToken { - self.0.syntax().first_child_or_token().unwrap().into_token().unwrap() - } - } } #[cfg(test)] diff --git a/crates/syntax/src/fuzz.rs b/crates/syntax/src/fuzz.rs index 9b5cd0135e83..3c5640f08a52 100644 --- a/crates/syntax/src/fuzz.rs +++ b/crates/syntax/src/fuzz.rs @@ -42,7 +42,7 @@ impl CheckReparse { let delete = TextRange::at(delete_start.try_into().unwrap(), delete_len.try_into().unwrap()); let edited_text = - format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]); + format!("{}{}{}", &text[..delete_start], insert, &text[delete_start + delete_len..]); Some(CheckReparse { text, insert, delete, edited_text }) } diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 924e72ee4039..ab24ed923118 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -273,8 +273,11 @@ macro_rules! match_ast { $( $( $path:ident )::+ ($it:pat) => $res:expr, )* _ => $catch_all:expr $(,)? }) => {{ - $( if let Some($it) = $($path::)+cast($node.clone()) { $res } else )* - { $catch_all } + #[allow(clippy::question_mark, reason = "if `$catch_all` is `return None` Clippy can mark this")] + { + $( if let Some($it) = $($path::)+cast($node.clone()) { $res } else )* + { $catch_all } + } }}; } diff --git a/docs/book/src/contributing/lsp-extensions.md b/docs/book/src/contributing/lsp-extensions.md index 6902bce83e6c..da4a5aaa686c 100644 --- a/docs/book/src/contributing/lsp-extensions.md +++ b/docs/book/src/contributing/lsp-extensions.md @@ -1,5 +1,5 @@