1
1
//! Lsif generator
2
2
3
+ use std:: collections:: HashMap ;
3
4
use std:: env;
4
5
use std:: time:: Instant ;
5
6
6
- use ide:: { StaticIndex , StaticIndexedFile , TokenStaticData } ;
7
+ use ide:: { Analysis , Cancellable , RootDatabase , StaticIndex , StaticIndexedFile , TokenId , TokenStaticData } ;
7
8
use ide_db:: LineIndexDatabase ;
8
9
9
10
use ide_db:: base_db:: salsa:: { self , ParallelDatabase } ;
10
11
use lsp_types:: { lsif:: * , Hover , HoverContents , NumberOrString } ;
11
12
use project_model:: { CargoConfig , ProjectManifest , ProjectWorkspace } ;
12
- use vfs:: AbsPathBuf ;
13
+ use vfs:: { AbsPathBuf , Vfs } ;
13
14
14
15
use crate :: cli:: {
15
16
flags,
@@ -27,9 +28,12 @@ impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> {
27
28
}
28
29
}
29
30
30
- #[ derive( Default ) ]
31
- struct LsifManager {
31
+ struct LsifManager < ' a > {
32
32
count : i32 ,
33
+ token_map : HashMap < TokenId , Id > ,
34
+ analysis : & ' a Analysis ,
35
+ db : & ' a RootDatabase ,
36
+ vfs : & ' a Vfs ,
33
37
}
34
38
35
39
#[ derive( Clone , Copy ) ]
@@ -41,7 +45,17 @@ impl From<Id> for NumberOrString {
41
45
}
42
46
}
43
47
44
- impl LsifManager {
48
+ impl LsifManager < ' _ > {
49
+ fn new < ' a > ( analysis : & ' a Analysis , db : & ' a RootDatabase , vfs : & ' a Vfs ) -> LsifManager < ' a > {
50
+ LsifManager {
51
+ count : 0 ,
52
+ token_map : HashMap :: default ( ) ,
53
+ analysis,
54
+ db,
55
+ vfs,
56
+ }
57
+ }
58
+
45
59
fn add ( & mut self , data : Element ) -> Id {
46
60
let id = Id ( self . count ) ;
47
61
self . emit ( & serde_json:: to_string ( & Entry { id : id. into ( ) , data } ) . unwrap ( ) ) ;
@@ -54,33 +68,67 @@ impl LsifManager {
54
68
println ! ( "{}" , data) ;
55
69
}
56
70
57
- fn add_tokens ( & mut self , line_index : & LineIndex , doc_id : Id , tokens : Vec < TokenStaticData > ) {
71
+ fn add_token ( & mut self , id : TokenId , token : TokenStaticData ) {
72
+ let result_set_id = self . add ( Element :: Vertex ( Vertex :: ResultSet ( ResultSet { key : None } ) ) ) ;
73
+ self . token_map . insert ( id, result_set_id) ;
74
+ if let Some ( hover) = token. hover {
75
+ let hover_id = self . add ( Element :: Vertex ( Vertex :: HoverResult {
76
+ result : Hover {
77
+ contents : HoverContents :: Markup ( to_proto:: markup_content ( hover. markup ) ) ,
78
+ range : None ,
79
+ } ,
80
+ } ) ) ;
81
+ self . add ( Element :: Edge ( Edge :: Hover ( EdgeData {
82
+ in_v : hover_id. into ( ) ,
83
+ out_v : result_set_id. into ( ) ,
84
+ } ) ) ) ;
85
+ }
86
+ }
87
+
88
+ fn add_file ( & mut self , file : StaticIndexedFile ) -> Cancellable < ( ) > {
89
+ let StaticIndexedFile { file_id, tokens, folds} = file;
90
+ let path = self . vfs . file_path ( file_id) ;
91
+ let path = path. as_path ( ) . unwrap ( ) ;
92
+ let doc_id = self . add ( Element :: Vertex ( Vertex :: Document ( Document {
93
+ language_id : "rust" . to_string ( ) ,
94
+ uri : lsp_types:: Url :: from_file_path ( path) . unwrap ( ) ,
95
+ } ) ) ) ;
96
+ let text = self . analysis . file_text ( file_id) ?;
97
+ let line_index = self . db . line_index ( file_id) ;
98
+ let line_index = LineIndex {
99
+ index : line_index. clone ( ) ,
100
+ encoding : OffsetEncoding :: Utf16 ,
101
+ endings : LineEndings :: Unix ,
102
+ } ;
103
+ let result = folds
104
+ . into_iter ( )
105
+ . map ( |it| to_proto:: folding_range ( & * text, & line_index, false , it) )
106
+ . collect ( ) ;
107
+ let folding_id = self . add ( Element :: Vertex ( Vertex :: FoldingRangeResult { result } ) ) ;
108
+ self . add ( Element :: Edge ( Edge :: FoldingRange ( EdgeData {
109
+ in_v : folding_id. into ( ) ,
110
+ out_v : doc_id. into ( ) ,
111
+ } ) ) ) ;
58
112
let tokens_id = tokens
59
113
. into_iter ( )
60
- . map ( |token | {
61
- let token_id = self . add ( Element :: Vertex ( Vertex :: Range {
62
- range : to_proto:: range ( line_index, token . range ) ,
114
+ . map ( |( range , id ) | {
115
+ let range_id = self . add ( Element :: Vertex ( Vertex :: Range {
116
+ range : to_proto:: range ( & line_index, range) ,
63
117
tag : None ,
64
118
} ) ) ;
65
- if let Some ( hover) = token. hover {
66
- let hover_id = self . add ( Element :: Vertex ( Vertex :: HoverResult {
67
- result : Hover {
68
- contents : HoverContents :: Markup ( to_proto:: markup_content ( hover. markup ) ) ,
69
- range : None ,
70
- } ,
71
- } ) ) ;
72
- self . add ( Element :: Edge ( Edge :: Hover ( EdgeData {
73
- in_v : hover_id. into ( ) ,
74
- out_v : token_id. into ( ) ,
75
- } ) ) ) ;
76
- }
77
- token_id. into ( )
119
+ let result_set_id = * self . token_map . get ( & id) . expect ( "token map doesn't contain id" ) ;
120
+ self . add ( Element :: Edge ( Edge :: Next ( EdgeData {
121
+ in_v : result_set_id. into ( ) ,
122
+ out_v : range_id. into ( ) ,
123
+ } ) ) ) ;
124
+ range_id. into ( )
78
125
} )
79
126
. collect ( ) ;
80
127
self . add ( Element :: Edge ( Edge :: Contains ( EdgeDataMultiIn {
81
128
in_vs : tokens_id,
82
129
out_v : doc_id. into ( ) ,
83
130
} ) ) ) ;
131
+ Ok ( ( ) )
84
132
}
85
133
}
86
134
@@ -106,37 +154,18 @@ impl flags::Lsif {
106
154
107
155
let si = StaticIndex :: compute ( db, & analysis) ?;
108
156
109
- let mut lsif = LsifManager :: default ( ) ;
157
+ let mut lsif = LsifManager :: new ( & analysis , db , & vfs ) ;
110
158
lsif. add ( Element :: Vertex ( Vertex :: MetaData ( MetaData {
111
159
version : String :: from ( "0.5.0" ) ,
112
160
project_root : lsp_types:: Url :: from_file_path ( path) . unwrap ( ) ,
113
161
position_encoding : Encoding :: Utf16 ,
114
162
tool_info : None ,
115
163
} ) ) ) ;
116
- for StaticIndexedFile { file_id, folds, tokens } in si. files {
117
- let path = vfs. file_path ( file_id) ;
118
- let path = path. as_path ( ) . unwrap ( ) ;
119
- let doc_id = lsif. add ( Element :: Vertex ( Vertex :: Document ( Document {
120
- language_id : "rust" . to_string ( ) ,
121
- uri : lsp_types:: Url :: from_file_path ( path) . unwrap ( ) ,
122
- } ) ) ) ;
123
- let text = analysis. file_text ( file_id) ?;
124
- let line_index = db. line_index ( file_id) ;
125
- let line_index = LineIndex {
126
- index : line_index. clone ( ) ,
127
- encoding : OffsetEncoding :: Utf16 ,
128
- endings : LineEndings :: Unix ,
129
- } ;
130
- let result = folds
131
- . into_iter ( )
132
- . map ( |it| to_proto:: folding_range ( & * text, & line_index, false , it) )
133
- . collect ( ) ;
134
- let folding_id = lsif. add ( Element :: Vertex ( Vertex :: FoldingRangeResult { result } ) ) ;
135
- lsif. add ( Element :: Edge ( Edge :: FoldingRange ( EdgeData {
136
- in_v : folding_id. into ( ) ,
137
- out_v : doc_id. into ( ) ,
138
- } ) ) ) ;
139
- lsif. add_tokens ( & line_index, doc_id, tokens) ;
164
+ for ( id, token) in si. tokens . iter ( ) {
165
+ lsif. add_token ( id, token) ;
166
+ }
167
+ for file in si. files {
168
+ lsif. add_file ( file) ?;
140
169
}
141
170
eprintln ! ( "Generating LSIF finished in {:?}" , now. elapsed( ) ) ;
142
171
Ok ( ( ) )
0 commit comments