Auto merge of #52375 - oli-obk:the_early_lint_pass_gets_the_worm, r=M… · rust-lang/rust@12ed235 (original) (raw)

`@@ -41,6 +41,7 @@ use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext};

`

41

41

``

42

42

`use std::collections::HashSet;

`

43

43

``

``

44

`+

use syntax::tokenstream::{TokenTree, TokenStream};

`

44

45

`use syntax::ast;

`

45

46

`use syntax::attr;

`

46

47

`use syntax::codemap::Spanned;

`

`@@ -1784,3 +1785,70 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestFunctions {

`

1784

1785

`};

`

1785

1786

`}

`

1786

1787

`}

`

``

1788

+

``

1789

`+

declare_lint! {

`

``

1790

`+

pub ASYNC_IDENTS,

`

``

1791

`+

Allow,

`

``

1792

`` +

"detects async being used as an identifier"

``

``

1793

`+

}

`

``

1794

+

``

1795

`` +

/// Checks for uses of async as an identifier

``

``

1796

`+

#[derive(Clone)]

`

``

1797

`+

pub struct Async2018;

`

``

1798

+

``

1799

`+

impl LintPass for Async2018 {

`

``

1800

`+

fn get_lints(&self) -> LintArray {

`

``

1801

`+

lint_array!(ASYNC_IDENTS)

`

``

1802

`+

}

`

``

1803

`+

}

`

``

1804

+

``

1805

`+

impl Async2018 {

`

``

1806

`+

fn check_tokens(&mut self, cx: &EarlyContext, tokens: TokenStream) {

`

``

1807

`+

for tt in tokens.into_trees() {

`

``

1808

`+

match tt {

`

``

1809

`+

TokenTree::Token(span, tok) => match tok.ident() {

`

``

1810

`+

// only report non-raw idents

`

``

1811

`+

Some((ident, false)) if ident.as_str() == "async" => {

`

``

1812

`+

self.report(cx, span.substitute_dummy(ident.span))

`

``

1813

`+

},

`

``

1814

`+

_ => {},

`

``

1815

`+

}

`

``

1816

`+

TokenTree::Delimited(_, ref delim) => {

`

``

1817

`+

self.check_tokens(cx, delim.tts.clone().into())

`

``

1818

`+

},

`

``

1819

`+

}

`

``

1820

`+

}

`

``

1821

`+

}

`

``

1822

`+

fn report(&mut self, cx: &EarlyContext, span: Span) {

`

``

1823

`` +

// don't lint r#async

``

``

1824

`+

if cx.sess.parse_sess.raw_identifier_spans.borrow().contains(&span) {

`

``

1825

`+

return;

`

``

1826

`+

}

`

``

1827

`+

let mut lint = cx.struct_span_lint(

`

``

1828

`+

ASYNC_IDENTS,

`

``

1829

`+

span,

`

``

1830

`` +

"async is a keyword in the 2018 edition",

``

``

1831

`+

);

`

``

1832

`+

lint.span_suggestion_with_applicability(

`

``

1833

`+

span,

`

``

1834

`+

"you can use a raw identifier to stay compatible",

`

``

1835

`+

"r#async".to_string(),

`

``

1836

`+

Applicability::MachineApplicable,

`

``

1837

`+

);

`

``

1838

`+

lint.emit()

`

``

1839

`+

}

`

``

1840

`+

}

`

``

1841

+

``

1842

`+

impl EarlyLintPass for Async2018 {

`

``

1843

`+

fn check_mac_def(&mut self, cx: &EarlyContext, mac_def: &ast::MacroDef, _id: ast::NodeId) {

`

``

1844

`+

self.check_tokens(cx, mac_def.stream());

`

``

1845

`+

}

`

``

1846

`+

fn check_mac(&mut self, cx: &EarlyContext, mac: &ast::Mac) {

`

``

1847

`+

self.check_tokens(cx, mac.node.tts.clone().into());

`

``

1848

`+

}

`

``

1849

`+

fn check_ident(&mut self, cx: &EarlyContext, ident: ast::Ident) {

`

``

1850

`+

if ident.as_str() == "async" {

`

``

1851

`+

self.report(cx, ident.span);

`

``

1852

`+

}

`

``

1853

`+

}

`

``

1854

`+

}

`