mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
integrate parsed lint attrs into clippy
This commit is contained in:
committed by
Jonathan Brouwer
parent
345a3eb08b
commit
d884f92b04
@@ -578,6 +578,8 @@ fn opt_span_lint<S: Into<MultiSpan>>(
|
||||
}
|
||||
}
|
||||
|
||||
/// Only appropriate for use inside of the compiler
|
||||
/// since the compiler doesn't track levels of tool lints
|
||||
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
|
||||
self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs)
|
||||
}
|
||||
|
||||
@@ -583,7 +583,7 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if matches!(name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
|
||||
allow_attributes_without_reason::check(cx, name, items, attr);
|
||||
}
|
||||
if is_lint_level(name, attr.id) {
|
||||
if is_lint_level(name) {
|
||||
blanket_clippy_restriction_lints::check(cx, name, items);
|
||||
}
|
||||
if items.is_empty() || !attr.has_name(sym::deprecated) {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use crate::attrs::is_lint_level;
|
||||
|
||||
use super::{Attribute, UNNECESSARY_CLIPPY_CFG};
|
||||
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use itertools::Itertools;
|
||||
use rustc_ast::AttrStyle;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, Level};
|
||||
use rustc_lint::{EarlyContext};
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(
|
||||
@@ -13,9 +15,10 @@ pub(super) fn check(
|
||||
behind_cfg_attr: &rustc_ast::MetaItem,
|
||||
attr: &Attribute,
|
||||
) {
|
||||
// FIXME use proper attr parsing here
|
||||
if cfg_attr.has_name(sym::clippy)
|
||||
&& let Some(ident) = behind_cfg_attr.ident()
|
||||
&& Level::from_symbol(ident.name, || Some(attr.id)).is_some()
|
||||
&& is_lint_level(ident.name)
|
||||
&& let Some(items) = behind_cfg_attr.meta_item_list()
|
||||
{
|
||||
let nb_items = items.len();
|
||||
|
||||
@@ -15,7 +15,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
|
||||
return;
|
||||
}
|
||||
if let Some(lint_list) = &attr.meta_item_list()
|
||||
&& attr.name().is_some_and(|name| is_lint_level(name, attr.id))
|
||||
&& attr.name().is_some_and(is_lint_level)
|
||||
{
|
||||
for lint in lint_list {
|
||||
match item.kind {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use clippy_utils::macros::{is_panic, macro_backtrace};
|
||||
use rustc_ast::{AttrId, MetaItemInner};
|
||||
use rustc_ast::{MetaItemInner};
|
||||
use rustc_hir::{
|
||||
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
|
||||
};
|
||||
@@ -16,8 +16,8 @@ pub(super) fn is_word(nmi: &MetaItemInner, expected: Symbol) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool {
|
||||
Level::from_symbol(symbol, || Some(attr_id)).is_some()
|
||||
pub(super) fn is_lint_level(symbol: Symbol) -> bool {
|
||||
Level::from_symbol(symbol).is_some()
|
||||
}
|
||||
|
||||
pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
use clippy_utils::msrvs::Msrv;
|
||||
use clippy_utils::source::{HasSession, IntoSpan as _, SpanRangeExt, snippet, snippet_block_with_applicability};
|
||||
use clippy_utils::{can_use_if_let_chains, span_contains_non_whitespace, sym, tokenize_with_text};
|
||||
use rustc_ast::{BinOpKind, MetaItemInner};
|
||||
use rustc_ast::BinOpKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Block, Expr, ExprKind, StmtKind};
|
||||
use rustc_hir::attrs::{AttributeKind, LintAttributeKind};
|
||||
use rustc_hir::{Attribute, Block, Expr, ExprKind, StmtKind};
|
||||
use rustc_lexer::TokenKind;
|
||||
use rustc_lint::{LateContext, LateLintPass, Level};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
|
||||
@@ -237,19 +238,26 @@ fn check_significant_tokens_and_expect_attrs(
|
||||
!span_contains_non_whitespace(cx, span, self.lint_commented_code)
|
||||
},
|
||||
|
||||
[attr]
|
||||
if matches!(Level::from_attr(attr), Some((Level::Expect, _)))
|
||||
&& let Some(metas) = attr.meta_item_list()
|
||||
&& let Some(MetaItemInner::MetaItem(meta_item)) = metas.first()
|
||||
&& let [tool, lint_name] = meta_item.path.segments.as_slice()
|
||||
&& tool.ident.name == sym::clippy
|
||||
&& [expected_lint_name, sym::style, sym::all].contains(&lint_name.ident.name) =>
|
||||
{
|
||||
// There is an `expect` attribute -- check that there is no _other_ significant text
|
||||
let span_before_attr = inner_if.span.split_at(1).1.until(attr.span());
|
||||
let span_after_attr = attr.span().between(inner_if_expr.span);
|
||||
!span_contains_non_whitespace(cx, span_before_attr, self.lint_commented_code)
|
||||
&& !span_contains_non_whitespace(cx, span_after_attr, self.lint_commented_code)
|
||||
[
|
||||
Attribute::Parsed(AttributeKind::LintAttributes(sub_attrs)),
|
||||
] => {
|
||||
sub_attrs
|
||||
.into_iter()
|
||||
.filter(|attr|attr.kind == LintAttributeKind::Expect)
|
||||
.flat_map(|attr| attr.lint_instances.iter().map(|group| (attr.attr_span, group)))
|
||||
.filter(|(_, lint_id)| {
|
||||
lint_id.tool_is_named(sym::clippy)
|
||||
&& (expected_lint_name == lint_id.lint_name()
|
||||
|| [expected_lint_name, sym::style, sym::all]
|
||||
.contains(&lint_id.original_name_without_tool()))
|
||||
})
|
||||
.any(|(attr_span, _)| {
|
||||
// There is an `expect` attribute -- check that there is no _other_ significant text
|
||||
let span_before_attr = inner_if.span.split_at(1).1.until(attr_span);
|
||||
let span_after_attr = attr_span.between(inner_if_expr.span);
|
||||
!span_contains_non_whitespace(cx, span_before_attr, self.lint_commented_code)
|
||||
&& !span_contains_non_whitespace(cx, span_after_attr, self.lint_commented_code)
|
||||
})
|
||||
},
|
||||
|
||||
// There are other attributes, which are significant tokens -- check failed
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
binary_expr_needs_parentheses, is_from_proc_macro, leaks_droppable_temporary_with_limited_lifetime,
|
||||
span_contains_cfg, span_find_starting_semi, sym,
|
||||
};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::attrs::{AttributeKind, LintAttributeKind};
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{Body, Expr, ExprKind, HirId, LangItem, MatchSource, StmtKind};
|
||||
use rustc_lint::{LateContext, Level, LintContext};
|
||||
use rustc_hir::{Attribute, Body, Expr, ExprKind, HirId, LangItem, MatchSource, StmtKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{BytePos, Pos, Span};
|
||||
use std::borrow::Cow;
|
||||
@@ -180,20 +180,18 @@ fn check_final_expr<'tcx>(
|
||||
// actually fulfill the expectation (clippy::#12998)
|
||||
match cx.tcx.hir_attrs(expr.hir_id) {
|
||||
[] => {},
|
||||
[attr] => {
|
||||
if matches!(Level::from_attr(attr), Some((Level::Expect, _)))
|
||||
&& let metas = attr.meta_item_list()
|
||||
&& let Some(lst) = metas
|
||||
&& let [MetaItemInner::MetaItem(meta_item), ..] = lst.as_slice()
|
||||
&& let [tool, lint_name] = meta_item.path.segments.as_slice()
|
||||
&& tool.ident.name == sym::clippy
|
||||
&& matches!(
|
||||
lint_name.ident.name,
|
||||
sym::needless_return | sym::style | sym::all | sym::warnings
|
||||
)
|
||||
[Attribute::Parsed(AttributeKind::LintAttributes(sub_attrs))] => {
|
||||
if !sub_attrs
|
||||
.into_iter()
|
||||
.filter(|attr| attr.kind == LintAttributeKind::Expect)
|
||||
.flat_map(|attr| &attr.lint_instances)
|
||||
.any(|lint| {
|
||||
matches!(
|
||||
lint.original_name_without_tool(),
|
||||
sym::needless_return | sym::style | sym::all | sym::warnings
|
||||
)
|
||||
})
|
||||
{
|
||||
// This is an expectation of the `needless_return` lint
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user