@@ -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
+ }
0 commit comments