Add HasSession
trait
This commit is contained in:
parent
5ccf5432ab
commit
3779062955
@ -6,7 +6,8 @@
|
|||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
|
use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
|
||||||
use rustc_lint::{LateContext, LintContext};
|
use rustc_lint::{EarlyContext, LateContext};
|
||||||
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::source_map::{original_sp, SourceMap};
|
use rustc_span::source_map::{original_sp, SourceMap};
|
||||||
use rustc_span::{
|
use rustc_span::{
|
||||||
@ -17,6 +18,30 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
|
pub trait HasSession {
|
||||||
|
fn sess(&self) -> &Session;
|
||||||
|
}
|
||||||
|
impl HasSession for Session {
|
||||||
|
fn sess(&self) -> &Session {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl HasSession for TyCtxt<'_> {
|
||||||
|
fn sess(&self) -> &Session {
|
||||||
|
self.sess
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl HasSession for EarlyContext<'_> {
|
||||||
|
fn sess(&self) -> &Session {
|
||||||
|
::rustc_lint::LintContext::sess(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl HasSession for LateContext<'_> {
|
||||||
|
fn sess(&self) -> &Session {
|
||||||
|
self.tcx.sess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Conversion of a value into the range portion of a `Span`.
|
/// Conversion of a value into the range portion of a `Span`.
|
||||||
pub trait SpanRange: Sized {
|
pub trait SpanRange: Sized {
|
||||||
fn into_range(self) -> Range<BytePos>;
|
fn into_range(self) -> Range<BytePos>;
|
||||||
@ -71,19 +96,19 @@ fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
|
|||||||
pub trait SpanRangeExt: SpanRange {
|
pub trait SpanRangeExt: SpanRange {
|
||||||
/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
|
/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
|
||||||
/// extends through multiple files, or is malformed.
|
/// extends through multiple files, or is malformed.
|
||||||
fn get_source_text(self, cx: &impl LintContext) -> Option<SourceFileRange> {
|
fn get_source_text(self, cx: &impl HasSession) -> Option<SourceFileRange> {
|
||||||
get_source_text(cx.sess().source_map(), self.into_range())
|
get_source_text(cx.sess().source_map(), self.into_range())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls the given function with the source text referenced and returns the value. Returns
|
/// Calls the given function with the source text referenced and returns the value. Returns
|
||||||
/// `None` if the source text cannot be retrieved.
|
/// `None` if the source text cannot be retrieved.
|
||||||
fn with_source_text<T>(self, cx: &impl LintContext, f: impl for<'a> FnOnce(&'a str) -> T) -> Option<T> {
|
fn with_source_text<T>(self, cx: &impl HasSession, f: impl for<'a> FnOnce(&'a str) -> T) -> Option<T> {
|
||||||
with_source_text(cx.sess().source_map(), self.into_range(), f)
|
with_source_text(cx.sess().source_map(), self.into_range(), f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the referenced source text satisfies the given predicate. Returns `false` if the
|
/// Checks if the referenced source text satisfies the given predicate. Returns `false` if the
|
||||||
/// source text cannot be retrieved.
|
/// source text cannot be retrieved.
|
||||||
fn check_source_text(self, cx: &impl LintContext, pred: impl for<'a> FnOnce(&'a str) -> bool) -> bool {
|
fn check_source_text(self, cx: &impl HasSession, pred: impl for<'a> FnOnce(&'a str) -> bool) -> bool {
|
||||||
self.with_source_text(cx, pred).unwrap_or(false)
|
self.with_source_text(cx, pred).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +116,7 @@ fn check_source_text(self, cx: &impl LintContext, pred: impl for<'a> FnOnce(&'a
|
|||||||
/// and returns the value. Returns `None` if the source text cannot be retrieved.
|
/// and returns the value. Returns `None` if the source text cannot be retrieved.
|
||||||
fn with_source_text_and_range<T>(
|
fn with_source_text_and_range<T>(
|
||||||
self,
|
self,
|
||||||
cx: &impl LintContext,
|
cx: &impl HasSession,
|
||||||
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> T,
|
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> T,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
with_source_text_and_range(cx.sess().source_map(), self.into_range(), f)
|
with_source_text_and_range(cx.sess().source_map(), self.into_range(), f)
|
||||||
@ -104,30 +129,30 @@ fn with_source_text_and_range<T>(
|
|||||||
/// The new range must reside within the same source file.
|
/// The new range must reside within the same source file.
|
||||||
fn map_range(
|
fn map_range(
|
||||||
self,
|
self,
|
||||||
cx: &impl LintContext,
|
cx: &impl HasSession,
|
||||||
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> Option<Range<usize>>,
|
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> Option<Range<usize>>,
|
||||||
) -> Option<Range<BytePos>> {
|
) -> Option<Range<BytePos>> {
|
||||||
map_range(cx.sess().source_map(), self.into_range(), f)
|
map_range(cx.sess().source_map(), self.into_range(), f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extends the range to include all preceding whitespace characters.
|
/// Extends the range to include all preceding whitespace characters.
|
||||||
fn with_leading_whitespace(self, cx: &impl LintContext) -> Range<BytePos> {
|
fn with_leading_whitespace(self, cx: &impl HasSession) -> Range<BytePos> {
|
||||||
with_leading_whitespace(cx.sess().source_map(), self.into_range())
|
with_leading_whitespace(cx.sess().source_map(), self.into_range())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trims the leading whitespace from the range.
|
/// Trims the leading whitespace from the range.
|
||||||
fn trim_start(self, cx: &impl LintContext) -> Range<BytePos> {
|
fn trim_start(self, cx: &impl HasSession) -> Range<BytePos> {
|
||||||
trim_start(cx.sess().source_map(), self.into_range())
|
trim_start(cx.sess().source_map(), self.into_range())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes the referenced source text to the given writer. Will return `Err` if the source text
|
/// Writes the referenced source text to the given writer. Will return `Err` if the source text
|
||||||
/// could not be retrieved.
|
/// could not be retrieved.
|
||||||
fn write_source_text_to(self, cx: &impl LintContext, dst: &mut impl fmt::Write) -> fmt::Result {
|
fn write_source_text_to(self, cx: &impl HasSession, dst: &mut impl fmt::Write) -> fmt::Result {
|
||||||
write_source_text_to(cx.sess().source_map(), self.into_range(), dst)
|
write_source_text_to(cx.sess().source_map(), self.into_range(), dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extracts the referenced source text as an owned string.
|
/// Extracts the referenced source text as an owned string.
|
||||||
fn source_text_to_string(self, cx: &impl LintContext) -> Option<String> {
|
fn source_text_to_string(self, cx: &impl HasSession) -> Option<String> {
|
||||||
self.with_source_text(cx, ToOwned::to_owned)
|
self.with_source_text(cx, ToOwned::to_owned)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,15 +252,15 @@ pub fn as_str(&self) -> Option<&str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
|
/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
|
||||||
pub fn expr_block<T: LintContext>(
|
pub fn expr_block(
|
||||||
cx: &T,
|
sess: &impl HasSession,
|
||||||
expr: &Expr<'_>,
|
expr: &Expr<'_>,
|
||||||
outer: SyntaxContext,
|
outer: SyntaxContext,
|
||||||
default: &str,
|
default: &str,
|
||||||
indent_relative_to: Option<Span>,
|
indent_relative_to: Option<Span>,
|
||||||
app: &mut Applicability,
|
app: &mut Applicability,
|
||||||
) -> String {
|
) -> String {
|
||||||
let (code, from_macro) = snippet_block_with_context(cx, expr.span, outer, default, indent_relative_to, app);
|
let (code, from_macro) = snippet_block_with_context(sess, expr.span, outer, default, indent_relative_to, app);
|
||||||
if !from_macro
|
if !from_macro
|
||||||
&& let ExprKind::Block(block, _) = expr.kind
|
&& let ExprKind::Block(block, _) = expr.kind
|
||||||
&& block.rules != BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
|
&& block.rules != BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
|
||||||
@ -260,13 +285,13 @@ pub fn expr_block<T: LintContext>(
|
|||||||
/// let x = ();
|
/// let x = ();
|
||||||
/// // ^^^^^^^^^^
|
/// // ^^^^^^^^^^
|
||||||
/// ```
|
/// ```
|
||||||
pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
|
pub fn first_line_of_span(sess: &impl HasSession, span: Span) -> Span {
|
||||||
first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos))
|
first_char_in_first_line(sess, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> {
|
fn first_char_in_first_line(sess: &impl HasSession, span: Span) -> Option<BytePos> {
|
||||||
let line_span = line_span(cx, span);
|
let line_span = line_span(sess, span);
|
||||||
snippet_opt(cx, line_span).and_then(|snip| {
|
snippet_opt(sess, line_span).and_then(|snip| {
|
||||||
snip.find(|c: char| !c.is_whitespace())
|
snip.find(|c: char| !c.is_whitespace())
|
||||||
.map(|pos| line_span.lo() + BytePos::from_usize(pos))
|
.map(|pos| line_span.lo() + BytePos::from_usize(pos))
|
||||||
})
|
})
|
||||||
@ -281,9 +306,9 @@ fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePo
|
|||||||
/// let x = ();
|
/// let x = ();
|
||||||
/// // ^^^^^^^^^^^^^^
|
/// // ^^^^^^^^^^^^^^
|
||||||
/// ```
|
/// ```
|
||||||
fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
|
fn line_span(sess: &impl HasSession, span: Span) -> Span {
|
||||||
let span = original_sp(span, DUMMY_SP);
|
let span = original_sp(span, DUMMY_SP);
|
||||||
let SourceFileAndLine { sf, line } = cx.sess().source_map().lookup_line(span.lo()).unwrap();
|
let SourceFileAndLine { sf, line } = sess.sess().source_map().lookup_line(span.lo()).unwrap();
|
||||||
let line_start = sf.lines()[line];
|
let line_start = sf.lines()[line];
|
||||||
let line_start = sf.absolute_position(line_start);
|
let line_start = sf.absolute_position(line_start);
|
||||||
span.with_lo(line_start)
|
span.with_lo(line_start)
|
||||||
@ -297,13 +322,13 @@ fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
|
|||||||
/// let x = ();
|
/// let x = ();
|
||||||
/// // ^^ -- will return 4
|
/// // ^^ -- will return 4
|
||||||
/// ```
|
/// ```
|
||||||
pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
|
pub fn indent_of(sess: &impl HasSession, span: Span) -> Option<usize> {
|
||||||
snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
|
snippet_opt(sess, line_span(sess, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a snippet of the indentation of the line of a span
|
/// Gets a snippet of the indentation of the line of a span
|
||||||
pub fn snippet_indent<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
pub fn snippet_indent(sess: &impl HasSession, span: Span) -> Option<String> {
|
||||||
snippet_opt(cx, line_span(cx, span)).map(|mut s| {
|
snippet_opt(sess, line_span(sess, span)).map(|mut s| {
|
||||||
let len = s.len() - s.trim_start().len();
|
let len = s.len() - s.trim_start().len();
|
||||||
s.truncate(len);
|
s.truncate(len);
|
||||||
s
|
s
|
||||||
@ -315,8 +340,8 @@ pub fn snippet_indent<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
|||||||
// sources that the user has no control over.
|
// sources that the user has no control over.
|
||||||
// For some reason these attributes don't have any expansion info on them, so
|
// For some reason these attributes don't have any expansion info on them, so
|
||||||
// we have to check it this way until there is a better way.
|
// we have to check it this way until there is a better way.
|
||||||
pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool {
|
pub fn is_present_in_source(sess: &impl HasSession, span: Span) -> bool {
|
||||||
if let Some(snippet) = snippet_opt(cx, span) {
|
if let Some(snippet) = snippet_opt(sess, span) {
|
||||||
if snippet.is_empty() {
|
if snippet.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -407,8 +432,8 @@ fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>,
|
|||||||
/// snippet(cx, span1, "..") // -> "value"
|
/// snippet(cx, span1, "..") // -> "value"
|
||||||
/// snippet(cx, span2, "..") // -> "Vec::new()"
|
/// snippet(cx, span2, "..") // -> "Vec::new()"
|
||||||
/// ```
|
/// ```
|
||||||
pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
pub fn snippet<'a>(sess: &impl HasSession, span: Span, default: &'a str) -> Cow<'a, str> {
|
||||||
snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
|
snippet_opt(sess, span).map_or_else(|| Cow::Borrowed(default), From::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as [`snippet`], but it adapts the applicability level by following rules:
|
/// 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<
|
|||||||
/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
|
/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
|
||||||
/// - If the default value is used and the applicability level is `MachineApplicable`, change it to
|
/// - If the default value is used and the applicability level is `MachineApplicable`, change it to
|
||||||
/// `HasPlaceholders`
|
/// `HasPlaceholders`
|
||||||
pub fn snippet_with_applicability<'a, T: LintContext>(
|
pub fn snippet_with_applicability<'a>(
|
||||||
cx: &T,
|
sess: &impl HasSession,
|
||||||
span: Span,
|
span: Span,
|
||||||
default: &'a str,
|
default: &'a str,
|
||||||
applicability: &mut Applicability,
|
applicability: &mut Applicability,
|
||||||
) -> Cow<'a, str> {
|
) -> Cow<'a, str> {
|
||||||
snippet_with_applicability_sess(cx.sess(), span, default, applicability)
|
snippet_with_applicability_sess(sess.sess(), span, default, applicability)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn snippet_with_applicability_sess<'a>(
|
fn snippet_with_applicability_sess<'a>(
|
||||||
@ -435,7 +460,7 @@ fn snippet_with_applicability_sess<'a>(
|
|||||||
if *applicability != Applicability::Unspecified && span.from_expansion() {
|
if *applicability != Applicability::Unspecified && span.from_expansion() {
|
||||||
*applicability = Applicability::MaybeIncorrect;
|
*applicability = Applicability::MaybeIncorrect;
|
||||||
}
|
}
|
||||||
snippet_opt_sess(sess, span).map_or_else(
|
snippet_opt(sess, span).map_or_else(
|
||||||
|| {
|
|| {
|
||||||
if *applicability == Applicability::MachineApplicable {
|
if *applicability == Applicability::MachineApplicable {
|
||||||
*applicability = Applicability::HasPlaceholders;
|
*applicability = Applicability::HasPlaceholders;
|
||||||
@ -447,12 +472,8 @@ fn snippet_with_applicability_sess<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a span to a code snippet. Returns `None` if not available.
|
/// Converts a span to a code snippet. Returns `None` if not available.
|
||||||
pub fn snippet_opt(cx: &impl LintContext, span: Span) -> Option<String> {
|
pub fn snippet_opt(sess: &impl HasSession, span: Span) -> Option<String> {
|
||||||
snippet_opt_sess(cx.sess(), span)
|
sess.sess().source_map().span_to_snippet(span).ok()
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
/// 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> {
|
|||||||
/// } // aligned with `if`
|
/// } // aligned with `if`
|
||||||
/// ```
|
/// ```
|
||||||
/// Note that the first line of the snippet always has 0 indentation.
|
/// Note that the first line of the snippet always has 0 indentation.
|
||||||
pub fn snippet_block<'a, T: LintContext>(
|
pub fn snippet_block<'a>(
|
||||||
cx: &T,
|
sess: &impl HasSession,
|
||||||
span: Span,
|
span: Span,
|
||||||
default: &'a str,
|
default: &'a str,
|
||||||
indent_relative_to: Option<Span>,
|
indent_relative_to: Option<Span>,
|
||||||
) -> Cow<'a, str> {
|
) -> Cow<'a, str> {
|
||||||
let snip = snippet(cx, span, default);
|
let snip = snippet(sess, span, default);
|
||||||
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
|
let indent = indent_relative_to.and_then(|s| indent_of(sess, s));
|
||||||
reindent_multiline(snip, true, indent)
|
reindent_multiline(snip, true, indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as `snippet_block`, but adapts the applicability level by the rules of
|
/// Same as `snippet_block`, but adapts the applicability level by the rules of
|
||||||
/// `snippet_with_applicability`.
|
/// `snippet_with_applicability`.
|
||||||
pub fn snippet_block_with_applicability<'a>(
|
pub fn snippet_block_with_applicability<'a>(
|
||||||
cx: &impl LintContext,
|
sess: &impl HasSession,
|
||||||
span: Span,
|
span: Span,
|
||||||
default: &'a str,
|
default: &'a str,
|
||||||
indent_relative_to: Option<Span>,
|
indent_relative_to: Option<Span>,
|
||||||
applicability: &mut Applicability,
|
applicability: &mut Applicability,
|
||||||
) -> Cow<'a, str> {
|
) -> Cow<'a, str> {
|
||||||
let snip = snippet_with_applicability(cx, span, default, applicability);
|
let snip = snippet_with_applicability(sess, span, default, applicability);
|
||||||
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
|
let indent = indent_relative_to.and_then(|s| indent_of(sess, s));
|
||||||
reindent_multiline(snip, true, indent)
|
reindent_multiline(snip, true, indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn snippet_block_with_context<'a>(
|
pub fn snippet_block_with_context<'a>(
|
||||||
cx: &impl LintContext,
|
sess: &impl HasSession,
|
||||||
span: Span,
|
span: Span,
|
||||||
outer: SyntaxContext,
|
outer: SyntaxContext,
|
||||||
default: &'a str,
|
default: &'a str,
|
||||||
indent_relative_to: Option<Span>,
|
indent_relative_to: Option<Span>,
|
||||||
app: &mut Applicability,
|
app: &mut Applicability,
|
||||||
) -> (Cow<'a, str>, bool) {
|
) -> (Cow<'a, str>, bool) {
|
||||||
let (snip, from_macro) = snippet_with_context(cx, span, outer, default, app);
|
let (snip, from_macro) = snippet_with_context(sess, span, outer, default, app);
|
||||||
let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
|
let indent = indent_relative_to.and_then(|s| indent_of(sess, s));
|
||||||
(reindent_multiline(snip, true, indent), from_macro)
|
(reindent_multiline(snip, true, indent), from_macro)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,13 +558,13 @@ pub fn snippet_block_with_context<'a>(
|
|||||||
///
|
///
|
||||||
/// This will also return whether or not the snippet is a macro call.
|
/// This will also return whether or not the snippet is a macro call.
|
||||||
pub fn snippet_with_context<'a>(
|
pub fn snippet_with_context<'a>(
|
||||||
cx: &impl LintContext,
|
sess: &impl HasSession,
|
||||||
span: Span,
|
span: Span,
|
||||||
outer: SyntaxContext,
|
outer: SyntaxContext,
|
||||||
default: &'a str,
|
default: &'a str,
|
||||||
applicability: &mut Applicability,
|
applicability: &mut Applicability,
|
||||||
) -> (Cow<'a, str>, bool) {
|
) -> (Cow<'a, str>, bool) {
|
||||||
snippet_with_context_sess(cx.sess(), span, outer, default, applicability)
|
snippet_with_context_sess(sess.sess(), span, outer, default, applicability)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn snippet_with_context_sess<'a>(
|
fn snippet_with_context_sess<'a>(
|
||||||
@ -661,15 +682,15 @@ pub fn trim_span(sm: &SourceMap, span: Span) -> Span {
|
|||||||
/// writeln!(o, "") -> writeln!(o, "")
|
/// writeln!(o, "") -> writeln!(o, "")
|
||||||
/// ^^ ^^^^
|
/// ^^ ^^^^
|
||||||
/// ```
|
/// ```
|
||||||
pub fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span {
|
pub fn expand_past_previous_comma(sess: &impl HasSession, span: Span) -> Span {
|
||||||
let extended = cx.sess().source_map().span_extend_to_prev_char(span, ',', true);
|
let extended = sess.sess().source_map().span_extend_to_prev_char(span, ',', true);
|
||||||
extended.with_lo(extended.lo() - BytePos(1))
|
extended.with_lo(extended.lo() - BytePos(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts `expr` to a `char` literal if it's a `str` literal containing a single
|
/// Converts `expr` to a `char` literal if it's a `str` literal containing a single
|
||||||
/// character (or a single byte with `ascii_only`)
|
/// character (or a single byte with `ascii_only`)
|
||||||
pub fn str_literal_to_char_literal(
|
pub fn str_literal_to_char_literal(
|
||||||
cx: &LateContext<'_>,
|
sess: &impl HasSession,
|
||||||
expr: &Expr<'_>,
|
expr: &Expr<'_>,
|
||||||
applicability: &mut Applicability,
|
applicability: &mut Applicability,
|
||||||
ascii_only: bool,
|
ascii_only: bool,
|
||||||
@ -684,7 +705,7 @@ pub fn str_literal_to_char_literal(
|
|||||||
}
|
}
|
||||||
&& len == 1
|
&& len == 1
|
||||||
{
|
{
|
||||||
let snip = snippet_with_applicability(cx, expr.span, string, applicability);
|
let snip = snippet_with_applicability(sess, expr.span, string, applicability);
|
||||||
let ch = if let StrStyle::Raw(nhash) = style {
|
let ch = if let StrStyle::Raw(nhash) = style {
|
||||||
let nhash = nhash as usize;
|
let nhash = nhash as usize;
|
||||||
// for raw string: r##"a"##
|
// for raw string: r##"a"##
|
||||||
|
Loading…
Reference in New Issue
Block a user