Skip to content

Commit 3779062

Browse files
committed
Add HasSession trait
1 parent 5ccf543 commit 3779062

File tree

1 file changed

+75
-54
lines changed

1 file changed

+75
-54
lines changed

clippy_utils/src/source.rs

Lines changed: 75 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use rustc_ast::{LitKind, StrStyle};
66
use rustc_data_structures::sync::Lrc;
77
use rustc_errors::Applicability;
88
use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
9-
use rustc_lint::{LateContext, LintContext};
9+
use rustc_lint::{EarlyContext, LateContext};
10+
use rustc_middle::ty::TyCtxt;
1011
use rustc_session::Session;
1112
use rustc_span::source_map::{original_sp, SourceMap};
1213
use rustc_span::{
@@ -17,6 +18,30 @@ use std::borrow::Cow;
1718
use std::fmt;
1819
use std::ops::Range;
1920

21+
pub trait HasSession {
22+
fn sess(&self) -> &Session;
23+
}
24+
impl HasSession for Session {
25+
fn sess(&self) -> &Session {
26+
self
27+
}
28+
}
29+
impl HasSession for TyCtxt<'_> {
30+
fn sess(&self) -> &Session {
31+
self.sess
32+
}
33+
}
34+
impl HasSession for EarlyContext<'_> {
35+
fn sess(&self) -> &Session {
36+
::rustc_lint::LintContext::sess(self)
37+
}
38+
}
39+
impl HasSession for LateContext<'_> {
40+
fn sess(&self) -> &Session {
41+
self.tcx.sess()
42+
}
43+
}
44+
2045
/// Conversion of a value into the range portion of a `Span`.
2146
pub trait SpanRange: Sized {
2247
fn into_range(self) -> Range<BytePos>;
@@ -71,27 +96,27 @@ impl IntoSpan for Range<BytePos> {
7196
pub trait SpanRangeExt: SpanRange {
7297
/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
7398
/// extends through multiple files, or is malformed.
74-
fn get_source_text(self, cx: &impl LintContext) -> Option<SourceFileRange> {
99+
fn get_source_text(self, cx: &impl HasSession) -> Option<SourceFileRange> {
75100
get_source_text(cx.sess().source_map(), self.into_range())
76101
}
77102

78103
/// Calls the given function with the source text referenced and returns the value. Returns
79104
/// `None` if the source text cannot be retrieved.
80-
fn with_source_text<T>(self, cx: &impl LintContext, f: impl for<'a> FnOnce(&'a str) -> T) -> Option<T> {
105+
fn with_source_text<T>(self, cx: &impl HasSession, f: impl for<'a> FnOnce(&'a str) -> T) -> Option<T> {
81106
with_source_text(cx.sess().source_map(), self.into_range(), f)
82107
}
83108

84109
/// Checks if the referenced source text satisfies the given predicate. Returns `false` if the
85110
/// source text cannot be retrieved.
86-
fn check_source_text(self, cx: &impl LintContext, pred: impl for<'a> FnOnce(&'a str) -> bool) -> bool {
111+
fn check_source_text(self, cx: &impl HasSession, pred: impl for<'a> FnOnce(&'a str) -> bool) -> bool {
87112
self.with_source_text(cx, pred).unwrap_or(false)
88113
}
89114

90115
/// Calls the given function with the both the text of the source file and the referenced range,
91116
/// and returns the value. Returns `None` if the source text cannot be retrieved.
92117
fn with_source_text_and_range<T>(
93118
self,
94-
cx: &impl LintContext,
119+
cx: &impl HasSession,
95120
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> T,
96121
) -> Option<T> {
97122
with_source_text_and_range(cx.sess().source_map(), self.into_range(), f)
@@ -104,30 +129,30 @@ pub trait SpanRangeExt: SpanRange {
104129
/// The new range must reside within the same source file.
105130
fn map_range(
106131
self,
107-
cx: &impl LintContext,
132+
cx: &impl HasSession,
108133
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> Option<Range<usize>>,
109134
) -> Option<Range<BytePos>> {
110135
map_range(cx.sess().source_map(), self.into_range(), f)
111136
}
112137

113138
/// Extends the range to include all preceding whitespace characters.
114-
fn with_leading_whitespace(self, cx: &impl LintContext) -> Range<BytePos> {
139+
fn with_leading_whitespace(self, cx: &impl HasSession) -> Range<BytePos> {
115140
with_leading_whitespace(cx.sess().source_map(), self.into_range())
116141
}
117142

118143
/// Trims the leading whitespace from the range.
119-
fn trim_start(self, cx: &impl LintContext) -> Range<BytePos> {
144+
fn trim_start(self, cx: &impl HasSession) -> Range<BytePos> {
120145
trim_start(cx.sess().source_map(), self.into_range())
121146
}
122147

123148
/// Writes the referenced source text to the given writer. Will return `Err` if the source text
124149
/// could not be retrieved.
125-
fn write_source_text_to(self, cx: &impl LintContext, dst: &mut impl fmt::Write) -> fmt::Result {
150+
fn write_source_text_to(self, cx: &impl HasSession, dst: &mut impl fmt::Write) -> fmt::Result {
126151
write_source_text_to(cx.sess().source_map(), self.into_range(), dst)
127152
}
128153

129154
/// Extracts the referenced source text as an owned string.
130-
fn source_text_to_string(self, cx: &impl LintContext) -> Option<String> {
155+
fn source_text_to_string(self, cx: &impl HasSession) -> Option<String> {
131156
self.with_source_text(cx, ToOwned::to_owned)
132157
}
133158
}
@@ -227,15 +252,15 @@ impl SourceFileRange {
227252
}
228253

229254
/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
230-
pub fn expr_block<T: LintContext>(
231-
cx: &T,
255+
pub fn expr_block(
256+
sess: &impl HasSession,
232257
expr: &Expr<'_>,
233258
outer: SyntaxContext,
234259
default: &str,
235260
indent_relative_to: Option<Span>,
236261
app: &mut Applicability,
237262
) -> String {
238-
let (code, from_macro) = snippet_block_with_context(cx, expr.span, outer, default, indent_relative_to, app);
263+
let (code, from_macro) = snippet_block_with_context(sess, expr.span, outer, default, indent_relative_to, app);
239264
if !from_macro
240265
&& let ExprKind::Block(block, _) = expr.kind
241266
&& block.rules != BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
@@ -260,13 +285,13 @@ pub fn expr_block<T: LintContext>(
260285
/// let x = ();
261286
/// // ^^^^^^^^^^
262287
/// ```
263-
pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
264-
first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos))
288+
pub fn first_line_of_span(sess: &impl HasSession, span: Span) -> Span {
289+
first_char_in_first_line(sess, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos))
265290
}
266291

267-
fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> {
268-
let line_span = line_span(cx, span);
269-
snippet_opt(cx, line_span).and_then(|snip| {
292+
fn first_char_in_first_line(sess: &impl HasSession, span: Span) -> Option<BytePos> {
293+
let line_span = line_span(sess, span);
294+
snippet_opt(sess, line_span).and_then(|snip| {
270295
snip.find(|c: char| !c.is_whitespace())
271296
.map(|pos| line_span.lo() + BytePos::from_usize(pos))
272297
})
@@ -281,9 +306,9 @@ fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePo
281306
/// let x = ();
282307
/// // ^^^^^^^^^^^^^^
283308
/// ```
284-
fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
309+
fn line_span(sess: &impl HasSession, span: Span) -> Span {
285310
let span = original_sp(span, DUMMY_SP);
286-
let SourceFileAndLine { sf, line } = cx.sess().source_map().lookup_line(span.lo()).unwrap();
311+
let SourceFileAndLine { sf, line } = sess.sess().source_map().lookup_line(span.lo()).unwrap();
287312
let line_start = sf.lines()[line];
288313
let line_start = sf.absolute_position(line_start);
289314
span.with_lo(line_start)
@@ -297,13 +322,13 @@ fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
297322
/// let x = ();
298323
/// // ^^ -- will return 4
299324
/// ```
300-
pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
301-
snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
325+
pub fn indent_of(sess: &impl HasSession, span: Span) -> Option<usize> {
326+
snippet_opt(sess, line_span(sess, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
302327
}
303328

304329
/// Gets a snippet of the indentation of the line of a span
305-
pub fn snippet_indent<T: LintContext>(cx: &T, span: Span) -> Option<String> {
306-
snippet_opt(cx, line_span(cx, span)).map(|mut s| {
330+
pub fn snippet_indent(sess: &impl HasSession, span: Span) -> Option<String> {
331+
snippet_opt(sess, line_span(sess, span)).map(|mut s| {
307332
let len = s.len() - s.trim_start().len();
308333
s.truncate(len);
309334
s
@@ -315,8 +340,8 @@ pub fn snippet_indent<T: LintContext>(cx: &T, span: Span) -> Option<String> {
315340
// sources that the user has no control over.
316341
// For some reason these attributes don't have any expansion info on them, so
317342
// we have to check it this way until there is a better way.
318-
pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool {
319-
if let Some(snippet) = snippet_opt(cx, span) {
343+
pub fn is_present_in_source(sess: &impl HasSession, span: Span) -> bool {
344+
if let Some(snippet) = snippet_opt(sess, span) {
320345
if snippet.is_empty() {
321346
return false;
322347
}
@@ -407,8 +432,8 @@ fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>,
407432
/// snippet(cx, span1, "..") // -> "value"
408433
/// snippet(cx, span2, "..") // -> "Vec::new()"
409434
/// ```
410-
pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
411-
snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
435+
pub fn snippet<'a>(sess: &impl HasSession, span: Span, default: &'a str) -> Cow<'a, str> {
436+
snippet_opt(sess, span).map_or_else(|| Cow::Borrowed(default), From::from)
412437
}
413438

414439
/// Same as [`snippet`], but it adapts the applicability level by following rules:
@@ -417,13 +442,13 @@ pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<
417442
/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
418443
/// - If the default value is used and the applicability level is `MachineApplicable`, change it to
419444
/// `HasPlaceholders`
420-
pub fn snippet_with_applicability<'a, T: LintContext>(
421-
cx: &T,
445+
pub fn snippet_with_applicability<'a>(
446+
sess: &impl HasSession,
422447
span: Span,
423448
default: &'a str,
424449
applicability: &mut Applicability,
425450
) -> Cow<'a, str> {
426-
snippet_with_applicability_sess(cx.sess(), span, default, applicability)
451+
snippet_with_applicability_sess(sess.sess(), span, default, applicability)
427452
}
428453

429454
fn snippet_with_applicability_sess<'a>(
@@ -435,7 +460,7 @@ fn snippet_with_applicability_sess<'a>(
435460
if *applicability != Applicability::Unspecified && span.from_expansion() {
436461
*applicability = Applicability::MaybeIncorrect;
437462
}
438-
snippet_opt_sess(sess, span).map_or_else(
463+
snippet_opt(sess, span).map_or_else(
439464
|| {
440465
if *applicability == Applicability::MachineApplicable {
441466
*applicability = Applicability::HasPlaceholders;
@@ -447,12 +472,8 @@ fn snippet_with_applicability_sess<'a>(
447472
}
448473

449474
/// Converts a span to a code snippet. Returns `None` if not available.
450-
pub fn snippet_opt(cx: &impl LintContext, span: Span) -> Option<String> {
451-
snippet_opt_sess(cx.sess(), span)
452-
}
453-
454-
fn snippet_opt_sess(sess: &Session, span: Span) -> Option<String> {
455-
sess.source_map().span_to_snippet(span).ok()
475+
pub fn snippet_opt(sess: &impl HasSession, span: Span) -> Option<String> {
476+
sess.sess().source_map().span_to_snippet(span).ok()
456477
}
457478

458479
/// Converts a span (from a block) to a code snippet if available, otherwise use default.
@@ -489,41 +510,41 @@ fn snippet_opt_sess(sess: &Session, span: Span) -> Option<String> {
489510
/// } // aligned with `if`
490511
/// ```
491512
/// Note that the first line of the snippet always has 0 indentation.
492-
pub fn snippet_block<'a, T: LintContext>(
493-
cx: &T,
513+
pub fn snippet_block<'a>(
514+
sess: &impl HasSession,
494515
span: Span,
495516
default: &'a str,
496517
indent_relative_to: Option<Span>,
497518
) -> Cow<'a, str> {
498-
let snip = snippet(cx, span, default);
499-
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
519+
let snip = snippet(sess, span, default);
520+
let indent = indent_relative_to.and_then(|s| indent_of(sess, s));
500521
reindent_multiline(snip, true, indent)
501522
}
502523

503524
/// Same as `snippet_block`, but adapts the applicability level by the rules of
504525
/// `snippet_with_applicability`.
505526
pub fn snippet_block_with_applicability<'a>(
506-
cx: &impl LintContext,
527+
sess: &impl HasSession,
507528
span: Span,
508529
default: &'a str,
509530
indent_relative_to: Option<Span>,
510531
applicability: &mut Applicability,
511532
) -> Cow<'a, str> {
512-
let snip = snippet_with_applicability(cx, span, default, applicability);
513-
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
533+
let snip = snippet_with_applicability(sess, span, default, applicability);
534+
let indent = indent_relative_to.and_then(|s| indent_of(sess, s));
514535
reindent_multiline(snip, true, indent)
515536
}
516537

517538
pub fn snippet_block_with_context<'a>(
518-
cx: &impl LintContext,
539+
sess: &impl HasSession,
519540
span: Span,
520541
outer: SyntaxContext,
521542
default: &'a str,
522543
indent_relative_to: Option<Span>,
523544
app: &mut Applicability,
524545
) -> (Cow<'a, str>, bool) {
525-
let (snip, from_macro) = snippet_with_context(cx, span, outer, default, app);
526-
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
546+
let (snip, from_macro) = snippet_with_context(sess, span, outer, default, app);
547+
let indent = indent_relative_to.and_then(|s| indent_of(sess, s));
527548
(reindent_multiline(snip, true, indent), from_macro)
528549
}
529550

@@ -537,13 +558,13 @@ pub fn snippet_block_with_context<'a>(
537558
///
538559
/// This will also return whether or not the snippet is a macro call.
539560
pub fn snippet_with_context<'a>(
540-
cx: &impl LintContext,
561+
sess: &impl HasSession,
541562
span: Span,
542563
outer: SyntaxContext,
543564
default: &'a str,
544565
applicability: &mut Applicability,
545566
) -> (Cow<'a, str>, bool) {
546-
snippet_with_context_sess(cx.sess(), span, outer, default, applicability)
567+
snippet_with_context_sess(sess.sess(), span, outer, default, applicability)
547568
}
548569

549570
fn snippet_with_context_sess<'a>(
@@ -661,15 +682,15 @@ pub fn trim_span(sm: &SourceMap, span: Span) -> Span {
661682
/// writeln!(o, "") -> writeln!(o, "")
662683
/// ^^ ^^^^
663684
/// ```
664-
pub fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span {
665-
let extended = cx.sess().source_map().span_extend_to_prev_char(span, ',', true);
685+
pub fn expand_past_previous_comma(sess: &impl HasSession, span: Span) -> Span {
686+
let extended = sess.sess().source_map().span_extend_to_prev_char(span, ',', true);
666687
extended.with_lo(extended.lo() - BytePos(1))
667688
}
668689

669690
/// Converts `expr` to a `char` literal if it's a `str` literal containing a single
670691
/// character (or a single byte with `ascii_only`)
671692
pub fn str_literal_to_char_literal(
672-
cx: &LateContext<'_>,
693+
sess: &impl HasSession,
673694
expr: &Expr<'_>,
674695
applicability: &mut Applicability,
675696
ascii_only: bool,
@@ -684,7 +705,7 @@ pub fn str_literal_to_char_literal(
684705
}
685706
&& len == 1
686707
{
687-
let snip = snippet_with_applicability(cx, expr.span, string, applicability);
708+
let snip = snippet_with_applicability(sess, expr.span, string, applicability);
688709
let ch = if let StrStyle::Raw(nhash) = style {
689710
let nhash = nhash as usize;
690711
// for raw string: r##"a"##

0 commit comments

Comments
 (0)