mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
internal: refactor incorrect case diagnostics
This commit is contained in:
parent
2ad7892462
commit
fc30c5ccbe
@ -34,6 +34,7 @@ macro_rules! diagnostics {
|
||||
diagnostics![
|
||||
BreakOutsideOfLoop,
|
||||
InactiveCode,
|
||||
IncorrectCase,
|
||||
MacroError,
|
||||
MismatchedArgCount,
|
||||
MissingFields,
|
||||
@ -195,31 +196,3 @@ impl Diagnostic for InternalBailedOut {
|
||||
}
|
||||
|
||||
pub use hir_ty::diagnostics::IncorrectCase;
|
||||
|
||||
impl Diagnostic for IncorrectCase {
|
||||
fn code(&self) -> DiagnosticCode {
|
||||
DiagnosticCode("incorrect-ident-case")
|
||||
}
|
||||
|
||||
fn message(&self) -> String {
|
||||
format!(
|
||||
"{} `{}` should have {} name, e.g. `{}`",
|
||||
self.ident_type,
|
||||
self.ident_text,
|
||||
self.expected_case.to_string(),
|
||||
self.suggested_text
|
||||
)
|
||||
}
|
||||
|
||||
fn display_source(&self) -> InFile<SyntaxNodePtr> {
|
||||
InFile::new(self.file, self.ident.clone().into())
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &(dyn Any + Send + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn is_experimental(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ use crate::{
|
||||
pub use crate::{
|
||||
attrs::{HasAttrs, Namespace},
|
||||
diagnostics::{
|
||||
AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, InternalBailedOut, MacroError,
|
||||
MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr,
|
||||
AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, InternalBailedOut,
|
||||
MacroError, MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr,
|
||||
MissingUnsafe, NoSuchField, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap,
|
||||
UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
|
||||
UnresolvedModule, UnresolvedProcMacro,
|
||||
@ -340,7 +340,7 @@ impl ModuleDef {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
|
||||
pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> {
|
||||
let id = match self {
|
||||
ModuleDef::Adt(it) => match it {
|
||||
Adt::Struct(it) => it.id.into(),
|
||||
@ -353,17 +353,19 @@ impl ModuleDef {
|
||||
ModuleDef::Module(it) => it.id.into(),
|
||||
ModuleDef::Const(it) => it.id.into(),
|
||||
ModuleDef::Static(it) => it.id.into(),
|
||||
_ => return,
|
||||
_ => return Vec::new(),
|
||||
};
|
||||
|
||||
let module = match self.module(db) {
|
||||
Some(it) => it,
|
||||
None => return,
|
||||
None => return Vec::new(),
|
||||
};
|
||||
|
||||
let mut acc = Vec::new();
|
||||
for diag in hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id) {
|
||||
sink.push(diag)
|
||||
acc.push(diag.into())
|
||||
}
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
@ -624,7 +626,7 @@ impl Module {
|
||||
acc.extend(m.diagnostics(db, sink, internal_diagnostics))
|
||||
}
|
||||
}
|
||||
_ => decl.diagnostics(db, sink),
|
||||
_ => acc.extend(decl.diagnostics(db)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1234,7 +1236,7 @@ impl Function {
|
||||
}
|
||||
|
||||
for diag in hir_ty::diagnostics::validate_module_item(db, krate, self.id.into()) {
|
||||
sink.push(diag)
|
||||
acc.push(diag.into())
|
||||
}
|
||||
acc
|
||||
}
|
||||
|
@ -84,9 +84,6 @@ impl fmt::Display for IdentType {
|
||||
}
|
||||
}
|
||||
|
||||
// Diagnostic: incorrect-ident-case
|
||||
//
|
||||
// This diagnostic is triggered if an item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention].
|
||||
#[derive(Debug)]
|
||||
pub struct IncorrectCase {
|
||||
pub file: HirFileId,
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
mod break_outside_of_loop;
|
||||
mod inactive_code;
|
||||
mod incorrect_case;
|
||||
mod macro_error;
|
||||
mod mismatched_arg_count;
|
||||
mod missing_fields;
|
||||
@ -135,7 +136,6 @@ pub struct DiagnosticsConfig {
|
||||
struct DiagnosticsContext<'a> {
|
||||
config: &'a DiagnosticsConfig,
|
||||
sema: Semantics<'a, RootDatabase>,
|
||||
#[allow(unused)]
|
||||
resolve: &'a AssistResolveStrategy,
|
||||
}
|
||||
|
||||
@ -165,9 +165,6 @@ pub(crate) fn diagnostics(
|
||||
}
|
||||
let res = RefCell::new(res);
|
||||
let sink_builder = DiagnosticSinkBuilder::new()
|
||||
.on::<hir::diagnostics::IncorrectCase, _>(|d| {
|
||||
res.borrow_mut().push(warning_with_fix(d, &sema, resolve));
|
||||
})
|
||||
.on::<UnlinkedFile, _>(|d| {
|
||||
// Limit diagnostic to the first few characters in the file. This matches how VS Code
|
||||
// renders it with the full span, but on other editors, and is less invasive.
|
||||
@ -216,6 +213,7 @@ pub(crate) fn diagnostics(
|
||||
#[rustfmt::skip]
|
||||
let d = match diag {
|
||||
AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d),
|
||||
AnyDiagnostic::IncorrectCase(d) => incorrect_case::incorrect_case(&ctx, &d),
|
||||
AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d),
|
||||
AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d),
|
||||
AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d),
|
||||
@ -250,16 +248,6 @@ pub(crate) fn diagnostics(
|
||||
res
|
||||
}
|
||||
|
||||
fn warning_with_fix<D: DiagnosticWithFixes>(
|
||||
d: &D,
|
||||
sema: &Semantics<RootDatabase>,
|
||||
resolve: &AssistResolveStrategy,
|
||||
) -> Diagnostic {
|
||||
Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message())
|
||||
.with_fixes(d.fixes(sema, resolve))
|
||||
.with_code(Some(d.code()))
|
||||
}
|
||||
|
||||
fn check_unnecessary_braces_in_use_statement(
|
||||
acc: &mut Vec<Diagnostic>,
|
||||
file_id: FileId,
|
||||
|
@ -1,6 +1,5 @@
|
||||
//! Provides a way to attach fixes to the diagnostics.
|
||||
//! The same module also has all curret custom fixes for the diagnostics implemented.
|
||||
mod change_case;
|
||||
|
||||
use hir::{diagnostics::Diagnostic, Semantics};
|
||||
use ide_assists::AssistResolveStrategy;
|
||||
|
@ -1,35 +1,46 @@
|
||||
use hir::{db::AstDatabase, diagnostics::IncorrectCase, InFile, Semantics};
|
||||
use ide_assists::{Assist, AssistResolveStrategy};
|
||||
use ide_db::{base_db::FilePosition, RootDatabase};
|
||||
use hir::{db::AstDatabase, InFile};
|
||||
use ide_assists::Assist;
|
||||
use ide_db::base_db::FilePosition;
|
||||
use syntax::AstNode;
|
||||
|
||||
use crate::{
|
||||
diagnostics::{unresolved_fix, DiagnosticWithFixes},
|
||||
diagnostics::{unresolved_fix, Diagnostic, DiagnosticsContext},
|
||||
references::rename::rename_with_semantics,
|
||||
Severity,
|
||||
};
|
||||
|
||||
impl DiagnosticWithFixes for IncorrectCase {
|
||||
fn fixes(
|
||||
&self,
|
||||
sema: &Semantics<RootDatabase>,
|
||||
resolve: &AssistResolveStrategy,
|
||||
) -> Option<Vec<Assist>> {
|
||||
let root = sema.db.parse_or_expand(self.file)?;
|
||||
let name_node = self.ident.to_node(&root);
|
||||
// Diagnostic: incorrect-ident-case
|
||||
//
|
||||
// This diagnostic is triggered if an item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention].
|
||||
pub(super) fn incorrect_case(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
"incorrect-ident-case",
|
||||
format!(
|
||||
"{} `{}` should have {} name, e.g. `{}`",
|
||||
d.ident_type, d.ident_text, d.expected_case, d.suggested_text
|
||||
),
|
||||
ctx.sema.diagnostics_display_range(InFile::new(d.file, d.ident.clone().into())).range,
|
||||
)
|
||||
.severity(Severity::WeakWarning)
|
||||
.with_fixes(fixes(ctx, d))
|
||||
}
|
||||
|
||||
let name_node = InFile::new(self.file, name_node.syntax());
|
||||
let frange = name_node.original_file_range(sema.db);
|
||||
let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
|
||||
fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Option<Vec<Assist>> {
|
||||
let root = ctx.sema.db.parse_or_expand(d.file)?;
|
||||
let name_node = d.ident.to_node(&root);
|
||||
|
||||
let label = format!("Rename to {}", self.suggested_text);
|
||||
let mut res = unresolved_fix("change_case", &label, frange.range);
|
||||
if resolve.should_resolve(&res.id) {
|
||||
let source_change = rename_with_semantics(sema, file_position, &self.suggested_text);
|
||||
res.source_change = Some(source_change.ok().unwrap_or_default());
|
||||
}
|
||||
let name_node = InFile::new(d.file, name_node.syntax());
|
||||
let frange = name_node.original_file_range(ctx.sema.db);
|
||||
let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
|
||||
|
||||
Some(vec![res])
|
||||
let label = format!("Rename to {}", d.suggested_text);
|
||||
let mut res = unresolved_fix("change_case", &label, frange.range);
|
||||
if ctx.resolve.should_resolve(&res.id) {
|
||||
let source_change = rename_with_semantics(&ctx.sema, file_position, &d.suggested_text);
|
||||
res.source_change = Some(source_change.ok().unwrap_or_default());
|
||||
}
|
||||
|
||||
Some(vec![res])
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
Loading…
Reference in New Issue
Block a user