From 883f5e5e657e714650d34cfb271abd8015210d08 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Fri, 24 Nov 2017 10:26:42 -0800 Subject: [PATCH] one-time diagnostics: span_suggestion, generalize methods for non-lints 304c8b1edabcd made the Session's one-time-diagnostics set take a special-purpose `DiagnosticMessageId` enum rather than a LintID so that it could support more than just lints, but the `diag_span_note_once` and `diag_note_once` methods continued to take references to lints: for API consistency, we now make these methods take a `DiagnosticMessageId` while we add support for one-time span-suggestions. --- src/librustc/lint/mod.rs | 13 ++++++------ src/librustc/session/mod.rs | 40 +++++++++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 906cae53710f..f0761ce61786 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -37,7 +37,7 @@ use errors::{DiagnosticBuilder, DiagnosticId}; use hir::def_id::{CrateNum, LOCAL_CRATE}; use hir::intravisit::{self, FnKind}; use hir; -use session::Session; +use session::{Session, DiagnosticMessageId}; use std::hash; use syntax::ast; use syntax::codemap::MultiSpan; @@ -423,7 +423,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session, LintSource::Default => { sess.diag_note_once( &mut err, - lint, + DiagnosticMessageId::from(lint), &format!("#[{}({})] on by default", level.as_str(), name)); } LintSource::CommandLine(lint_flag_val) => { @@ -437,24 +437,25 @@ pub fn struct_lint_level<'a>(sess: &'a Session, if lint_flag_val.as_str() == name { sess.diag_note_once( &mut err, - lint, + DiagnosticMessageId::from(lint), &format!("requested on the command line with `{} {}`", flag, hyphen_case_lint_name)); } else { let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); sess.diag_note_once( &mut err, - lint, + DiagnosticMessageId::from(lint), &format!("`{} {}` implied by `{} {}`", flag, hyphen_case_lint_name, flag, hyphen_case_flag_val)); } } LintSource::Node(lint_attr_name, src) => { - sess.diag_span_note_once(&mut err, lint, src, "lint level defined here"); + sess.diag_span_note_once(&mut err, DiagnosticMessageId::from(lint), + src, "lint level defined here"); if lint_attr_name.as_str() != name { let level_str = level.as_str(); - sess.diag_note_once(&mut err, lint, + sess.diag_note_once(&mut err, DiagnosticMessageId::from(lint), &format!("#[{}({})] implied by #[{}({})]", level_str, name, level_str, lint_attr_name)); } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index df5805bacd41..36c1966bdc83 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -161,6 +161,7 @@ pub struct PerfStats { enum DiagnosticBuilderMethod { Note, SpanNote, + SpanSuggestion(String), // suggestion // add more variants as needed to support one-time diagnostics } @@ -173,6 +174,12 @@ pub enum DiagnosticMessageId { StabilityId(u32) // issue number } +impl From<&'static lint::Lint> for DiagnosticMessageId { + fn from(lint: &'static lint::Lint) -> Self { + DiagnosticMessageId::LintId(lint::LintId::of(lint)) + } +} + impl Session { pub fn local_crate_disambiguator(&self) -> CrateDisambiguator { match *self.crate_disambiguator.borrow() { @@ -358,10 +365,11 @@ impl Session { fn diag_once<'a, 'b>(&'a self, diag_builder: &'b mut DiagnosticBuilder<'a>, method: DiagnosticBuilderMethod, - lint: &'static lint::Lint, message: &str, span: Option) { + msg_id: DiagnosticMessageId, + message: &str, + span_maybe: Option) { - let lint_id = DiagnosticMessageId::LintId(lint::LintId::of(lint)); - let id_span_message = (lint_id, span, message.to_owned()); + let id_span_message = (msg_id, span_maybe, message.to_owned()); let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message); if fresh { match method { @@ -369,7 +377,12 @@ impl Session { diag_builder.note(message); }, DiagnosticBuilderMethod::SpanNote => { - diag_builder.span_note(span.expect("span_note expects a span"), message); + let span = span_maybe.expect("span_note needs a span"); + diag_builder.span_note(span, message); + }, + DiagnosticBuilderMethod::SpanSuggestion(suggestion) => { + let span = span_maybe.expect("span_suggestion needs a span"); + diag_builder.span_suggestion(span, message, suggestion); } } } @@ -377,14 +390,25 @@ impl Session { pub fn diag_span_note_once<'a, 'b>(&'a self, diag_builder: &'b mut DiagnosticBuilder<'a>, - lint: &'static lint::Lint, span: Span, message: &str) { - self.diag_once(diag_builder, DiagnosticBuilderMethod::SpanNote, lint, message, Some(span)); + msg_id: DiagnosticMessageId, span: Span, message: &str) { + self.diag_once(diag_builder, DiagnosticBuilderMethod::SpanNote, + msg_id, message, Some(span)); } pub fn diag_note_once<'a, 'b>(&'a self, diag_builder: &'b mut DiagnosticBuilder<'a>, - lint: &'static lint::Lint, message: &str) { - self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, lint, message, None); + msg_id: DiagnosticMessageId, message: &str) { + self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, msg_id, message, None); + } + + pub fn diag_span_suggestion_once<'a, 'b>(&'a self, + diag_builder: &'b mut DiagnosticBuilder<'a>, + msg_id: DiagnosticMessageId, + span: Span, + message: &str, + suggestion: String) { + self.diag_once(diag_builder, DiagnosticBuilderMethod::SpanSuggestion(suggestion), + msg_id, message, Some(span)); } pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {