Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ homepage = "https://github.com/rust-lang/cargo"
repository = "https://github.com/rust-lang/cargo"

[workspace.dependencies]
annotate-snippets = "0.11.5"
annotate-snippets = { version = "0.12.1", features = ["simd"] }
anstream = "0.6.20"
anstyle = "1.0.11"
anyhow = "1.0.98"
Expand Down
8 changes: 4 additions & 4 deletions src/cargo/core/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt;
use std::io::IsTerminal;
use std::io::prelude::*;

use annotate_snippets::{Message, Renderer};
use annotate_snippets::{Renderer, Report};
use anstream::AutoStream;
use anstyle::Style;

Expand Down Expand Up @@ -406,16 +406,16 @@ impl Shell {
Ok(())
}

/// Prints the passed in [Message] to stderr
pub fn print_message(&mut self, message: Message<'_>) -> std::io::Result<()> {
/// Prints the passed in [`Report`] to stderr
pub fn print_report(&mut self, report: Report<'_>) -> std::io::Result<()> {
let term_width = self
.err_width()
.diagnostic_terminal_width()
.unwrap_or(annotate_snippets::renderer::DEFAULT_TERM_WIDTH);
writeln!(
self.err(),
"{}",
Renderer::styled().term_width(term_width).render(message)
Renderer::styled().term_width(term_width).render(report)
)
}
}
Expand Down
212 changes: 94 additions & 118 deletions src/cargo/util/lints.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::core::{Edition, Feature, Features, Manifest, Package};
use crate::{CargoResult, GlobalContext};
use annotate_snippets::{Level, Snippet};
use annotate_snippets::{AnnotationKind, Group, Level, Snippet};
use cargo_util_schemas::manifest::{TomlLintLevel, TomlToolLints};
use pathdiff::diff_paths;
use std::fmt::Display;
Expand Down Expand Up @@ -133,78 +133,69 @@ fn verify_feature_enabled(
dash_feature_name
);

let message = if let Some(span) =
get_span(manifest.document(), &["lints", "cargo", lint_name], false)
let (contents, path, span) = if let Some(span) =
get_key_value_span(manifest.document(), &["lints", "cargo", lint_name])
{
Level::Error
.title(&title)
.snippet(
Snippet::source(manifest.contents())
.origin(&manifest_path)
.annotation(Level::Error.span(span).label(&label))
.fold(true),
)
.footer(Level::Help.title(&help))
(manifest.contents(), manifest_path, span)
} else if let Some(lint_span) =
get_key_value_span(ws_document, &["workspace", "lints", "cargo", lint_name])
{
(ws_contents, ws_path, lint_span)
} else {
let lint_span = get_span(
ws_document,
&["workspace", "lints", "cargo", lint_name],
false,
)
.unwrap_or_else(|| {
panic!("could not find `cargo::{lint_name}` in `[lints]`, or `[workspace.lints]` ")
});
panic!("could not find `cargo::{lint_name}` in `[lints]`, or `[workspace.lints]` ")
};

let inherited_note = if let (Some(inherit_span_key), Some(inherit_span_value)) = (
get_span(manifest.document(), &["lints", "workspace"], false),
get_span(manifest.document(), &["lints", "workspace"], true),
) {
Level::Note.title(&second_title).snippet(
let mut report = Vec::new();
report.push(
Group::with_title(Level::ERROR.primary_title(title))
.element(
Snippet::source(contents)
.path(path)
.annotation(AnnotationKind::Primary.span(span.key).label(label)),
)
.element(Level::HELP.message(help)),
);

if let Some(inherit_span) = get_key_value_span(manifest.document(), &["lints", "workspace"])
{
report.push(
Group::with_title(Level::NOTE.secondary_title(second_title)).element(
Snippet::source(manifest.contents())
.origin(&manifest_path)
.path(manifest_path)
.annotation(
Level::Note.span(inherit_span_key.start..inherit_span_value.end),
)
.fold(true),
)
} else {
Level::Note.title(&second_title)
};

Level::Error
.title(&title)
.snippet(
Snippet::source(ws_contents)
.origin(&ws_path)
.annotation(Level::Error.span(lint_span).label(&label))
.fold(true),
)
.footer(inherited_note)
.footer(Level::Help.title(&help))
};
AnnotationKind::Context
.span(inherit_span.key.start..inherit_span.value.end),
),
),
);
}

*error_count += 1;
gctx.shell().print_message(message)?;
gctx.shell().print_report(&report)?;
}
Ok(())
}

pub fn get_span(
#[derive(Clone)]
pub struct TomlSpan {
pub key: Range<usize>,
pub value: Range<usize>,
}

pub fn get_key_value_span(
document: &toml::Spanned<toml::de::DeTable<'static>>,
path: &[&str],
get_value: bool,
) -> Option<Range<usize>> {
) -> Option<TomlSpan> {
let mut table = document.get_ref();
let mut iter = path.into_iter().peekable();
while let Some(key) = iter.next() {
let key_s: &str = key.as_ref();
let (key, item) = table.get_key_value(key_s)?;
if iter.peek().is_none() {
return if get_value {
Some(item.span())
} else {
Some(key.span())
};
return Some(TomlSpan {
key: key.span(),
value: item.span(),
});
}
if let Some(next_table) = item.get_ref().as_table() {
table = next_table;
Expand All @@ -213,7 +204,10 @@ pub fn get_span(
if let Some(array) = item.get_ref().as_array() {
let next = iter.next().unwrap();
return array.iter().find_map(|item| match item.get_ref() {
toml::de::DeValue::String(s) if s == next => Some(item.span()),
toml::de::DeValue::String(s) if s == next => Some(TomlSpan {
key: key.span(),
value: item.span(),
}),
_ => None,
});
}
Expand Down Expand Up @@ -337,12 +331,12 @@ impl LintLevel {
self == &LintLevel::Forbid || self == &LintLevel::Deny
}

pub fn to_diagnostic_level(self) -> Level {
pub fn to_diagnostic_level(self) -> Level<'static> {
match self {
LintLevel::Allow => unreachable!("allow does not map to a diagnostic level"),
LintLevel::Warn => Level::Warning,
LintLevel::Deny => Level::Error,
LintLevel::Forbid => Level::Error,
LintLevel::Warn => Level::WARNING,
LintLevel::Deny => Level::ERROR,
LintLevel::Forbid => Level::ERROR,
}
}
}
Expand Down Expand Up @@ -455,19 +449,17 @@ pub fn check_im_a_teapot(
let manifest_path = rel_cwd_manifest_path(path, gctx);
let emitted_reason = IM_A_TEAPOT.emitted_source(lint_level, reason);

let key_span = get_span(manifest.document(), &["package", "im-a-teapot"], false).unwrap();
let value_span = get_span(manifest.document(), &["package", "im-a-teapot"], true).unwrap();
let message = level
.title(IM_A_TEAPOT.desc)
.snippet(
let span = get_key_value_span(manifest.document(), &["package", "im-a-teapot"]).unwrap();

let report = &[Group::with_title(level.primary_title(IM_A_TEAPOT.desc))
.element(
Snippet::source(manifest.contents())
.origin(&manifest_path)
.annotation(level.span(key_span.start..value_span.end))
.fold(true),
.path(&manifest_path)
.annotation(AnnotationKind::Primary.span(span.key.start..span.value.end)),
)
.footer(Level::Note.title(&emitted_reason));
.element(Level::NOTE.message(&emitted_reason))];

gctx.shell().print_message(message)?;
gctx.shell().print_report(report)?;
}
Ok(())
}
Expand Down Expand Up @@ -535,64 +527,48 @@ fn output_unknown_lints(
let help =
matching.map(|(name, kind)| format!("there is a {kind} with a similar name: `{name}`"));

let mut footers = Vec::new();
let (contents, path, span) = if let Some(span) =
get_key_value_span(manifest.document(), &["lints", "cargo", lint_name])
{
(manifest.contents(), manifest_path, span)
} else if let Some(lint_span) =
get_key_value_span(ws_document, &["workspace", "lints", "cargo", lint_name])
{
(ws_contents, ws_path, lint_span)
} else {
panic!("could not find `cargo::{lint_name}` in `[lints]`, or `[workspace.lints]` ")
};

let mut report = Vec::new();
let mut group = Group::with_title(level.clone().primary_title(title)).element(
Snippet::source(contents)
.path(path)
.annotation(AnnotationKind::Primary.span(span.key)),
);
if emitted_source.is_none() {
emitted_source = Some(UNKNOWN_LINTS.emitted_source(lint_level, reason));
footers.push(Level::Note.title(emitted_source.as_ref().unwrap()));
group = group.element(Level::NOTE.message(emitted_source.as_ref().unwrap()));
}
if let Some(help) = help.as_ref() {
group = group.element(Level::HELP.message(help));
}
report.push(group);

let mut message = if let Some(span) =
get_span(manifest.document(), &["lints", "cargo", lint_name], false)
if let Some(inherit_span) = get_key_value_span(manifest.document(), &["lints", "workspace"])
{
level.title(&title).snippet(
Snippet::source(manifest.contents())
.origin(&manifest_path)
.annotation(Level::Error.span(span))
.fold(true),
)
} else {
let lint_span = get_span(
ws_document,
&["workspace", "lints", "cargo", lint_name],
false,
)
.unwrap_or_else(|| {
panic!("could not find `cargo::{lint_name}` in `[lints]`, or `[workspace.lints]` ")
});

let inherited_note = if let (Some(inherit_span_key), Some(inherit_span_value)) = (
get_span(manifest.document(), &["lints", "workspace"], false),
get_span(manifest.document(), &["lints", "workspace"], true),
) {
Level::Note.title(&second_title).snippet(
report.push(
Group::with_title(Level::NOTE.secondary_title(second_title)).element(
Snippet::source(manifest.contents())
.origin(&manifest_path)
.path(manifest_path)
.annotation(
Level::Note.span(inherit_span_key.start..inherit_span_value.end),
)
.fold(true),
)
} else {
Level::Note.title(&second_title)
};
footers.push(inherited_note);

level.title(&title).snippet(
Snippet::source(ws_contents)
.origin(&ws_path)
.annotation(Level::Error.span(lint_span))
.fold(true),
)
};

if let Some(help) = help.as_ref() {
footers.push(Level::Help.title(help));
}
for footer in footers {
message = message.footer(footer);
AnnotationKind::Context
.span(inherit_span.key.start..inherit_span.value.end),
),
),
);
}

gctx.shell().print_message(message)?;
gctx.shell().print_report(&report)?;
}

Ok(())
Expand Down
Loading
Loading