1
Fork 0

Auto merge of #115387 - weihanglo:merge-check-and-lint, r=oli-obk

Make unknown/renamed/removed lints passed via command line respect lint levels
This commit is contained in:
bors 2023-09-11 08:56:29 +00:00
commit 5d62ab8981
25 changed files with 324 additions and 185 deletions

View file

@ -16,10 +16,6 @@
use self::TargetLint::*;
use crate::errors::{
CheckNameDeprecated, CheckNameRemoved, CheckNameRenamed, CheckNameUnknown,
CheckNameUnknownTool, RequestedLevel, UnsupportedGroup,
};
use crate::levels::LintLevelsBuilder;
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
@ -330,58 +326,6 @@ impl LintStore {
}
}
/// Checks the validity of lint names derived from the command line.
pub fn check_lint_name_cmdline(
&self,
sess: &Session,
lint_name: &str,
level: Level,
registered_tools: &RegisteredTools,
) {
let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
if lint_name_only == crate::WARNINGS.name_lower() && matches!(level, Level::ForceWarn(_)) {
sess.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() });
return;
}
match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
CheckLintNameResult::Renamed(replace) => {
sess.emit_warning(CheckNameRenamed {
lint_name,
replace: &replace,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::Removed(reason) => {
sess.emit_warning(CheckNameRemoved {
lint_name,
reason: &reason,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::NoLint(suggestion) => {
sess.emit_err(CheckNameUnknown {
lint_name,
suggestion,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::Tool(Err((Some(_), new_name))) => {
sess.emit_warning(CheckNameDeprecated {
lint_name,
new_name: &new_name,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::NoTool => {
sess.emit_err(CheckNameUnknownTool {
tool_name: tool_name.unwrap(),
sub: RequestedLevel { level, lint_name },
});
}
_ => {}
};
}
/// True if this symbol represents a lint group name.
pub fn is_lint_group(&self, lint_name: Symbol) -> bool {
debug!(
@ -1402,14 +1346,3 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LateContext<'tcx> {
err
}
}
pub fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) {
match lint_name.split_once("::") {
Some((tool_name, lint_name)) => {
let tool_name = Symbol::intern(tool_name);
(Some(tool_name), lint_name)
}
None => (None, lint_name),
}
}

View file

@ -1,7 +1,5 @@
use crate::fluent_generated as fluent;
use rustc_errors::{
AddToDiagnostic, Diagnostic, ErrorGuaranteed, Handler, IntoDiagnostic, SubdiagnosticMessage,
};
use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessage};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::lint::Level;
use rustc_span::{Span, Symbol};
@ -102,29 +100,6 @@ pub struct UnsupportedGroup {
pub lint_group: String,
}
pub struct CheckNameUnknown<'a> {
pub lint_name: &'a str,
pub suggestion: Option<Symbol>,
pub sub: RequestedLevel<'a>,
}
impl IntoDiagnostic<'_> for CheckNameUnknown<'_> {
fn into_diagnostic(
self,
handler: &Handler,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = handler.struct_err(fluent::lint_check_name_unknown);
diag.code(rustc_errors::error_code!(E0602));
if let Some(suggestion) = self.suggestion {
diag.help(fluent::lint_help);
diag.set_arg("suggestion", suggestion);
}
diag.set_arg("lint_name", self.lint_name);
diag.subdiagnostic(self.sub);
diag
}
}
#[derive(Diagnostic)]
#[diag(lint_check_name_unknown_tool, code = "E0602")]
pub struct CheckNameUnknownTool<'a> {
@ -132,30 +107,3 @@ pub struct CheckNameUnknownTool<'a> {
#[subdiagnostic]
pub sub: RequestedLevel<'a>,
}
#[derive(Diagnostic)]
#[diag(lint_check_name_renamed)]
pub struct CheckNameRenamed<'a> {
pub lint_name: &'a str,
pub replace: &'a str,
#[subdiagnostic]
pub sub: RequestedLevel<'a>,
}
#[derive(Diagnostic)]
#[diag(lint_check_name_removed)]
pub struct CheckNameRemoved<'a> {
pub lint_name: &'a str,
pub reason: &'a str,
#[subdiagnostic]
pub sub: RequestedLevel<'a>,
}
#[derive(Diagnostic)]
#[diag(lint_check_name_deprecated)]
pub struct CheckNameDeprecated<'a> {
pub lint_name: &'a str,
pub new_name: &'a str,
#[subdiagnostic]
pub sub: RequestedLevel<'a>,
}

View file

@ -1,3 +1,8 @@
use crate::errors::{CheckNameUnknownTool, RequestedLevel, UnsupportedGroup};
use crate::lints::{
DeprecatedLintNameFromCommandLine, RemovedLintFromCommandLine, RenamedLintFromCommandLine,
UnknownLintFromCommandLine,
};
use crate::{
builtin::MISSING_DOCS,
context::{CheckLintNameResult, LintStore},
@ -552,12 +557,55 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
fn add_command_line(&mut self) {
for &(ref lint_name, level) in &self.sess.opts.lint_opts {
self.store.check_lint_name_cmdline(self.sess, &lint_name, level, self.registered_tools);
// Checks the validity of lint names derived from the command line.
let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
if lint_name_only == crate::WARNINGS.name_lower()
&& matches!(level, Level::ForceWarn(_))
{
self.sess.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() });
}
match self.store.check_lint_name(lint_name_only, tool_name, self.registered_tools) {
CheckLintNameResult::Renamed(ref replace) => {
let name = lint_name.as_str();
let suggestion = RenamedLintSuggestion::WithoutSpan { replace };
let requested_level = RequestedLevel { level, lint_name };
let lint = RenamedLintFromCommandLine { name, suggestion, requested_level };
self.emit_lint(RENAMED_AND_REMOVED_LINTS, lint);
}
CheckLintNameResult::Removed(ref reason) => {
let name = lint_name.as_str();
let requested_level = RequestedLevel { level, lint_name };
let lint = RemovedLintFromCommandLine { name, reason, requested_level };
self.emit_lint(RENAMED_AND_REMOVED_LINTS, lint);
}
CheckLintNameResult::NoLint(suggestion) => {
let name = lint_name.clone();
let suggestion =
suggestion.map(|replace| UnknownLintSuggestion::WithoutSpan { replace });
let requested_level = RequestedLevel { level, lint_name };
let lint = UnknownLintFromCommandLine { name, suggestion, requested_level };
self.emit_lint(UNKNOWN_LINTS, lint);
}
CheckLintNameResult::Tool(Err((Some(_), ref replace))) => {
let name = lint_name.clone();
let requested_level = RequestedLevel { level, lint_name };
let lint = DeprecatedLintNameFromCommandLine { name, replace, requested_level };
self.emit_lint(RENAMED_AND_REMOVED_LINTS, lint);
}
CheckLintNameResult::NoTool => {
self.sess.emit_err(CheckNameUnknownTool {
tool_name: tool_name.unwrap(),
sub: RequestedLevel { level, lint_name },
});
}
_ => {}
};
let orig_level = level;
let lint_flag_val = Symbol::intern(lint_name);
let Ok(ids) = self.store.find_lints(&lint_name) else {
// errors handled in check_lint_name_cmdline above
// errors already handled above
continue;
};
for id in ids {
@ -915,24 +963,18 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
_ if !self.warn_about_weird_lints => {}
CheckLintNameResult::Renamed(new_name) => {
CheckLintNameResult::Renamed(ref replace) => {
let suggestion =
RenamedLintSuggestion { suggestion: sp, replace: new_name.as_str() };
RenamedLintSuggestion::WithSpan { suggestion: sp, replace };
let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
self.emit_spanned_lint(
RENAMED_AND_REMOVED_LINTS,
sp.into(),
RenamedLint { name: name.as_str(), suggestion },
);
let lint = RenamedLint { name: name.as_str(), suggestion };
self.emit_spanned_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
}
CheckLintNameResult::Removed(reason) => {
CheckLintNameResult::Removed(ref reason) => {
let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
self.emit_spanned_lint(
RENAMED_AND_REMOVED_LINTS,
sp.into(),
RemovedLint { name: name.as_str(), reason: reason.as_str() },
);
let lint = RemovedLint { name: name.as_str(), reason };
self.emit_spanned_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
}
CheckLintNameResult::NoLint(suggestion) => {
@ -941,13 +983,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
} else {
name.to_string()
};
let suggestion = suggestion
.map(|replace| UnknownLintSuggestion { suggestion: sp, replace });
self.emit_spanned_lint(
UNKNOWN_LINTS,
sp.into(),
UnknownLint { name, suggestion },
);
let suggestion = suggestion.map(|replace| {
UnknownLintSuggestion::WithSpan { suggestion: sp, replace }
});
let lint = UnknownLint { name, suggestion };
self.emit_spanned_lint(UNKNOWN_LINTS, sp.into(), lint);
}
}
// If this lint was renamed, apply the new lint instead of ignoring the attribute.
@ -1092,3 +1132,14 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { shallow_lint_levels_on, lint_expectations, ..*providers };
}
pub fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) {
match lint_name.split_once("::") {
Some((tool_name, lint_name)) => {
let tool_name = Symbol::intern(tool_name);
(Some(tool_name), lint_name)
}
None => (None, lint_name),
}
}

View file

@ -2,6 +2,7 @@
#![allow(rustc::diagnostic_outside_of_impl)]
use std::num::NonZeroU32;
use crate::errors::RequestedLevel;
use crate::fluent_generated as fluent;
use rustc_errors::{
AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, DiagnosticStyledString,
@ -1012,6 +1013,16 @@ pub struct DeprecatedLintName<'a> {
pub replace: &'a str,
}
#[derive(LintDiagnostic)]
#[diag(lint_deprecated_lint_name)]
#[help]
pub struct DeprecatedLintNameFromCommandLine<'a> {
pub name: String,
pub replace: &'a str,
#[subdiagnostic]
pub requested_level: RequestedLevel<'a>,
}
#[derive(LintDiagnostic)]
#[diag(lint_renamed_lint)]
pub struct RenamedLint<'a> {
@ -1021,11 +1032,25 @@ pub struct RenamedLint<'a> {
}
#[derive(Subdiagnostic)]
#[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")]
pub struct RenamedLintSuggestion<'a> {
#[primary_span]
pub suggestion: Span,
pub replace: &'a str,
pub enum RenamedLintSuggestion<'a> {
#[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")]
WithSpan {
#[primary_span]
suggestion: Span,
replace: &'a str,
},
#[help(lint_help)]
WithoutSpan { replace: &'a str },
}
#[derive(LintDiagnostic)]
#[diag(lint_renamed_lint)]
pub struct RenamedLintFromCommandLine<'a> {
pub name: &'a str,
#[subdiagnostic]
pub suggestion: RenamedLintSuggestion<'a>,
#[subdiagnostic]
pub requested_level: RequestedLevel<'a>,
}
#[derive(LintDiagnostic)]
@ -1035,6 +1060,15 @@ pub struct RemovedLint<'a> {
pub reason: &'a str,
}
#[derive(LintDiagnostic)]
#[diag(lint_removed_lint)]
pub struct RemovedLintFromCommandLine<'a> {
pub name: &'a str,
pub reason: &'a str,
#[subdiagnostic]
pub requested_level: RequestedLevel<'a>,
}
#[derive(LintDiagnostic)]
#[diag(lint_unknown_lint)]
pub struct UnknownLint {
@ -1044,11 +1078,25 @@ pub struct UnknownLint {
}
#[derive(Subdiagnostic)]
#[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
pub struct UnknownLintSuggestion {
#[primary_span]
pub suggestion: Span,
pub replace: Symbol,
pub enum UnknownLintSuggestion {
#[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
WithSpan {
#[primary_span]
suggestion: Span,
replace: Symbol,
},
#[help(lint_help)]
WithoutSpan { replace: Symbol },
}
#[derive(LintDiagnostic)]
#[diag(lint_unknown_lint, code = "E0602")]
pub struct UnknownLintFromCommandLine<'a> {
pub name: String,
#[subdiagnostic]
pub suggestion: Option<UnknownLintSuggestion>,
#[subdiagnostic]
pub requested_level: RequestedLevel<'a>,
}
#[derive(LintDiagnostic)]

View file

@ -1,4 +1,4 @@
use crate::context::parse_lint_and_tool_name;
use crate::levels::parse_lint_and_tool_name;
use rustc_span::{create_default_session_globals_then, Symbol};
#[test]