Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/diagnostics.rs9
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_fields.rs29
-rw-r--r--crates/ide-diagnostics/src/lib.rs6
3 files changed, 38 insertions, 6 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 7f672a697c..555270bad8 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -282,7 +282,7 @@ pub struct MissingFields {
pub file: HirFileId,
pub field_list_parent: AstPtr<Either<ast::RecordExpr, ast::RecordPat>>,
pub field_list_parent_path: Option<AstPtr<ast::Path>>,
- pub missed_fields: Vec<Name>,
+ pub missed_fields: Vec<(Name, Field)>,
}
#[derive(Debug)]
@@ -476,7 +476,12 @@ impl<'db> AnyDiagnostic<'db> {
let variant_data = variant.fields(db);
let missed_fields = missed_fields
.into_iter()
- .map(|idx| variant_data.fields()[idx].name.clone())
+ .map(|idx| {
+ (
+ variant_data.fields()[idx].name.clone(),
+ Field { parent: variant.into(), id: idx },
+ )
+ })
.collect();
let record = match record {
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index efbd266714..85368cc09f 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -1,6 +1,6 @@
use either::Either;
use hir::{
- AssocItem, FindPathConfig, HirDisplay, InFile, Type,
+ AssocItem, FindPathConfig, HasVisibility, HirDisplay, InFile, Type,
db::{ExpandDatabase, HirDatabase},
sym,
};
@@ -35,7 +35,7 @@ use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix};
// ```
pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Diagnostic {
let mut message = String::from("missing structure fields:\n");
- for field in &d.missed_fields {
+ for (field, _) in &d.missed_fields {
format_to!(message, "- {}\n", field.display(ctx.sema.db, ctx.edition));
}
@@ -57,7 +57,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
// `struct A(usize);`
// `let a = A { 0: () }`
// but it is uncommon usage and it should not be encouraged.
- if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
+ if d.missed_fields.iter().any(|(name, _)| name.as_tuple_index().is_some()) {
return None;
}
@@ -68,6 +68,12 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
let range = InFile::new(d.file, d.field_list_parent.text_range())
.original_node_file_range_rooted_opt(ctx.sema.db)?;
+ if let Some(current_module) = current_module
+ && d.missed_fields.iter().any(|(_, field)| !field.is_visible_from(ctx.db(), current_module))
+ {
+ return None;
+ }
+
let build_text_edit = |new_syntax: &SyntaxNode, old_syntax| {
let edit = {
let old_range = ctx.sema.original_range_opt(old_syntax)?;
@@ -254,7 +260,7 @@ fn get_default_constructor(
#[cfg(test)]
mod tests {
- use crate::tests::{check_diagnostics, check_fix};
+ use crate::tests::{check_diagnostics, check_fix, check_no_fix};
#[test]
fn missing_record_pat_field_diagnostic() {
@@ -960,4 +966,19 @@ fn f() -> A {
"#,
);
}
+
+ #[test]
+ fn inaccessible_fields() {
+ check_no_fix(
+ r#"
+mod foo {
+ pub struct Bar { baz: i32 }
+}
+
+fn qux() {
+ foo::Bar {$0};
+}
+ "#,
+ );
+ }
}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 519639db00..09c9f8eab0 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -285,6 +285,12 @@ struct DiagnosticsContext<'a> {
is_nightly: bool,
}
+impl<'a> DiagnosticsContext<'a> {
+ fn db(&self) -> &'a RootDatabase {
+ self.sema.db
+ }
+}
+
/// Request parser level diagnostics for the given [`FileId`].
pub fn syntax_diagnostics(
db: &RootDatabase,