#![allow(clippy::module_name_repetitions)]
-use crate::line_span;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LintContext};
+use rustc_session::Session;
use rustc_span::hygiene;
-use rustc_span::source_map::SourceMap;
-use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext};
+use rustc_span::source_map::{original_sp, SourceMap};
+use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
use std::borrow::Cow;
/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
})
}
+/// Extends the span to the beginning of the spans line, incl. whitespaces.
+///
+/// ```rust
+/// let x = ();
+/// // ^^
+/// // will be converted to
+/// let x = ();
+/// // ^^^^^^^^^^^^^^
+/// ```
+fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
+ let span = original_sp(span, DUMMY_SP);
+ let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
+ let line_no = source_map_and_line.line;
+ let line_start = source_map_and_line.sf.lines(|lines| lines[line_no]);
+ span.with_lo(line_start)
+}
+
/// Returns the indentation of the line of a span
///
/// ```rust,ignore
span: Span,
default: &'a str,
applicability: &mut Applicability,
+) -> Cow<'a, str> {
+ snippet_with_applicability_sess(cx.sess(), span, default, applicability)
+}
+
+fn snippet_with_applicability_sess<'a>(
+ sess: &Session,
+ span: Span,
+ default: &'a str,
+ applicability: &mut Applicability,
) -> Cow<'a, str> {
if *applicability != Applicability::Unspecified && span.from_expansion() {
*applicability = Applicability::MaybeIncorrect;
}
- snippet_opt(cx, span).map_or_else(
+ snippet_opt_sess(sess, span).map_or_else(
|| {
if *applicability == Applicability::MachineApplicable {
*applicability = Applicability::HasPlaceholders;
}
/// Converts a span to a code snippet. Returns `None` if not available.
-pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> {
- cx.sess().source_map().span_to_snippet(span).ok()
+pub fn snippet_opt(cx: &impl LintContext, span: Span) -> Option<String> {
+ snippet_opt_sess(cx.sess(), span)
+}
+
+fn snippet_opt_sess(sess: &Session, span: Span) -> Option<String> {
+ sess.source_map().span_to_snippet(span).ok()
}
/// Converts a span (from a block) to a code snippet if available, otherwise use default.
/// Same as `snippet_block`, but adapts the applicability level by the rules of
/// `snippet_with_applicability`.
-pub fn snippet_block_with_applicability<'a, T: LintContext>(
- cx: &T,
+pub fn snippet_block_with_applicability<'a>(
+ cx: &impl LintContext,
span: Span,
default: &'a str,
indent_relative_to: Option<Span>,
///
/// This will also return whether or not the snippet is a macro call.
pub fn snippet_with_context<'a>(
- cx: &LateContext<'_>,
+ cx: &impl LintContext,
+ span: Span,
+ outer: SyntaxContext,
+ default: &'a str,
+ applicability: &mut Applicability,
+) -> (Cow<'a, str>, bool) {
+ snippet_with_context_sess(cx.sess(), span, outer, default, applicability)
+}
+
+fn snippet_with_context_sess<'a>(
+ sess: &Session,
span: Span,
outer: SyntaxContext,
default: &'a str,
);
(
- snippet_with_applicability(cx, span, default, applicability),
+ snippet_with_applicability_sess(sess, span, default, applicability),
is_macro_call,
)
}