@@ -3,6 +3,7 @@ use hir::{
3
3
AsAssocItem , AssocItemContainer , GenericParam , HasAttrs , HasSource , HirDisplay , InFile , Module ,
4
4
ModuleDef , Semantics ,
5
5
} ;
6
+ use ide_completion:: generated_lint_completions:: { CLIPPY_LINTS , FEATURES } ;
6
7
use ide_db:: {
7
8
base_db:: SourceDatabase ,
8
9
defs:: { Definition , NameClass , NameRefClass } ,
@@ -11,7 +12,10 @@ use ide_db::{
11
12
} ;
12
13
use itertools:: Itertools ;
13
14
use stdx:: format_to;
14
- use syntax:: { ast, match_ast, AstNode , AstToken , SyntaxKind :: * , SyntaxToken , TokenAtOffset , T } ;
15
+ use syntax:: {
16
+ algo, ast, match_ast, AstNode , AstToken , Direction , SyntaxKind :: * , SyntaxToken , TokenAtOffset ,
17
+ T ,
18
+ } ;
15
19
16
20
use crate :: {
17
21
display:: { macro_label, TryToNav } ,
@@ -115,8 +119,8 @@ pub(crate) fn hover(
115
119
|d| d. defined( db) ,
116
120
) ,
117
121
118
- _ => ast :: Comment :: cast ( token . clone ( ) )
119
- . and_then ( |_| {
122
+ _ => {
123
+ if ast :: Comment :: cast ( token . clone ( ) ) . is_some ( ) {
120
124
let ( attributes, def) = doc_attributes( & sema, & node) ?;
121
125
let ( docs, doc_mapping) = attributes. docs_with_rangemap( db) ?;
122
126
let ( idl_range, link, ns) =
@@ -129,9 +133,11 @@ pub(crate) fn hover(
129
133
}
130
134
} ) ?;
131
135
range = Some ( idl_range) ;
132
- resolve_doc_path_for_def( db, def, & link, ns)
133
- } )
134
- . map( Definition :: ModuleDef ) ,
136
+ resolve_doc_path_for_def( db, def, & link, ns) . map( Definition :: ModuleDef )
137
+ } else {
138
+ return try_hover_for_attribute( & token) ;
139
+ }
140
+ } ,
135
141
}
136
142
} ;
137
143
@@ -194,6 +200,40 @@ pub(crate) fn hover(
194
200
Some ( RangeInfo :: new ( range, res) )
195
201
}
196
202
203
+ fn try_hover_for_attribute ( token : & SyntaxToken ) -> Option < RangeInfo < HoverResult > > {
204
+ let attr = token. ancestors ( ) . nth ( 1 ) . and_then ( ast:: Attr :: cast) ?;
205
+ let ( path, tt) = attr. as_simple_call ( ) ?;
206
+ if !tt. syntax ( ) . text_range ( ) . contains ( token. text_range ( ) . start ( ) ) {
207
+ return None ;
208
+ }
209
+ let lints = match & * path {
210
+ "feature" => FEATURES ,
211
+ "allow" | "warn" | "forbid" | "error" => {
212
+ let is_clippy = algo:: skip_trivia_token ( token. clone ( ) , Direction :: Prev )
213
+ . filter ( |t| t. kind ( ) == T ! [ :: ] )
214
+ . and_then ( |t| algo:: skip_trivia_token ( t, Direction :: Prev ) )
215
+ . map_or ( false , |t| t. kind ( ) == T ! [ ident] && t. text ( ) == "clippy" ) ;
216
+ if is_clippy {
217
+ CLIPPY_LINTS
218
+ } else {
219
+ & [ ]
220
+ }
221
+ }
222
+ _ => return None ,
223
+ } ;
224
+ let lint = lints
225
+ . binary_search_by_key ( & token. text ( ) , |lint| lint. label )
226
+ . ok ( )
227
+ . map ( |idx| & FEATURES [ idx] ) ?;
228
+ Some ( RangeInfo :: new (
229
+ token. text_range ( ) ,
230
+ HoverResult {
231
+ markup : Markup :: from ( format ! ( "```\n {}\n ```\n ___\n \n {}" , lint. label, lint. description) ) ,
232
+ ..Default :: default ( )
233
+ } ,
234
+ ) )
235
+ }
236
+
197
237
fn show_implementations_action ( db : & RootDatabase , def : Definition ) -> Option < HoverAction > {
198
238
fn to_action ( nav_target : NavigationTarget ) -> HoverAction {
199
239
HoverAction :: Implementation ( FilePosition {
@@ -3977,4 +4017,42 @@ pub fn foo() {}
3977
4017
"# ] ] ,
3978
4018
)
3979
4019
}
4020
+
4021
+ #[ test]
4022
+ fn hover_feature ( ) {
4023
+ check (
4024
+ r#"#![feature(box_syntax$0)]"# ,
4025
+ expect ! [ [ r##"
4026
+ *box_syntax*
4027
+ ```
4028
+ box_syntax
4029
+ ```
4030
+ ___
4031
+
4032
+ # `box_syntax`
4033
+
4034
+ The tracking issue for this feature is: [#49733]
4035
+
4036
+ [#49733]: https://github.com/rust-lang/rust/issues/49733
4037
+
4038
+ See also [`box_patterns`](box-patterns.md)
4039
+
4040
+ ------------------------
4041
+
4042
+ Currently the only stable way to create a `Box` is via the `Box::new` method.
4043
+ Also it is not possible in stable Rust to destructure a `Box` in a match
4044
+ pattern. The unstable `box` keyword can be used to create a `Box`. An example
4045
+ usage would be:
4046
+
4047
+ ```rust
4048
+ #![feature(box_syntax)]
4049
+
4050
+ fn main() {
4051
+ let b = box 5;
4052
+ }
4053
+ ```
4054
+
4055
+ "## ] ] ,
4056
+ )
4057
+ }
3980
4058
}
0 commit comments