about summary refs log tree commit diff
path: root/compiler/rustc_lint/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_lint/src')
-rw-r--r--compiler/rustc_lint/src/hidden_unicode_codepoints.rs67
-rw-r--r--compiler/rustc_lint/src/lints.rs90
2 files changed, 107 insertions, 50 deletions
diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
index dc2f5c0e296..7c1af6bee1d 100644
--- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
+++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
@@ -1,7 +1,12 @@
-use crate::{EarlyContext, EarlyLintPass, LintContext};
+use crate::{
+    lints::{
+        HiddenUnicodeCodepointsDiag, HiddenUnicodeCodepointsDiagLabels,
+        HiddenUnicodeCodepointsDiagSub,
+    },
+    EarlyContext, EarlyLintPass, LintContext,
+};
 use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS};
 use rustc_ast as ast;
-use rustc_errors::{fluent, Applicability, SuggestionStyle};
 use rustc_span::{BytePos, Span, Symbol};
 
 declare_lint! {
@@ -60,55 +65,19 @@ impl HiddenUnicodeCodepoints {
             })
             .collect();
 
-        cx.struct_span_lint(
+        let count = spans.len();
+        let labels = point_at_inner_spans
+            .then_some(HiddenUnicodeCodepointsDiagLabels { spans: spans.clone() });
+        let sub = if point_at_inner_spans && !spans.is_empty() {
+            HiddenUnicodeCodepointsDiagSub::Escape { spans }
+        } else {
+            HiddenUnicodeCodepointsDiagSub::NoEscape { spans }
+        };
+
+        cx.emit_spanned_lint(
             TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
             span,
-            fluent::lint_hidden_unicode_codepoints,
-            |lint| {
-                lint.set_arg("label", label);
-                lint.set_arg("count", spans.len());
-                lint.span_label(span, fluent::label);
-                lint.note(fluent::note);
-                if point_at_inner_spans {
-                    for (c, span) in &spans {
-                        lint.span_label(*span, format!("{:?}", c));
-                    }
-                }
-                if point_at_inner_spans && !spans.is_empty() {
-                    lint.multipart_suggestion_with_style(
-                        fluent::suggestion_remove,
-                        spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
-                        Applicability::MachineApplicable,
-                        SuggestionStyle::HideCodeAlways,
-                    );
-                    lint.multipart_suggestion(
-                        fluent::suggestion_escape,
-                        spans
-                            .into_iter()
-                            .map(|(c, span)| {
-                                let c = format!("{:?}", c);
-                                (span, c[1..c.len() - 1].to_string())
-                            })
-                            .collect(),
-                        Applicability::MachineApplicable,
-                    );
-                } else {
-                    // FIXME: in other suggestions we've reversed the inner spans of doc comments. We
-                    // should do the same here to provide the same good suggestions as we do for
-                    // literals above.
-                    lint.set_arg(
-                        "escaped",
-                        spans
-                            .into_iter()
-                            .map(|(c, _)| format!("{:?}", c))
-                            .collect::<Vec<String>>()
-                            .join(", "),
-                    );
-                    lint.note(fluent::suggestion_remove);
-                    lint.note(fluent::no_suggestion_note_escape);
-                }
-                lint
-            },
+            HiddenUnicodeCodepointsDiag { label, count, span_label: span, labels, sub },
         );
     }
 }
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index faeb396ce8c..4da099dcc1d 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1,6 +1,8 @@
 use std::num::NonZeroU32;
 
-use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage};
+use rustc_errors::{
+    fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, SuggestionStyle,
+};
 use rustc_hir::def_id::DefId;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{Predicate, Ty, TyCtxt};
@@ -363,6 +365,92 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> {
     pub end_span: Span,
 }
 
+// hidden_unicode_codepoints.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_hidden_unicode_codepoints)]
+#[note]
+pub struct HiddenUnicodeCodepointsDiag<'a> {
+    pub label: &'a str,
+    pub count: usize,
+    #[label]
+    pub span_label: Span,
+    #[subdiagnostic]
+    pub labels: Option<HiddenUnicodeCodepointsDiagLabels>,
+    #[subdiagnostic]
+    pub sub: HiddenUnicodeCodepointsDiagSub,
+}
+
+pub struct HiddenUnicodeCodepointsDiagLabels {
+    pub spans: Vec<(char, Span)>,
+}
+
+impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels {
+    fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
+    where
+        F: Fn(
+            &mut rustc_errors::Diagnostic,
+            rustc_errors::SubdiagnosticMessage,
+        ) -> rustc_errors::SubdiagnosticMessage,
+    {
+        for (c, span) in self.spans {
+            diag.span_label(span, format!("{:?}", c));
+        }
+    }
+}
+
+pub enum HiddenUnicodeCodepointsDiagSub {
+    Escape { spans: Vec<(char, Span)> },
+    NoEscape { spans: Vec<(char, Span)> },
+}
+
+// Used because of multiple multipart_suggestion and note
+impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
+    fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
+    where
+        F: Fn(
+            &mut rustc_errors::Diagnostic,
+            rustc_errors::SubdiagnosticMessage,
+        ) -> rustc_errors::SubdiagnosticMessage,
+    {
+        match self {
+            HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
+                diag.multipart_suggestion_with_style(
+                    fluent::suggestion_remove,
+                    spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
+                    Applicability::MachineApplicable,
+                    SuggestionStyle::HideCodeAlways,
+                );
+                diag.multipart_suggestion(
+                    fluent::suggestion_escape,
+                    spans
+                        .into_iter()
+                        .map(|(c, span)| {
+                            let c = format!("{:?}", c);
+                            (span, c[1..c.len() - 1].to_string())
+                        })
+                        .collect(),
+                    Applicability::MachineApplicable,
+                );
+            }
+            HiddenUnicodeCodepointsDiagSub::NoEscape { spans } => {
+                // FIXME: in other suggestions we've reversed the inner spans of doc comments. We
+                // should do the same here to provide the same good suggestions as we do for
+                // literals above.
+                diag.set_arg(
+                    "escaped",
+                    spans
+                        .into_iter()
+                        .map(|(c, _)| format!("{:?}", c))
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                );
+                diag.note(fluent::suggestion_remove);
+                diag.note(fluent::no_suggestion_note_escape);
+            }
+        }
+    }
+}
+
 // internal.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_default_hash_types)]