@@ -13,7 +13,7 @@ use tree_sitter::{Query, QueryCursor};
1313use xmlparser:: { Token , Tokenizer } ;
1414
1515use crate :: format_loc;
16- use crate :: model:: { Model , ModelIndex } ;
16+ use crate :: model:: { Model , ModelId , ModelIndex } ;
1717use crate :: record:: Record ;
1818use crate :: utils:: { offset_range_to_lsp_range, ByteOffset , CharOffset , ImStr , RangeExt } ;
1919
@@ -185,7 +185,7 @@ impl ModuleIndex {
185185}
186186
187187async fn add_root_xml ( path : PathBuf , module_name : ImStr ) -> miette:: Result < Output > {
188- let path_uri = path. to_string_lossy ( ) ;
188+ let uri : Url = format ! ( "file://{}" , path. to_string_lossy( ) ) . parse ( ) . into_diagnostic ( ) ? ;
189189 let file = tokio:: fs:: read ( & path)
190190 . await
191191 . into_diagnostic ( )
@@ -201,7 +201,7 @@ async fn add_root_xml(path: PathBuf, module_name: ImStr) -> miette::Result<Outpu
201201 let record = Record :: from_reader (
202202 CharOffset ( span. start ( ) ) ,
203203 module_name. clone ( ) ,
204- & path_uri ,
204+ uri . clone ( ) ,
205205 & mut reader,
206206 rope. clone ( ) ,
207207 ) ?;
@@ -210,7 +210,7 @@ async fn add_root_xml(path: PathBuf, module_name: ImStr) -> miette::Result<Outpu
210210 let template = Record :: template (
211211 CharOffset ( span. start ( ) ) ,
212212 module_name. clone ( ) ,
213- & path_uri ,
213+ uri . clone ( ) ,
214214 & mut reader,
215215 rope. clone ( ) ,
216216 ) ?;
@@ -238,72 +238,62 @@ fn model_query() -> &'static Query {
238238}
239239
240240async fn add_root_py ( path : PathBuf , _: ImStr ) -> miette:: Result < Output > {
241- let file = tokio:: fs:: read ( & path)
241+ let contents = tokio:: fs:: read ( & path)
242242 . await
243243 . into_diagnostic ( )
244244 . with_context ( || format_loc ! ( "Could not read {}" , path. display( ) ) ) ?;
245245
246246 let mut parser = tree_sitter:: Parser :: new ( ) ;
247247 parser. set_language ( tree_sitter_python:: language ( ) ) . into_diagnostic ( ) ?;
248248
249- let ast = parser. parse ( & file, None ) . ok_or_else ( || diagnostic ! ( "AST not parsed" ) ) ?;
249+ let ast = parser
250+ . parse ( & contents, None )
251+ . ok_or_else ( || diagnostic ! ( "AST not parsed" ) ) ?;
250252 let query = model_query ( ) ;
251253 let mut cursor = QueryCursor :: new ( ) ;
252254
253255 let mut out = vec ! [ ] ;
254- let rope = Rope :: from_str ( & String :: from_utf8_lossy ( & file) ) ;
255- let eq_slice = |range : std:: ops:: Range < usize > , slice : & [ u8 ] | & file[ range] == slice;
256- for match_ in cursor. matches ( query, ast. root_node ( ) , file. as_slice ( ) ) {
257- let mut captures = match_. captures ;
258- let tail = match captures {
259- [ models, _, tail @ ..] if eq_slice ( models. node . byte_range ( ) , b"models" ) => tail,
260- [ _model, tail @ ..] => {
261- debug_assert ! ( matches!( & file[ _model. node. byte_range( ) ] , b"Model" | b"TransientModel" ) ) ;
262- tail
263- }
264- unk => Err ( diagnostic ! (
265- "Bug: Unknown pattern {:?}" ,
266- unk. iter( )
267- . map( |capture| String :: from_utf8_lossy( & file[ capture. node. byte_range( ) ] ) )
268- . collect:: <Vec <_>>( )
269- ) ) ?,
270- } ;
271- captures = tail;
272- let mut model = None ;
273- while !captures. is_empty ( ) {
274- match captures {
275- [ _name, name, tail @ ..] if eq_slice ( _name. node . byte_range ( ) , b"_name" ) => {
276- captures = tail;
277- let name = name. node . byte_range ( ) . contract ( 1 ) ;
278- if name. is_empty ( ) {
279- break ;
280- }
281- model = Some ( Model {
282- model : String :: from_utf8_lossy ( & file[ name. clone ( ) ] ) . to_string ( ) ,
283- range : offset_range_to_lsp_range ( name. map_unit ( ByteOffset ) , rope. clone ( ) )
284- . ok_or_else ( || diagnostic ! ( "name range" ) ) ?,
285- inherit : false ,
286- } ) ;
256+ let rope = Rope :: from_str ( & String :: from_utf8_lossy ( & contents) ) ;
257+ ' match_: for match_ in cursor. matches ( query, ast. root_node ( ) , contents. as_slice ( ) ) {
258+ let mut inherits = vec ! [ ] ;
259+ let mut range = None ;
260+ let mut maybe_base = None ;
261+ for capture in match_. captures {
262+ if capture. index == 3 && maybe_base. is_none ( ) {
263+ // @name
264+ let name = capture. node . byte_range ( ) . contract ( 1 ) ;
265+ if name. is_empty ( ) {
266+ continue ' match_;
287267 }
288- [ _inherit, inherit, tail @ ..] if eq_slice ( _inherit. node . byte_range ( ) , b"_inherit" ) => {
289- captures = tail;
290- let inherit = inherit. node . byte_range ( ) . contract ( 1 ) ;
291- if inherit. is_empty ( ) {
292- continue ;
293- }
294- if model. is_none ( ) {
295- model = Some ( Model {
296- model : String :: from_utf8_lossy ( & file[ inherit. clone ( ) ] ) . to_string ( ) ,
297- range : offset_range_to_lsp_range ( inherit. map_unit ( ByteOffset ) , rope. clone ( ) )
298- . ok_or_else ( || diagnostic ! ( "inherit range" ) ) ?,
299- inherit : true ,
300- } ) ;
301- }
268+ maybe_base = Some ( String :: from_utf8_lossy ( & contents[ name] ) ) ;
269+ } else if capture. index == 5 {
270+ // @inherit
271+ let inherit = capture. node . byte_range ( ) . contract ( 1 ) ;
272+ if !inherit. is_empty ( ) {
273+ inherits. push ( ImStr :: from ( String :: from_utf8_lossy ( & contents[ inherit] ) . as_ref ( ) ) ) ;
302274 }
303- unk => Err ( diagnostic ! ( "Bug: Leftover captures: {unk:?}" ) ) ?,
275+ } else if capture. index == 6 {
276+ // @model
277+ range = Some ( capture. node . byte_range ( ) ) ;
304278 }
305279 }
306- out. extend ( model) ;
280+ let range = offset_range_to_lsp_range ( range. unwrap ( ) . map_unit ( ByteOffset ) , rope. clone ( ) )
281+ . ok_or_else ( || diagnostic ! ( "model range" ) ) ?;
282+ match ( inherits. as_slice ( ) , maybe_base) {
283+ ( [ single] , Some ( base) ) if base. as_ref ( ) == single => out. push ( Model {
284+ model : ModelId :: Inherit ( inherits. into_boxed_slice ( ) ) ,
285+ range,
286+ } ) ,
287+ ( _, None ) if !inherits. is_empty ( ) => out. push ( Model {
288+ model : ModelId :: Inherit ( inherits. into_boxed_slice ( ) ) ,
289+ range,
290+ } ) ,
291+ ( _, Some ( base) ) => out. push ( Model {
292+ model : ModelId :: Base ( base. as_ref ( ) . into ( ) ) ,
293+ range,
294+ } ) ,
295+ _ => { }
296+ }
307297 }
308298
309299 Ok ( Output :: Models {
0 commit comments