Coverage Report

Created: 2026-07-19 07:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wit-parser/src/ast.rs
Line
Count
Source
1
use crate::ast::error::ParseError;
2
use crate::{ParseResult, UnresolvedPackage, UnresolvedPackageGroup};
3
use alloc::borrow::Cow;
4
use alloc::boxed::Box;
5
use alloc::format;
6
use alloc::string::{String, ToString};
7
use alloc::vec::Vec;
8
#[cfg(feature = "std")]
9
use anyhow::Context as _;
10
use core::fmt;
11
use core::mem;
12
use core::result::Result;
13
use lex::{Span, Token, Tokenizer};
14
use semver::Version;
15
#[cfg(feature = "std")]
16
use std::path::Path;
17
18
pub mod error;
19
pub mod lex;
20
21
pub use resolve::Resolver;
22
mod resolve;
23
pub mod toposort;
24
25
pub use lex::validate_id;
26
27
/// Representation of a single WIT `*.wit` file and nested packages.
28
struct PackageFile<'a> {
29
    /// Optional `package foo:bar;` header
30
    package_id: Option<PackageName<'a>>,
31
    /// Other AST items.
32
    decl_list: DeclList<'a>,
33
}
34
35
/// Maximum nesting depth of `package { ... }` scopes.
36
const MAX_ITEM_DEPTH: usize = 100;
37
38
impl<'a> PackageFile<'a> {
39
    /// Parse a standalone file represented by `tokens`.
40
    ///
41
    /// This will optionally start with `package foo:bar;` and then will have a
42
    /// list of ast items after it.
43
16.9k
    fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
44
16.9k
        let mut package_name_tokens_peek = tokens.clone();
45
16.9k
        let docs = parse_docs(&mut package_name_tokens_peek)?;
46
47
        // Parse `package foo:bar;` but throw it out if it's actually
48
        // `package foo:bar { ... }` since that's an ast item instead.
49
16.9k
        let package_id = if package_name_tokens_peek.eat(Token::Package)? {
50
12.9k
            let name = PackageName::parse(&mut package_name_tokens_peek, docs)?;
51
12.9k
            if package_name_tokens_peek.eat(Token::Semicolon)? {
52
12.9k
                *tokens = package_name_tokens_peek;
53
12.9k
                Some(name)
54
            } else {
55
0
                None
56
            }
57
        } else {
58
3.99k
            None
59
        };
60
16.9k
        let decl_list = DeclList::parse_until(tokens, None, 0)?;
61
16.9k
        Ok(PackageFile {
62
16.9k
            package_id,
63
16.9k
            decl_list,
64
16.9k
        })
65
16.9k
    }
66
67
    /// Parse a nested package of the form `package foo:bar { ... }`
68
620
    fn parse_nested(
69
620
        tokens: &mut Tokenizer<'a>,
70
620
        docs: Docs<'a>,
71
620
        attributes: Vec<Attribute<'a>>,
72
620
        depth: usize,
73
620
    ) -> ParseResult<Self> {
74
620
        let span = tokens.expect(Token::Package)?;
75
620
        if !attributes.is_empty() {
76
0
            return Err(ParseError::new_syntax(
77
0
                span,
78
0
                format!("cannot place attributes on nested packages"),
79
0
            ));
80
620
        }
81
620
        if depth >= MAX_ITEM_DEPTH {
82
0
            return Err(ParseError::new_syntax(span, "package nesting too deep"));
83
620
        }
84
620
        let package_id = PackageName::parse(tokens, docs)?;
85
620
        tokens.expect(Token::LeftBrace)?;
86
620
        let decl_list = DeclList::parse_until(tokens, Some(Token::RightBrace), depth + 1)?;
87
620
        Ok(PackageFile {
88
620
            package_id: Some(package_id),
89
620
            decl_list,
90
620
        })
91
620
    }
92
}
93
94
/// Stores all of the declarations in a package's scope. In AST terms, this
95
/// means everything except the `package` declaration that demarcates a package
96
/// scope. In the traditional implicit format, these are all of the declarations
97
/// non-`package` declarations in the file:
98
///
99
/// ```wit
100
/// package foo:name;
101
///
102
/// /* START DECL LIST */
103
/// // Some comment...
104
/// interface i {}
105
/// world w {}
106
/// /* END DECL LIST */
107
/// ```
108
///
109
/// In the nested package style, a [`DeclList`] is everything inside of each
110
/// `package` element's brackets:
111
///
112
/// ```wit
113
/// package foo:name {
114
///   /* START FIRST DECL LIST */
115
///   // Some comment...
116
///   interface i {}
117
///   world w {}
118
///   /* END FIRST DECL LIST */
119
/// }
120
///
121
/// package bar:name {
122
///   /* START SECOND DECL LIST */
123
///   // Some comment...
124
///   interface i {}
125
///   world w {}
126
///   /* END SECOND DECL LIST */
127
/// }
128
/// ```
129
#[derive(Default)]
130
pub struct DeclList<'a> {
131
    items: Vec<AstItem<'a>>,
132
}
133
134
impl<'a> DeclList<'a> {
135
17.5k
    fn parse_until(
136
17.5k
        tokens: &mut Tokenizer<'a>,
137
17.5k
        end: Option<Token>,
138
17.5k
        depth: usize,
139
17.5k
    ) -> ParseResult<DeclList<'a>> {
140
17.5k
        let mut items = Vec::new();
141
17.5k
        let mut docs = parse_docs(tokens)?;
142
        loop {
143
75.5k
            match end {
144
1.45k
                Some(end) => {
145
1.45k
                    if tokens.eat(end)? {
146
620
                        break;
147
832
                    }
148
                }
149
                None => {
150
74.1k
                    if tokens.clone().next()?.is_none() {
151
16.9k
                        break;
152
57.1k
                    }
153
                }
154
            }
155
57.9k
            items.push(AstItem::parse(tokens, docs, depth)?);
156
57.9k
            docs = parse_docs(tokens)?;
157
        }
158
17.5k
        Ok(DeclList { items })
159
17.5k
    }
160
161
52.7k
    fn for_each_path<'b>(
162
52.7k
        &'b self,
163
52.7k
        f: &mut dyn FnMut(
164
52.7k
            Option<&'b Id<'a>>,
165
52.7k
            &'b [Attribute<'a>],
166
52.7k
            &'b UsePath<'a>,
167
52.7k
            Option<&'b [UseName<'a>]>,
168
52.7k
            WorldOrInterface,
169
52.7k
        ) -> ParseResult<()>,
170
52.7k
    ) -> ParseResult<()> {
171
172k
        for item in self.items.iter() {
172
172k
            match item {
173
40.7k
                AstItem::World(world) => {
174
                    // Visit imports here first before exports to help preserve
175
                    // round-tripping of documents because printing a world puts
176
                    // imports first but textually they can be listed with
177
                    // exports first.
178
40.7k
                    let mut imports = Vec::new();
179
40.7k
                    let mut exports = Vec::new();
180
80.8k
                    for item in world.items.iter() {
181
80.8k
                        match item {
182
1.73k
                            WorldItem::Use(u) => f(
183
1.73k
                                None,
184
1.73k
                                &u.attributes,
185
1.73k
                                &u.from,
186
1.73k
                                Some(&u.names),
187
1.73k
                                WorldOrInterface::Interface,
188
1.73k
                            )?,
189
0
                            WorldItem::Include(i) => f(
190
0
                                Some(&world.name),
191
0
                                &i.attributes,
192
0
                                &i.from,
193
0
                                None,
194
0
                                WorldOrInterface::World,
195
0
                            )?,
196
19.4k
                            WorldItem::Type(_) => {}
197
                            WorldItem::Import(Import {
198
11.9k
                                kind, attributes, ..
199
11.9k
                            }) => imports.push((kind, attributes)),
200
                            WorldItem::Export(Export {
201
47.6k
                                kind, attributes, ..
202
47.6k
                            }) => exports.push((kind, attributes)),
203
                        }
204
                    }
205
206
40.7k
                    let mut visit_kind =
207
59.6k
                        |kind: &'b ExternKind<'a>, attrs: &'b [Attribute<'a>]| match kind {
208
4.01k
                            ExternKind::Interface(_, items) => {
209
10.6k
                                for item in items {
210
10.6k
                                    match item {
211
1.43k
                                        InterfaceItem::Use(u) => f(
212
1.43k
                                            None,
213
1.43k
                                            &u.attributes,
214
1.43k
                                            &u.from,
215
1.43k
                                            Some(&u.names),
216
1.43k
                                            WorldOrInterface::Interface,
217
1.43k
                                        )?,
218
9.18k
                                        _ => {}
219
                                    }
220
                                }
221
4.01k
                                Ok(())
222
                            }
223
43.8k
                            ExternKind::Path(path) | ExternKind::NamedPath(_, path) => {
224
46.1k
                                f(None, attrs, path, None, WorldOrInterface::Interface)
225
                            }
226
9.41k
                            ExternKind::Func(..) => Ok(()),
227
59.6k
                        };
228
229
40.7k
                    for (kind, attrs) in imports {
230
11.9k
                        visit_kind(kind, attrs)?;
231
                    }
232
47.6k
                    for (kind, attrs) in exports {
233
47.6k
                        visit_kind(kind, attrs)?;
234
                    }
235
                }
236
122k
                AstItem::Interface(i) => {
237
139k
                    for item in i.items.iter() {
238
139k
                        match item {
239
57.2k
                            InterfaceItem::Use(u) => f(
240
57.2k
                                Some(&i.name),
241
57.2k
                                &u.attributes,
242
57.2k
                                &u.from,
243
57.2k
                                Some(&u.names),
244
57.2k
                                WorldOrInterface::Interface,
245
57.2k
                            )?,
246
82.0k
                            _ => {}
247
                        }
248
                    }
249
                }
250
8.52k
                AstItem::Use(u) => {
251
                    // At the top-level, we don't know if this is a world or an interface
252
                    // It is up to the resolver to decides how to handle this ambiguity.
253
8.52k
                    f(
254
8.52k
                        None,
255
8.52k
                        &u.attributes,
256
8.52k
                        &u.item,
257
8.52k
                        None,
258
8.52k
                        WorldOrInterface::Unknown,
259
8.52k
                    )?;
260
                }
261
262
0
                AstItem::Package(pkg) => pkg.decl_list.for_each_path(f)?,
263
            }
264
        }
265
52.7k
        Ok(())
266
52.7k
    }
267
}
268
269
enum AstItem<'a> {
270
    Interface(Interface<'a>),
271
    World(World<'a>),
272
    Use(ToplevelUse<'a>),
273
    Package(PackageFile<'a>),
274
}
275
276
impl<'a> AstItem<'a> {
277
57.9k
    fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>, depth: usize) -> ParseResult<Self> {
278
57.9k
        let attributes = Attribute::parse_list(tokens)?;
279
57.9k
        match tokens.clone().next()? {
280
40.9k
            Some((_span, Token::Interface)) => {
281
40.9k
                Interface::parse(tokens, docs, attributes).map(Self::Interface)
282
            }
283
13.5k
            Some((_span, Token::World)) => World::parse(tokens, docs, attributes).map(Self::World),
284
2.84k
            Some((_span, Token::Use)) => ToplevelUse::parse(tokens, attributes).map(Self::Use),
285
620
            Some((_span, Token::Package)) => {
286
620
                PackageFile::parse_nested(tokens, docs, attributes, depth).map(Self::Package)
287
            }
288
0
            other => Err(err_expected(tokens, "`world`, `interface` or `use`", other).into()),
289
        }
290
57.9k
    }
291
}
292
293
#[derive(Debug, Clone)]
294
struct PackageName<'a> {
295
    docs: Docs<'a>,
296
    span: Span,
297
    namespace: Id<'a>,
298
    name: Id<'a>,
299
    version: Option<(Span, Version)>,
300
}
301
302
impl<'a> PackageName<'a> {
303
13.5k
    fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> ParseResult<Self> {
304
13.5k
        let namespace = parse_id(tokens)?;
305
13.5k
        tokens.expect(Token::Colon)?;
306
13.5k
        let name = parse_id(tokens)?;
307
13.5k
        let version = parse_opt_version(tokens)?;
308
        Ok(PackageName {
309
13.5k
            docs,
310
13.5k
            span: Span::new(
311
13.5k
                namespace.span.start(),
312
13.5k
                version
313
13.5k
                    .as_ref()
314
13.5k
                    .map(|(s, _)| s.end())
315
13.5k
                    .unwrap_or(name.span.end()),
316
            ),
317
13.5k
            namespace,
318
13.5k
            name,
319
13.5k
            version,
320
        })
321
13.5k
    }
322
323
85.1k
    fn package_name(&self) -> crate::PackageName {
324
        crate::PackageName {
325
85.1k
            namespace: self.namespace.name.to_string(),
326
85.1k
            name: self.name.name.to_string(),
327
85.1k
            version: self.version.as_ref().map(|(_, v)| v.clone()),
328
        }
329
85.1k
    }
330
}
331
332
struct ToplevelUse<'a> {
333
    span: Span,
334
    attributes: Vec<Attribute<'a>>,
335
    item: UsePath<'a>,
336
    as_: Option<Id<'a>>,
337
}
338
339
impl<'a> ToplevelUse<'a> {
340
2.84k
    fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
341
2.84k
        let span = tokens.expect(Token::Use)?;
342
2.84k
        let item = UsePath::parse(tokens)?;
343
2.84k
        let as_ = if tokens.eat(Token::As)? {
344
2.58k
            Some(parse_id(tokens)?)
345
        } else {
346
253
            None
347
        };
348
2.84k
        tokens.expect_semicolon()?;
349
2.84k
        Ok(ToplevelUse {
350
2.84k
            span,
351
2.84k
            attributes,
352
2.84k
            item,
353
2.84k
            as_,
354
2.84k
        })
355
2.84k
    }
356
}
357
358
struct World<'a> {
359
    docs: Docs<'a>,
360
    attributes: Vec<Attribute<'a>>,
361
    name: Id<'a>,
362
    items: Vec<WorldItem<'a>>,
363
}
364
365
impl<'a> World<'a> {
366
13.5k
    fn parse(
367
13.5k
        tokens: &mut Tokenizer<'a>,
368
13.5k
        docs: Docs<'a>,
369
13.5k
        attributes: Vec<Attribute<'a>>,
370
13.5k
    ) -> ParseResult<Self> {
371
13.5k
        tokens.expect(Token::World)?;
372
13.5k
        let name = parse_id(tokens)?;
373
13.5k
        let items = Self::parse_items(tokens)?;
374
13.5k
        Ok(World {
375
13.5k
            docs,
376
13.5k
            attributes,
377
13.5k
            name,
378
13.5k
            items,
379
13.5k
        })
380
13.5k
    }
381
382
13.5k
    fn parse_items(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<WorldItem<'a>>> {
383
13.5k
        tokens.expect(Token::LeftBrace)?;
384
13.5k
        let mut items = Vec::new();
385
        loop {
386
40.5k
            let docs = parse_docs(tokens)?;
387
40.5k
            if tokens.eat(Token::RightBrace)? {
388
13.5k
                break;
389
26.9k
            }
390
26.9k
            let attributes = Attribute::parse_list(tokens)?;
391
26.9k
            items.push(WorldItem::parse(tokens, docs, attributes)?);
392
        }
393
13.5k
        Ok(items)
394
13.5k
    }
395
}
396
397
enum WorldItem<'a> {
398
    Import(Import<'a>),
399
    Export(Export<'a>),
400
    Use(Use<'a>),
401
    Type(TypeDef<'a>),
402
    Include(Include<'a>),
403
}
404
405
impl<'a> WorldItem<'a> {
406
26.9k
    fn parse(
407
26.9k
        tokens: &mut Tokenizer<'a>,
408
26.9k
        docs: Docs<'a>,
409
26.9k
        attributes: Vec<Attribute<'a>>,
410
26.9k
    ) -> ParseResult<WorldItem<'a>> {
411
26.9k
        match tokens.clone().next()? {
412
3.99k
            Some((_span, Token::Import)) => {
413
3.99k
                Import::parse(tokens, docs, attributes).map(WorldItem::Import)
414
            }
415
15.8k
            Some((_span, Token::Export)) => {
416
15.8k
                Export::parse(tokens, docs, attributes).map(WorldItem::Export)
417
            }
418
578
            Some((_span, Token::Use)) => Use::parse(tokens, attributes).map(WorldItem::Use),
419
1.06k
            Some((_span, Token::Type)) => {
420
1.06k
                TypeDef::parse(tokens, docs, attributes).map(WorldItem::Type)
421
            }
422
242
            Some((_span, Token::Flags)) => {
423
242
                TypeDef::parse_flags(tokens, docs, attributes).map(WorldItem::Type)
424
            }
425
487
            Some((_span, Token::Resource)) => {
426
487
                TypeDef::parse_resource(tokens, docs, attributes).map(WorldItem::Type)
427
            }
428
551
            Some((_span, Token::Record)) => {
429
551
                TypeDef::parse_record(tokens, docs, attributes).map(WorldItem::Type)
430
            }
431
342
            Some((_span, Token::Variant)) => {
432
342
                TypeDef::parse_variant(tokens, docs, attributes).map(WorldItem::Type)
433
            }
434
3.80k
            Some((_span, Token::Enum)) => {
435
3.80k
                TypeDef::parse_enum(tokens, docs, attributes).map(WorldItem::Type)
436
            }
437
0
            Some((_span, Token::Include)) => {
438
0
                Include::parse(tokens, attributes).map(WorldItem::Include)
439
            }
440
0
            other => Err(err_expected(
441
0
                tokens,
442
0
                "`import`, `export`, `include`, `use`, or type definition",
443
0
                other,
444
0
            )
445
0
            .into()),
446
        }
447
26.9k
    }
448
}
449
450
struct Import<'a> {
451
    docs: Docs<'a>,
452
    attributes: Vec<Attribute<'a>>,
453
    kind: ExternKind<'a>,
454
}
455
456
impl<'a> Import<'a> {
457
3.99k
    fn parse(
458
3.99k
        tokens: &mut Tokenizer<'a>,
459
3.99k
        docs: Docs<'a>,
460
3.99k
        attributes: Vec<Attribute<'a>>,
461
3.99k
    ) -> ParseResult<Import<'a>> {
462
3.99k
        tokens.expect(Token::Import)?;
463
3.99k
        let kind = ExternKind::parse(tokens)?;
464
3.99k
        Ok(Import {
465
3.99k
            docs,
466
3.99k
            attributes,
467
3.99k
            kind,
468
3.99k
        })
469
3.99k
    }
470
}
471
472
struct Export<'a> {
473
    docs: Docs<'a>,
474
    attributes: Vec<Attribute<'a>>,
475
    kind: ExternKind<'a>,
476
}
477
478
impl<'a> Export<'a> {
479
15.8k
    fn parse(
480
15.8k
        tokens: &mut Tokenizer<'a>,
481
15.8k
        docs: Docs<'a>,
482
15.8k
        attributes: Vec<Attribute<'a>>,
483
15.8k
    ) -> ParseResult<Export<'a>> {
484
15.8k
        tokens.expect(Token::Export)?;
485
15.8k
        let kind = ExternKind::parse(tokens)?;
486
15.8k
        Ok(Export {
487
15.8k
            docs,
488
15.8k
            attributes,
489
15.8k
            kind,
490
15.8k
        })
491
15.8k
    }
492
}
493
494
enum ExternKind<'a> {
495
    Interface(Id<'a>, Vec<InterfaceItem<'a>>),
496
    Path(UsePath<'a>),
497
    Func(Id<'a>, Func<'a>),
498
    /// `label: use-path` — a named import/export that implements an interface.
499
    NamedPath(Id<'a>, UsePath<'a>),
500
}
501
502
impl<'a> ExternKind<'a> {
503
19.8k
    fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<ExternKind<'a>> {
504
        // Create a copy of the token stream to test out if this is a function
505
        // or an interface import. In those situations the token stream gets
506
        // reset to the state of the clone and we continue down those paths.
507
        //
508
        // If neither a function nor an interface appears here though then the
509
        // clone is thrown away and the original token stream is parsed for an
510
        // interface. This will redo the original ID parse and the original
511
        // colon parse, but that shouldn't be too bad perf-wise.
512
19.8k
        let mut clone = tokens.clone();
513
19.8k
        let id = parse_id(&mut clone)?;
514
19.8k
        if clone.eat(Token::Colon)? {
515
            // import foo: async? func(...)
516
19.4k
            if clone.clone().eat(Token::Func)? || clone.clone().eat(Token::Async)? {
517
3.13k
                *tokens = clone;
518
3.13k
                let ret = ExternKind::Func(id, Func::parse(tokens)?);
519
3.13k
                tokens.expect_semicolon()?;
520
3.13k
                return Ok(ret);
521
16.2k
            }
522
523
            // import foo: interface { ... }
524
16.2k
            if clone.eat(Token::Interface)? {
525
1.33k
                *tokens = clone;
526
1.33k
                return Ok(ExternKind::Interface(id, Interface::parse_items(tokens)?));
527
14.9k
            }
528
529
            // import label: use-path
530
            // At this point we consumed `id:` on the clone but the next token
531
            // is not `func`, `async`, or `interface`. This could be either:
532
            //   import label: local-iface;          (NamedPath)
533
            //   import label: pkg:name/iface;       (NamedPath with package path)
534
            //   import ns:pkg/iface;                (regular fully-qualified Path)
535
            //
536
            // Disambiguate: if the next tokens are `id /`, then the colon was
537
            // part of a fully-qualified `namespace:package/interface` name, not
538
            // a label separator. Fall through to the Path parser in that case.
539
14.9k
            let mut peek = clone.clone();
540
14.9k
            let is_qualified_path =
541
14.9k
                parse_id(&mut peek).is_ok() && peek.clone().eat(Token::Slash).unwrap_or(false);
542
14.9k
            if !is_qualified_path {
543
14.6k
                *tokens = clone;
544
14.6k
                let path = UsePath::parse(tokens)?;
545
14.6k
                tokens.expect_semicolon()?;
546
14.6k
                return Ok(ExternKind::NamedPath(id, path));
547
325
            }
548
454
        }
549
550
        // import foo
551
        // import foo/bar
552
        // import foo:bar/baz
553
779
        let ret = ExternKind::Path(UsePath::parse(tokens)?);
554
779
        tokens.expect_semicolon()?;
555
779
        Ok(ret)
556
19.8k
    }
557
558
0
    fn span(&self) -> Span {
559
0
        match self {
560
0
            ExternKind::Interface(id, _) => id.span,
561
0
            ExternKind::Path(UsePath::Id(id)) => id.span,
562
0
            ExternKind::Path(UsePath::Package { name, .. }) => name.span,
563
0
            ExternKind::Func(id, _) => id.span,
564
0
            ExternKind::NamedPath(id, _) => id.span,
565
        }
566
0
    }
567
}
568
569
struct Interface<'a> {
570
    docs: Docs<'a>,
571
    attributes: Vec<Attribute<'a>>,
572
    name: Id<'a>,
573
    items: Vec<InterfaceItem<'a>>,
574
}
575
576
impl<'a> Interface<'a> {
577
40.9k
    fn parse(
578
40.9k
        tokens: &mut Tokenizer<'a>,
579
40.9k
        docs: Docs<'a>,
580
40.9k
        attributes: Vec<Attribute<'a>>,
581
40.9k
    ) -> ParseResult<Self> {
582
40.9k
        tokens.expect(Token::Interface)?;
583
40.9k
        let name = parse_id(tokens)?;
584
40.9k
        let items = Self::parse_items(tokens)?;
585
40.9k
        Ok(Interface {
586
40.9k
            docs,
587
40.9k
            attributes,
588
40.9k
            name,
589
40.9k
            items,
590
40.9k
        })
591
40.9k
    }
592
593
42.2k
    pub(super) fn parse_items(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<InterfaceItem<'a>>> {
594
42.2k
        tokens.expect(Token::LeftBrace)?;
595
42.2k
        let mut items = Vec::new();
596
        loop {
597
92.2k
            let docs = parse_docs(tokens)?;
598
92.2k
            if tokens.eat(Token::RightBrace)? {
599
42.2k
                break;
600
49.9k
            }
601
49.9k
            let attributes = Attribute::parse_list(tokens)?;
602
49.9k
            items.push(InterfaceItem::parse(tokens, docs, attributes)?);
603
        }
604
42.2k
        Ok(items)
605
42.2k
    }
606
}
607
608
#[derive(Debug)]
609
pub enum WorldOrInterface {
610
    World,
611
    Interface,
612
    Unknown,
613
}
614
615
enum InterfaceItem<'a> {
616
    TypeDef(TypeDef<'a>),
617
    Func(NamedFunc<'a>),
618
    Use(Use<'a>),
619
}
620
621
struct Use<'a> {
622
    attributes: Vec<Attribute<'a>>,
623
    from: UsePath<'a>,
624
    names: Vec<UseName<'a>>,
625
}
626
627
#[derive(Debug)]
628
enum UsePath<'a> {
629
    Id(Id<'a>),
630
    Package { id: PackageName<'a>, name: Id<'a> },
631
}
632
633
impl<'a> UsePath<'a> {
634
38.3k
    fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
635
38.3k
        let id = parse_id(tokens)?;
636
38.3k
        if tokens.eat(Token::Colon)? {
637
            // `foo:bar/baz@1.0`
638
27.7k
            let namespace = id;
639
27.7k
            let pkg_name = parse_id(tokens)?;
640
27.7k
            tokens.expect(Token::Slash)?;
641
27.7k
            let name = parse_id(tokens)?;
642
27.7k
            let version = parse_opt_version(tokens)?;
643
27.7k
            Ok(UsePath::Package {
644
27.7k
                id: PackageName {
645
27.7k
                    docs: Default::default(),
646
27.7k
                    span: Span::new(namespace.span.start(), pkg_name.span.end()),
647
27.7k
                    namespace,
648
27.7k
                    name: pkg_name,
649
27.7k
                    version,
650
27.7k
                },
651
27.7k
                name,
652
27.7k
            })
653
        } else {
654
            // `foo`
655
10.6k
            Ok(UsePath::Id(id))
656
        }
657
38.3k
    }
658
659
5.68k
    fn name(&self) -> &Id<'a> {
660
5.68k
        match self {
661
1.96k
            UsePath::Id(id) => id,
662
3.71k
            UsePath::Package { name, .. } => name,
663
        }
664
5.68k
    }
665
}
666
667
struct UseName<'a> {
668
    name: Id<'a>,
669
    as_: Option<Id<'a>>,
670
}
671
672
impl<'a> Use<'a> {
673
20.1k
    fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
674
20.1k
        tokens.expect(Token::Use)?;
675
20.1k
        let from = UsePath::parse(tokens)?;
676
20.1k
        tokens.expect(Token::Period)?;
677
20.1k
        tokens.expect(Token::LeftBrace)?;
678
679
20.1k
        let mut names = Vec::new();
680
23.3k
        while !tokens.eat(Token::RightBrace)? {
681
23.3k
            let mut name = UseName {
682
23.3k
                name: parse_id(tokens)?,
683
23.3k
                as_: None,
684
            };
685
23.3k
            if tokens.eat(Token::As)? {
686
21.5k
                name.as_ = Some(parse_id(tokens)?);
687
1.81k
            }
688
23.3k
            names.push(name);
689
23.3k
            if !tokens.eat(Token::Comma)? {
690
20.1k
                tokens.expect(Token::RightBrace)?;
691
20.1k
                break;
692
3.23k
            }
693
        }
694
20.1k
        tokens.expect_semicolon()?;
695
20.1k
        Ok(Use {
696
20.1k
            attributes,
697
20.1k
            from,
698
20.1k
            names,
699
20.1k
        })
700
20.1k
    }
701
}
702
703
struct Include<'a> {
704
    from: UsePath<'a>,
705
    attributes: Vec<Attribute<'a>>,
706
    names: Vec<IncludeName<'a>>,
707
}
708
709
struct IncludeName<'a> {
710
    name: Id<'a>,
711
    as_: Id<'a>,
712
}
713
714
impl<'a> Include<'a> {
715
0
    fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
716
0
        tokens.expect(Token::Include)?;
717
0
        let from = UsePath::parse(tokens)?;
718
719
0
        let names = if tokens.eat(Token::With)? {
720
0
            parse_list(
721
0
                tokens,
722
0
                Token::LeftBrace,
723
0
                Token::RightBrace,
724
0
                |_docs, tokens| {
725
0
                    let name = parse_id(tokens)?;
726
0
                    tokens.expect(Token::As)?;
727
0
                    let as_ = parse_id(tokens)?;
728
0
                    Ok(IncludeName { name, as_ })
729
0
                },
730
0
            )?
731
        } else {
732
0
            tokens.expect_semicolon()?;
733
0
            Vec::new()
734
        };
735
736
0
        Ok(Include {
737
0
            attributes,
738
0
            from,
739
0
            names,
740
0
        })
741
0
    }
742
}
743
744
#[derive(Debug, Clone)]
745
pub struct Id<'a> {
746
    name: &'a str,
747
    span: Span,
748
}
749
750
impl<'a> From<&'a str> for Id<'a> {
751
0
    fn from(s: &'a str) -> Id<'a> {
752
0
        Id {
753
0
            name: s.into(),
754
0
            span: Default::default(),
755
0
        }
756
0
    }
757
}
758
759
#[derive(Debug, Clone)]
760
pub struct Docs<'a> {
761
    docs: Vec<Cow<'a, str>>,
762
    span: Span,
763
}
764
765
impl<'a> Default for Docs<'a> {
766
498k
    fn default() -> Self {
767
498k
        Self {
768
498k
            docs: Default::default(),
769
498k
            span: Default::default(),
770
498k
        }
771
498k
    }
772
}
773
774
struct TypeDef<'a> {
775
    docs: Docs<'a>,
776
    attributes: Vec<Attribute<'a>>,
777
    name: Id<'a>,
778
    ty: Type<'a>,
779
}
780
781
enum Type<'a> {
782
    Bool(Span),
783
    U8(Span),
784
    U16(Span),
785
    U32(Span),
786
    U64(Span),
787
    S8(Span),
788
    S16(Span),
789
    S32(Span),
790
    S64(Span),
791
    F32(Span),
792
    F64(Span),
793
    Char(Span),
794
    String(Span),
795
    Name(Id<'a>),
796
    List(List<'a>),
797
    Map(Map<'a>),
798
    FixedLengthList(FixedLengthList<'a>),
799
    Handle(Handle<'a>),
800
    Resource(Resource<'a>),
801
    Record(Record<'a>),
802
    Flags(Flags<'a>),
803
    Variant(Variant<'a>),
804
    Tuple(Tuple<'a>),
805
    Enum(Enum<'a>),
806
    Option(Option_<'a>),
807
    Result(Result_<'a>),
808
    Future(Future<'a>),
809
    Stream(Stream<'a>),
810
    ErrorContext(Span),
811
}
812
813
enum Handle<'a> {
814
    Own { resource: Id<'a> },
815
    Borrow { resource: Id<'a> },
816
}
817
818
impl Handle<'_> {
819
221
    fn span(&self) -> Span {
820
221
        match self {
821
221
            Handle::Own { resource } | Handle::Borrow { resource } => resource.span,
822
        }
823
221
    }
824
}
825
826
struct Resource<'a> {
827
    span: Span,
828
    funcs: Vec<ResourceFunc<'a>>,
829
}
830
831
enum ResourceFunc<'a> {
832
    Method(NamedFunc<'a>),
833
    Static(NamedFunc<'a>),
834
    Constructor(NamedFunc<'a>),
835
}
836
837
impl<'a> ResourceFunc<'a> {
838
3.58k
    fn parse(
839
3.58k
        docs: Docs<'a>,
840
3.58k
        attributes: Vec<Attribute<'a>>,
841
3.58k
        tokens: &mut Tokenizer<'a>,
842
3.58k
    ) -> ParseResult<Self> {
843
3.58k
        match tokens.clone().next()? {
844
526
            Some((span, Token::Constructor)) => {
845
526
                tokens.expect(Token::Constructor)?;
846
526
                tokens.expect(Token::LeftParen)?;
847
946
                let params = parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
848
946
                    let name = parse_id(tokens)?;
849
946
                    tokens.expect(Token::Colon)?;
850
946
                    let ty = Type::parse(tokens)?;
851
946
                    Ok((name, ty))
852
946
                })?;
853
526
                let result = if tokens.eat(Token::RArrow)? {
854
0
                    let ty = Type::parse(tokens)?;
855
0
                    Some(ty)
856
                } else {
857
526
                    None
858
                };
859
526
                tokens.expect_semicolon()?;
860
526
                Ok(ResourceFunc::Constructor(NamedFunc {
861
526
                    docs,
862
526
                    attributes,
863
526
                    name: Id {
864
526
                        span,
865
526
                        name: "constructor",
866
526
                    },
867
526
                    func: Func {
868
526
                        span,
869
526
                        async_: false,
870
526
                        params,
871
526
                        result,
872
526
                    },
873
526
                }))
874
            }
875
3.06k
            Some((_span, Token::Id | Token::ExplicitId)) => {
876
3.06k
                let name = parse_id(tokens)?;
877
3.06k
                tokens.expect(Token::Colon)?;
878
3.06k
                let ctor = if tokens.eat(Token::Static)? {
879
1.17k
                    ResourceFunc::Static
880
1.88k
                } else {
881
1.88k
                    ResourceFunc::Method
882
1.88k
                };
883
3.06k
                let func = Func::parse(tokens)?;
884
3.06k
                tokens.expect_semicolon()?;
885
3.06k
                Ok(ctor(NamedFunc {
886
3.06k
                    docs,
887
3.06k
                    attributes,
888
3.06k
                    name,
889
3.06k
                    func,
890
3.06k
                }))
891
            }
892
0
            other => Err(err_expected(tokens, "`constructor` or identifier", other).into()),
893
        }
894
3.58k
    }
895
896
3.58k
    fn named_func(&self) -> &NamedFunc<'a> {
897
        use ResourceFunc::*;
898
3.58k
        match self {
899
3.58k
            Method(f) | Static(f) | Constructor(f) => f,
900
        }
901
3.58k
    }
902
}
903
904
struct Record<'a> {
905
    span: Span,
906
    fields: Vec<Field<'a>>,
907
}
908
909
struct Field<'a> {
910
    docs: Docs<'a>,
911
    name: Id<'a>,
912
    ty: Type<'a>,
913
}
914
915
struct Flags<'a> {
916
    span: Span,
917
    flags: Vec<Flag<'a>>,
918
}
919
920
struct Flag<'a> {
921
    docs: Docs<'a>,
922
    name: Id<'a>,
923
}
924
925
struct Variant<'a> {
926
    span: Span,
927
    cases: Vec<Case<'a>>,
928
}
929
930
struct Case<'a> {
931
    docs: Docs<'a>,
932
    name: Id<'a>,
933
    ty: Option<Type<'a>>,
934
}
935
936
struct Enum<'a> {
937
    span: Span,
938
    cases: Vec<EnumCase<'a>>,
939
}
940
941
struct EnumCase<'a> {
942
    docs: Docs<'a>,
943
    name: Id<'a>,
944
}
945
946
struct Option_<'a> {
947
    span: Span,
948
    ty: Box<Type<'a>>,
949
}
950
951
struct List<'a> {
952
    span: Span,
953
    ty: Box<Type<'a>>,
954
}
955
956
struct Map<'a> {
957
    span: Span,
958
    key: Box<Type<'a>>,
959
    value: Box<Type<'a>>,
960
}
961
962
struct FixedLengthList<'a> {
963
    span: Span,
964
    ty: Box<Type<'a>>,
965
    size: u32,
966
}
967
968
struct Future<'a> {
969
    span: Span,
970
    ty: Option<Box<Type<'a>>>,
971
}
972
973
struct Tuple<'a> {
974
    span: Span,
975
    types: Vec<Type<'a>>,
976
}
977
978
struct Result_<'a> {
979
    span: Span,
980
    ok: Option<Box<Type<'a>>>,
981
    err: Option<Box<Type<'a>>>,
982
}
983
984
struct Stream<'a> {
985
    span: Span,
986
    ty: Option<Box<Type<'a>>>,
987
}
988
989
struct NamedFunc<'a> {
990
    docs: Docs<'a>,
991
    attributes: Vec<Attribute<'a>>,
992
    name: Id<'a>,
993
    func: Func<'a>,
994
}
995
996
type ParamList<'a> = Vec<(Id<'a>, Type<'a>)>;
997
998
struct Func<'a> {
999
    span: Span,
1000
    async_: bool,
1001
    params: ParamList<'a>,
1002
    result: Option<Type<'a>>,
1003
}
1004
1005
impl<'a> Func<'a> {
1006
19.8k
    fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Func<'a>> {
1007
19.8k
        fn parse_params<'a>(
1008
19.8k
            tokens: &mut Tokenizer<'a>,
1009
19.8k
            left_paren: bool,
1010
19.8k
        ) -> ParseResult<ParamList<'a>> {
1011
19.8k
            if left_paren {
1012
19.8k
                tokens.expect(Token::LeftParen)?;
1013
0
            };
1014
44.8k
            parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
1015
44.8k
                let name = parse_id(tokens)?;
1016
44.8k
                tokens.expect(Token::Colon)?;
1017
44.8k
                let ty = Type::parse(tokens)?;
1018
44.8k
                Ok((name, ty))
1019
44.8k
            })
1020
19.8k
        }
1021
1022
19.8k
        let async_ = tokens.eat(Token::Async)?;
1023
19.8k
        let span = tokens.expect(Token::Func)?;
1024
19.8k
        let params = parse_params(tokens, true)?;
1025
19.8k
        let result = if tokens.eat(Token::RArrow)? {
1026
15.1k
            let ty = Type::parse(tokens)?;
1027
15.1k
            Some(ty)
1028
        } else {
1029
4.73k
            None
1030
        };
1031
19.8k
        Ok(Func {
1032
19.8k
            span,
1033
19.8k
            async_,
1034
19.8k
            params,
1035
19.8k
            result,
1036
19.8k
        })
1037
19.8k
    }
1038
}
1039
1040
impl<'a> InterfaceItem<'a> {
1041
49.9k
    fn parse(
1042
49.9k
        tokens: &mut Tokenizer<'a>,
1043
49.9k
        docs: Docs<'a>,
1044
49.9k
        attributes: Vec<Attribute<'a>>,
1045
49.9k
    ) -> ParseResult<InterfaceItem<'a>> {
1046
49.9k
        match tokens.clone().next()? {
1047
1.01k
            Some((_span, Token::Type)) => {
1048
1.01k
                TypeDef::parse(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1049
            }
1050
517
            Some((_span, Token::Flags)) => {
1051
517
                TypeDef::parse_flags(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1052
            }
1053
7.05k
            Some((_span, Token::Enum)) => {
1054
7.05k
                TypeDef::parse_enum(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1055
            }
1056
5.14k
            Some((_span, Token::Variant)) => {
1057
5.14k
                TypeDef::parse_variant(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1058
            }
1059
1.36k
            Some((_span, Token::Resource)) => {
1060
1.36k
                TypeDef::parse_resource(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1061
            }
1062
1.62k
            Some((_span, Token::Record)) => {
1063
1.62k
                TypeDef::parse_record(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1064
            }
1065
6.90k
            Some((_span, Token::Id)) | Some((_span, Token::ExplicitId)) => {
1066
13.6k
                NamedFunc::parse(tokens, docs, attributes).map(InterfaceItem::Func)
1067
            }
1068
19.5k
            Some((_span, Token::Use)) => Use::parse(tokens, attributes).map(InterfaceItem::Use),
1069
0
            other => Err(err_expected(tokens, "`type`, `resource` or `func`", other).into()),
1070
        }
1071
49.9k
    }
1072
}
1073
1074
impl<'a> TypeDef<'a> {
1075
2.07k
    fn parse(
1076
2.07k
        tokens: &mut Tokenizer<'a>,
1077
2.07k
        docs: Docs<'a>,
1078
2.07k
        attributes: Vec<Attribute<'a>>,
1079
2.07k
    ) -> ParseResult<Self> {
1080
2.07k
        tokens.expect(Token::Type)?;
1081
2.07k
        let name = parse_id(tokens)?;
1082
2.07k
        tokens.expect(Token::Equals)?;
1083
2.07k
        let ty = Type::parse(tokens)?;
1084
2.07k
        tokens.expect_semicolon()?;
1085
2.07k
        Ok(TypeDef {
1086
2.07k
            docs,
1087
2.07k
            attributes,
1088
2.07k
            name,
1089
2.07k
            ty,
1090
2.07k
        })
1091
2.07k
    }
1092
1093
759
    fn parse_flags(
1094
759
        tokens: &mut Tokenizer<'a>,
1095
759
        docs: Docs<'a>,
1096
759
        attributes: Vec<Attribute<'a>>,
1097
759
    ) -> ParseResult<Self> {
1098
759
        tokens.expect(Token::Flags)?;
1099
759
        let name = parse_id(tokens)?;
1100
759
        let ty = Type::Flags(Flags {
1101
759
            span: name.span,
1102
759
            flags: parse_list(
1103
759
                tokens,
1104
759
                Token::LeftBrace,
1105
759
                Token::RightBrace,
1106
2.45k
                |docs, tokens| {
1107
2.45k
                    let name = parse_id(tokens)?;
1108
2.45k
                    Ok(Flag { docs, name })
1109
2.45k
                },
1110
0
            )?,
1111
        });
1112
759
        Ok(TypeDef {
1113
759
            docs,
1114
759
            attributes,
1115
759
            name,
1116
759
            ty,
1117
759
        })
1118
759
    }
1119
1120
1.85k
    fn parse_resource(
1121
1.85k
        tokens: &mut Tokenizer<'a>,
1122
1.85k
        docs: Docs<'a>,
1123
1.85k
        attributes: Vec<Attribute<'a>>,
1124
1.85k
    ) -> ParseResult<Self> {
1125
1.85k
        tokens.expect(Token::Resource)?;
1126
1.85k
        let name = parse_id(tokens)?;
1127
1.85k
        let mut funcs = Vec::new();
1128
1.85k
        if tokens.eat(Token::LeftBrace)? {
1129
4.98k
            while !tokens.eat(Token::RightBrace)? {
1130
3.58k
                let docs = parse_docs(tokens)?;
1131
3.58k
                let attributes = Attribute::parse_list(tokens)?;
1132
3.58k
                funcs.push(ResourceFunc::parse(docs, attributes, tokens)?);
1133
            }
1134
        } else {
1135
458
            tokens.expect_semicolon()?;
1136
        }
1137
1.85k
        let ty = Type::Resource(Resource {
1138
1.85k
            span: name.span,
1139
1.85k
            funcs,
1140
1.85k
        });
1141
1.85k
        Ok(TypeDef {
1142
1.85k
            docs,
1143
1.85k
            attributes,
1144
1.85k
            name,
1145
1.85k
            ty,
1146
1.85k
        })
1147
1.85k
    }
1148
1149
2.17k
    fn parse_record(
1150
2.17k
        tokens: &mut Tokenizer<'a>,
1151
2.17k
        docs: Docs<'a>,
1152
2.17k
        attributes: Vec<Attribute<'a>>,
1153
2.17k
    ) -> ParseResult<Self> {
1154
2.17k
        tokens.expect(Token::Record)?;
1155
2.17k
        let name = parse_id(tokens)?;
1156
2.17k
        let ty = Type::Record(Record {
1157
2.17k
            span: name.span,
1158
2.17k
            fields: parse_list(
1159
2.17k
                tokens,
1160
2.17k
                Token::LeftBrace,
1161
2.17k
                Token::RightBrace,
1162
7.74k
                |docs, tokens| {
1163
7.74k
                    let name = parse_id(tokens)?;
1164
7.74k
                    tokens.expect(Token::Colon)?;
1165
7.74k
                    let ty = Type::parse(tokens)?;
1166
7.74k
                    Ok(Field { docs, name, ty })
1167
7.74k
                },
1168
0
            )?,
1169
        });
1170
2.17k
        Ok(TypeDef {
1171
2.17k
            docs,
1172
2.17k
            attributes,
1173
2.17k
            name,
1174
2.17k
            ty,
1175
2.17k
        })
1176
2.17k
    }
1177
1178
5.48k
    fn parse_variant(
1179
5.48k
        tokens: &mut Tokenizer<'a>,
1180
5.48k
        docs: Docs<'a>,
1181
5.48k
        attributes: Vec<Attribute<'a>>,
1182
5.48k
    ) -> ParseResult<Self> {
1183
5.48k
        tokens.expect(Token::Variant)?;
1184
5.48k
        let name = parse_id(tokens)?;
1185
5.48k
        let ty = Type::Variant(Variant {
1186
5.48k
            span: name.span,
1187
5.48k
            cases: parse_list(
1188
5.48k
                tokens,
1189
5.48k
                Token::LeftBrace,
1190
5.48k
                Token::RightBrace,
1191
19.3k
                |docs, tokens| {
1192
19.3k
                    let name = parse_id(tokens)?;
1193
19.3k
                    let ty = if tokens.eat(Token::LeftParen)? {
1194
17.7k
                        let ty = Type::parse(tokens)?;
1195
17.7k
                        tokens.expect(Token::RightParen)?;
1196
17.7k
                        Some(ty)
1197
                    } else {
1198
1.58k
                        None
1199
                    };
1200
19.3k
                    Ok(Case { docs, name, ty })
1201
19.3k
                },
1202
0
            )?,
1203
        });
1204
5.48k
        Ok(TypeDef {
1205
5.48k
            docs,
1206
5.48k
            attributes,
1207
5.48k
            name,
1208
5.48k
            ty,
1209
5.48k
        })
1210
5.48k
    }
1211
1212
10.8k
    fn parse_enum(
1213
10.8k
        tokens: &mut Tokenizer<'a>,
1214
10.8k
        docs: Docs<'a>,
1215
10.8k
        attributes: Vec<Attribute<'a>>,
1216
10.8k
    ) -> ParseResult<Self> {
1217
10.8k
        tokens.expect(Token::Enum)?;
1218
10.8k
        let name = parse_id(tokens)?;
1219
10.8k
        let ty = Type::Enum(Enum {
1220
10.8k
            span: name.span,
1221
10.8k
            cases: parse_list(
1222
10.8k
                tokens,
1223
10.8k
                Token::LeftBrace,
1224
10.8k
                Token::RightBrace,
1225
57.5k
                |docs, tokens| {
1226
57.5k
                    let name = parse_id(tokens)?;
1227
57.5k
                    Ok(EnumCase { docs, name })
1228
57.5k
                },
1229
0
            )?,
1230
        });
1231
10.8k
        Ok(TypeDef {
1232
10.8k
            docs,
1233
10.8k
            attributes,
1234
10.8k
            name,
1235
10.8k
            ty,
1236
10.8k
        })
1237
10.8k
    }
1238
}
1239
1240
impl<'a> NamedFunc<'a> {
1241
13.6k
    fn parse(
1242
13.6k
        tokens: &mut Tokenizer<'a>,
1243
13.6k
        docs: Docs<'a>,
1244
13.6k
        attributes: Vec<Attribute<'a>>,
1245
13.6k
    ) -> ParseResult<Self> {
1246
13.6k
        let name = parse_id(tokens)?;
1247
13.6k
        tokens.expect(Token::Colon)?;
1248
13.6k
        let func = Func::parse(tokens)?;
1249
13.6k
        tokens.expect_semicolon()?;
1250
13.6k
        Ok(NamedFunc {
1251
13.6k
            docs,
1252
13.6k
            attributes,
1253
13.6k
            name,
1254
13.6k
            func,
1255
13.6k
        })
1256
13.6k
    }
1257
}
1258
1259
507k
fn parse_id<'a>(tokens: &mut Tokenizer<'a>) -> ParseResult<Id<'a>> {
1260
507k
    match tokens.next()? {
1261
221k
        Some((span, Token::Id)) => Ok(Id {
1262
221k
            name: tokens.parse_id(span)?,
1263
221k
            span,
1264
        }),
1265
285k
        Some((span, Token::ExplicitId)) => Ok(Id {
1266
285k
            name: tokens.parse_explicit_id(span)?,
1267
285k
            span,
1268
        }),
1269
0
        other => Err(err_expected(tokens, "an identifier or string", other)),
1270
    }
1271
507k
}
1272
1273
41.2k
fn parse_opt_version(tokens: &mut Tokenizer<'_>) -> ParseResult<Option<(Span, Version)>> {
1274
41.2k
    if tokens.eat(Token::At)? {
1275
36.7k
        parse_version(tokens).map(Some)
1276
    } else {
1277
4.55k
        Ok(None)
1278
    }
1279
41.2k
}
1280
1281
39.4k
fn parse_version(tokens: &mut Tokenizer<'_>) -> ParseResult<(Span, Version)> {
1282
39.4k
    let start = tokens.expect(Token::Integer)?.start();
1283
39.4k
    tokens.expect(Token::Period)?;
1284
39.4k
    tokens.expect(Token::Integer)?;
1285
39.4k
    tokens.expect(Token::Period)?;
1286
39.4k
    let end = tokens.expect(Token::Integer)?.end();
1287
39.4k
    let mut span = Span::new(start, end);
1288
39.4k
    eat_ids(tokens, Token::Minus, &mut span)?;
1289
39.4k
    eat_ids(tokens, Token::Plus, &mut span)?;
1290
39.4k
    let string = tokens.get_span(span);
1291
39.4k
    let version =
1292
39.4k
        Version::parse(string).map_err(|e| ParseError::new_syntax(span, e.to_string()))?;
1293
39.4k
    return Ok((span, version));
1294
1295
    // According to `semver.org` this is what we're parsing:
1296
    //
1297
    // ```ebnf
1298
    // <pre-release> ::= <dot-separated pre-release identifiers>
1299
    //
1300
    // <dot-separated pre-release identifiers> ::= <pre-release identifier>
1301
    //                                           | <pre-release identifier> "." <dot-separated pre-release identifiers>
1302
    //
1303
    // <build> ::= <dot-separated build identifiers>
1304
    //
1305
    // <dot-separated build identifiers> ::= <build identifier>
1306
    //                                     | <build identifier> "." <dot-separated build identifiers>
1307
    //
1308
    // <pre-release identifier> ::= <alphanumeric identifier>
1309
    //                            | <numeric identifier>
1310
    //
1311
    // <build identifier> ::= <alphanumeric identifier>
1312
    //                      | <digits>
1313
    //
1314
    // <alphanumeric identifier> ::= <non-digit>
1315
    //                             | <non-digit> <identifier characters>
1316
    //                             | <identifier characters> <non-digit>
1317
    //                             | <identifier characters> <non-digit> <identifier characters>
1318
    //
1319
    // <numeric identifier> ::= "0"
1320
    //                        | <positive digit>
1321
    //                        | <positive digit> <digits>
1322
    //
1323
    // <identifier characters> ::= <identifier character>
1324
    //                           | <identifier character> <identifier characters>
1325
    //
1326
    // <identifier character> ::= <digit>
1327
    //                          | <non-digit>
1328
    //
1329
    // <non-digit> ::= <letter>
1330
    //               | "-"
1331
    //
1332
    // <digits> ::= <digit>
1333
    //            | <digit> <digits>
1334
    // ```
1335
    //
1336
    // This is loosely based on WIT syntax and an approximation is parsed here:
1337
    //
1338
    // * This function starts by parsing the optional leading `-` and `+` which
1339
    //   indicates pre-release and build metadata.
1340
    // * Afterwards all of $id, $integer, `-`, and `.` are chomped. The only
1341
    //   exception here is that if `.` isn't followed by $id, $integer, or `-`
1342
    //   then it's assumed that it's something like `use a:b@1.0.0-a.{...}`
1343
    //   where the `.` is part of WIT syntax, not semver.
1344
    //
1345
    // Note that this additionally doesn't try to return any first-class errors.
1346
    // Instead this bails out on something unrecognized for something else in
1347
    // the system to return an error.
1348
78.9k
    fn eat_ids(
1349
78.9k
        tokens: &mut Tokenizer<'_>,
1350
78.9k
        prefix: Token,
1351
78.9k
        end: &mut Span,
1352
78.9k
    ) -> Result<(), lex::Error> {
1353
78.9k
        if !tokens.eat(prefix)? {
1354
9.93k
            return Ok(());
1355
69.0k
        }
1356
        loop {
1357
239k
            let mut clone = tokens.clone();
1358
239k
            match clone.next()? {
1359
69.0k
                Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1360
69.0k
                    end.set_end(span.end());
1361
69.0k
                    *tokens = clone;
1362
69.0k
                }
1363
116k
                Some((_span, Token::Period)) => match clone.next()? {
1364
101k
                    Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1365
101k
                        end.set_end(span.end());
1366
101k
                        *tokens = clone;
1367
101k
                    }
1368
14.4k
                    _ => break Ok(()),
1369
                },
1370
54.5k
                _ => break Ok(()),
1371
            }
1372
        }
1373
78.9k
    }
1374
39.4k
}
1375
1376
471k
fn parse_docs<'a>(tokens: &mut Tokenizer<'a>) -> Result<Docs<'a>, lex::Error> {
1377
471k
    let mut docs = Docs::default();
1378
471k
    let mut clone = tokens.clone();
1379
471k
    let mut started = false;
1380
876k
    while let Some((span, token)) = clone.next_raw()? {
1381
859k
        match token {
1382
405k
            Token::Whitespace => {}
1383
            Token::Comment => {
1384
0
                let comment = tokens.get_span(span);
1385
0
                if !started {
1386
0
                    docs.span.set_start(span.start());
1387
0
                    started = true;
1388
0
                }
1389
0
                let trailing_ws = comment
1390
0
                    .bytes()
1391
0
                    .rev()
1392
0
                    .take_while(|ch| ch.is_ascii_whitespace())
1393
0
                    .count();
1394
0
                docs.span.set_end(span.end() - (trailing_ws as u32));
1395
0
                docs.docs.push(comment.into());
1396
            }
1397
453k
            _ => break,
1398
        };
1399
405k
        *tokens = clone.clone();
1400
    }
1401
471k
    Ok(docs)
1402
471k
}
1403
1404
/// Maximum nesting depth of types parsed with `Type::parse`, e.g.
1405
/// `list<list<list<...>>>`.
1406
const MAX_TYPE_DEPTH: usize = 100;
1407
1408
impl<'a> Type<'a> {
1409
88.4k
    fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
1410
88.4k
        Type::parse_at_depth(tokens, 0)
1411
88.4k
    }
1412
1413
234k
    fn parse_at_depth(tokens: &mut Tokenizer<'a>, depth: usize) -> ParseResult<Self> {
1414
234k
        let token = tokens.next()?;
1415
234k
        if depth >= MAX_TYPE_DEPTH {
1416
0
            let span = match token {
1417
0
                Some((span, _)) => span,
1418
0
                None => tokens.eof_span(),
1419
            };
1420
0
            return Err(ParseError::new_syntax(span, "type nesting too deep"));
1421
234k
        }
1422
234k
        match token {
1423
8.14k
            Some((span, Token::U8)) => Ok(Type::U8(span)),
1424
2.15k
            Some((span, Token::U16)) => Ok(Type::U16(span)),
1425
2.64k
            Some((span, Token::U32)) => Ok(Type::U32(span)),
1426
1.93k
            Some((span, Token::U64)) => Ok(Type::U64(span)),
1427
2.43k
            Some((span, Token::S8)) => Ok(Type::S8(span)),
1428
1.94k
            Some((span, Token::S16)) => Ok(Type::S16(span)),
1429
2.56k
            Some((span, Token::S32)) => Ok(Type::S32(span)),
1430
10.7k
            Some((span, Token::S64)) => Ok(Type::S64(span)),
1431
4.53k
            Some((span, Token::F32)) => Ok(Type::F32(span)),
1432
8.17k
            Some((span, Token::F64)) => Ok(Type::F64(span)),
1433
12.5k
            Some((span, Token::Char)) => Ok(Type::Char(span)),
1434
1435
            // tuple<T, U, ...>
1436
23.8k
            Some((span, Token::Tuple)) => {
1437
23.8k
                let types = parse_list(
1438
23.8k
                    tokens,
1439
23.8k
                    Token::LessThan,
1440
23.8k
                    Token::GreaterThan,
1441
86.3k
                    |_docs, tokens| Type::parse_at_depth(tokens, depth + 1),
1442
0
                )?;
1443
23.8k
                Ok(Type::Tuple(Tuple { span, types }))
1444
            }
1445
1446
78.2k
            Some((span, Token::Bool)) => Ok(Type::Bool(span)),
1447
2.11k
            Some((span, Token::String_)) => Ok(Type::String(span)),
1448
1449
            // list<T>
1450
            // list<T, N>
1451
8.90k
            Some((span, Token::List)) => {
1452
8.90k
                tokens.expect(Token::LessThan)?;
1453
8.90k
                let ty = Type::parse_at_depth(tokens, depth + 1)?;
1454
8.90k
                let size = if tokens.eat(Token::Comma)? {
1455
3.37k
                    let number = tokens.next()?;
1456
3.37k
                    if let Some((span, Token::Integer)) = number {
1457
3.37k
                        let size: u32 = tokens.get_span(span).parse().map_err(|e| {
1458
0
                            ParseError::new_syntax(span, format!("invalid list size: {e}"))
1459
0
                        })?;
1460
3.37k
                        Some(size)
1461
                    } else {
1462
0
                        return Err(err_expected(tokens, "fixed-length", number).into());
1463
                    }
1464
                } else {
1465
5.53k
                    None
1466
                };
1467
8.90k
                tokens.expect(Token::GreaterThan)?;
1468
8.90k
                if let Some(size) = size {
1469
3.37k
                    Ok(Type::FixedLengthList(FixedLengthList {
1470
3.37k
                        span,
1471
3.37k
                        ty: Box::new(ty),
1472
3.37k
                        size,
1473
3.37k
                    }))
1474
                } else {
1475
5.53k
                    Ok(Type::List(List {
1476
5.53k
                        span,
1477
5.53k
                        ty: Box::new(ty),
1478
5.53k
                    }))
1479
                }
1480
            }
1481
1482
            // map<K, V>
1483
0
            Some((span, Token::Map)) => {
1484
0
                tokens.expect(Token::LessThan)?;
1485
0
                let key = Type::parse_at_depth(tokens, depth + 1)?;
1486
0
                tokens.expect(Token::Comma)?;
1487
0
                let value = Type::parse_at_depth(tokens, depth + 1)?;
1488
0
                tokens.expect(Token::GreaterThan)?;
1489
0
                Ok(Type::Map(Map {
1490
0
                    span,
1491
0
                    key: Box::new(key),
1492
0
                    value: Box::new(value),
1493
0
                }))
1494
            }
1495
1496
            // option<T>
1497
14.9k
            Some((span, Token::Option_)) => {
1498
14.9k
                tokens.expect(Token::LessThan)?;
1499
14.9k
                let ty = Type::parse_at_depth(tokens, depth + 1)?;
1500
14.9k
                tokens.expect(Token::GreaterThan)?;
1501
14.9k
                Ok(Type::Option(Option_ {
1502
14.9k
                    span,
1503
14.9k
                    ty: Box::new(ty),
1504
14.9k
                }))
1505
            }
1506
1507
            // result<T, E>
1508
            // result<_, E>
1509
            // result<T>
1510
            // result
1511
15.5k
            Some((span, Token::Result_)) => {
1512
15.5k
                let mut ok = None;
1513
15.5k
                let mut err = None;
1514
1515
15.5k
                if tokens.eat(Token::LessThan)? {
1516
15.2k
                    if tokens.eat(Token::Underscore)? {
1517
1.60k
                        tokens.expect(Token::Comma)?;
1518
1.60k
                        err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1519
                    } else {
1520
13.6k
                        ok = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1521
13.6k
                        if tokens.eat(Token::Comma)? {
1522
11.4k
                            err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1523
2.16k
                        }
1524
                    };
1525
15.2k
                    tokens.expect(Token::GreaterThan)?;
1526
304
                };
1527
15.5k
                Ok(Type::Result(Result_ { span, ok, err }))
1528
            }
1529
1530
            // future<T>
1531
            // future
1532
7.08k
            Some((span, Token::Future)) => {
1533
7.08k
                let mut ty = None;
1534
1535
7.08k
                if tokens.eat(Token::LessThan)? {
1536
4.90k
                    ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1537
4.90k
                    tokens.expect(Token::GreaterThan)?;
1538
2.17k
                };
1539
7.08k
                Ok(Type::Future(Future { span, ty }))
1540
            }
1541
1542
            // stream<T>
1543
            // stream
1544
3.98k
            Some((span, Token::Stream)) => {
1545
3.98k
                let mut ty = None;
1546
1547
3.98k
                if tokens.eat(Token::LessThan)? {
1548
3.98k
                    ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1549
3.98k
                    tokens.expect(Token::GreaterThan)?;
1550
0
                };
1551
3.98k
                Ok(Type::Stream(Stream { span, ty }))
1552
            }
1553
1554
            // error-context
1555
19.5k
            Some((span, Token::ErrorContext)) => Ok(Type::ErrorContext(span)),
1556
1557
            // own<T>
1558
221
            Some((_span, Token::Own)) => {
1559
221
                tokens.expect(Token::LessThan)?;
1560
221
                let resource = parse_id(tokens)?;
1561
221
                tokens.expect(Token::GreaterThan)?;
1562
221
                Ok(Type::Handle(Handle::Own { resource }))
1563
            }
1564
1565
            // borrow<T>
1566
0
            Some((_span, Token::Borrow)) => {
1567
0
                tokens.expect(Token::LessThan)?;
1568
0
                let resource = parse_id(tokens)?;
1569
0
                tokens.expect(Token::GreaterThan)?;
1570
0
                Ok(Type::Handle(Handle::Borrow { resource }))
1571
            }
1572
1573
            // `foo`
1574
1.00k
            Some((span, Token::Id)) => Ok(Type::Name(Id {
1575
1.00k
                name: tokens.parse_id(span)?.into(),
1576
1.00k
                span,
1577
            })),
1578
            // `%foo`
1579
933
            Some((span, Token::ExplicitId)) => Ok(Type::Name(Id {
1580
933
                name: tokens.parse_explicit_id(span)?.into(),
1581
933
                span,
1582
            })),
1583
1584
0
            other => Err(err_expected(tokens, "a type", other).into()),
1585
        }
1586
234k
    }
1587
1588
232k
    fn span(&self) -> Span {
1589
232k
        match self {
1590
77.6k
            Type::Bool(span)
1591
8.13k
            | Type::U8(span)
1592
2.13k
            | Type::U16(span)
1593
2.61k
            | Type::U32(span)
1594
1.91k
            | Type::U64(span)
1595
2.40k
            | Type::S8(span)
1596
1.93k
            | Type::S16(span)
1597
2.48k
            | Type::S32(span)
1598
10.6k
            | Type::S64(span)
1599
4.44k
            | Type::F32(span)
1600
8.11k
            | Type::F64(span)
1601
12.4k
            | Type::Char(span)
1602
2.09k
            | Type::String(span)
1603
156k
            | Type::ErrorContext(span) => *span,
1604
1.92k
            Type::Name(id) => id.span,
1605
5.46k
            Type::List(l) => l.span,
1606
0
            Type::Map(m) => m.span,
1607
3.36k
            Type::FixedLengthList(l) => l.span,
1608
221
            Type::Handle(h) => h.span(),
1609
0
            Type::Resource(r) => r.span,
1610
0
            Type::Record(r) => r.span,
1611
0
            Type::Flags(f) => f.span,
1612
0
            Type::Variant(v) => v.span,
1613
23.5k
            Type::Tuple(t) => t.span,
1614
0
            Type::Enum(e) => e.span,
1615
14.6k
            Type::Option(o) => o.span,
1616
15.4k
            Type::Result(r) => r.span,
1617
7.07k
            Type::Future(f) => f.span,
1618
3.96k
            Type::Stream(s) => s.span,
1619
        }
1620
232k
    }
1621
}
1622
1623
43.0k
fn parse_list<'a, T>(
1624
43.0k
    tokens: &mut Tokenizer<'a>,
1625
43.0k
    start: Token,
1626
43.0k
    end: Token,
1627
43.0k
    parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1628
43.0k
) -> ParseResult<Vec<T>> {
1629
43.0k
    tokens.expect(start)?;
1630
43.0k
    parse_list_trailer(tokens, end, parse)
1631
43.0k
}
Unexecuted instantiation: wit_parser::ast::parse_list::<wit_parser::ast::IncludeName, <wit_parser::ast::Include>::parse::{closure#0}>
wit_parser::ast::parse_list::<wit_parser::ast::Case, <wit_parser::ast::TypeDef>::parse_variant::{closure#0}>
Line
Count
Source
1623
5.48k
fn parse_list<'a, T>(
1624
5.48k
    tokens: &mut Tokenizer<'a>,
1625
5.48k
    start: Token,
1626
5.48k
    end: Token,
1627
5.48k
    parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1628
5.48k
) -> ParseResult<Vec<T>> {
1629
5.48k
    tokens.expect(start)?;
1630
5.48k
    parse_list_trailer(tokens, end, parse)
1631
5.48k
}
wit_parser::ast::parse_list::<wit_parser::ast::Flag, <wit_parser::ast::TypeDef>::parse_flags::{closure#0}>
Line
Count
Source
1623
759
fn parse_list<'a, T>(
1624
759
    tokens: &mut Tokenizer<'a>,
1625
759
    start: Token,
1626
759
    end: Token,
1627
759
    parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1628
759
) -> ParseResult<Vec<T>> {
1629
759
    tokens.expect(start)?;
1630
759
    parse_list_trailer(tokens, end, parse)
1631
759
}
wit_parser::ast::parse_list::<wit_parser::ast::Type, <wit_parser::ast::Type>::parse_at_depth::{closure#0}>
Line
Count
Source
1623
23.8k
fn parse_list<'a, T>(
1624
23.8k
    tokens: &mut Tokenizer<'a>,
1625
23.8k
    start: Token,
1626
23.8k
    end: Token,
1627
23.8k
    parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1628
23.8k
) -> ParseResult<Vec<T>> {
1629
23.8k
    tokens.expect(start)?;
1630
23.8k
    parse_list_trailer(tokens, end, parse)
1631
23.8k
}
wit_parser::ast::parse_list::<wit_parser::ast::Field, <wit_parser::ast::TypeDef>::parse_record::{closure#0}>
Line
Count
Source
1623
2.17k
fn parse_list<'a, T>(
1624
2.17k
    tokens: &mut Tokenizer<'a>,
1625
2.17k
    start: Token,
1626
2.17k
    end: Token,
1627
2.17k
    parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1628
2.17k
) -> ParseResult<Vec<T>> {
1629
2.17k
    tokens.expect(start)?;
1630
2.17k
    parse_list_trailer(tokens, end, parse)
1631
2.17k
}
wit_parser::ast::parse_list::<wit_parser::ast::EnumCase, <wit_parser::ast::TypeDef>::parse_enum::{closure#0}>
Line
Count
Source
1623
10.8k
fn parse_list<'a, T>(
1624
10.8k
    tokens: &mut Tokenizer<'a>,
1625
10.8k
    start: Token,
1626
10.8k
    end: Token,
1627
10.8k
    parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1628
10.8k
) -> ParseResult<Vec<T>> {
1629
10.8k
    tokens.expect(start)?;
1630
10.8k
    parse_list_trailer(tokens, end, parse)
1631
10.8k
}
1632
1633
63.4k
fn parse_list_trailer<'a, T>(
1634
63.4k
    tokens: &mut Tokenizer<'a>,
1635
63.4k
    end: Token,
1636
63.4k
    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637
63.4k
) -> ParseResult<Vec<T>> {
1638
63.4k
    let mut items = Vec::new();
1639
    loop {
1640
        // get docs before we skip them to try to eat the end token
1641
242k
        let docs = parse_docs(tokens)?;
1642
1643
        // if we found an end token then we're done
1644
242k
        if tokens.eat(end)? {
1645
23.0k
            break;
1646
219k
        }
1647
1648
219k
        let item = parse(docs, tokens)?;
1649
219k
        items.push(item);
1650
1651
        // if there's no trailing comma then this is required to be the end,
1652
        // otherwise we go through the loop to try to get another item
1653
219k
        if !tokens.eat(Token::Comma)? {
1654
40.4k
            tokens.expect(end)?;
1655
40.4k
            break;
1656
178k
        }
1657
    }
1658
63.4k
    Ok(items)
1659
63.4k
}
Unexecuted instantiation: wit_parser::ast::parse_list_trailer::<wit_parser::ast::IncludeName, <wit_parser::ast::Include>::parse::{closure#0}>
wit_parser::ast::parse_list_trailer::<wit_parser::ast::Case, <wit_parser::ast::TypeDef>::parse_variant::{closure#0}>
Line
Count
Source
1633
5.48k
fn parse_list_trailer<'a, T>(
1634
5.48k
    tokens: &mut Tokenizer<'a>,
1635
5.48k
    end: Token,
1636
5.48k
    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637
5.48k
) -> ParseResult<Vec<T>> {
1638
5.48k
    let mut items = Vec::new();
1639
    loop {
1640
        // get docs before we skip them to try to eat the end token
1641
24.8k
        let docs = parse_docs(tokens)?;
1642
1643
        // if we found an end token then we're done
1644
24.8k
        if tokens.eat(end)? {
1645
5.48k
            break;
1646
19.3k
        }
1647
1648
19.3k
        let item = parse(docs, tokens)?;
1649
19.3k
        items.push(item);
1650
1651
        // if there's no trailing comma then this is required to be the end,
1652
        // otherwise we go through the loop to try to get another item
1653
19.3k
        if !tokens.eat(Token::Comma)? {
1654
0
            tokens.expect(end)?;
1655
0
            break;
1656
19.3k
        }
1657
    }
1658
5.48k
    Ok(items)
1659
5.48k
}
wit_parser::ast::parse_list_trailer::<wit_parser::ast::Flag, <wit_parser::ast::TypeDef>::parse_flags::{closure#0}>
Line
Count
Source
1633
759
fn parse_list_trailer<'a, T>(
1634
759
    tokens: &mut Tokenizer<'a>,
1635
759
    end: Token,
1636
759
    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637
759
) -> ParseResult<Vec<T>> {
1638
759
    let mut items = Vec::new();
1639
    loop {
1640
        // get docs before we skip them to try to eat the end token
1641
3.20k
        let docs = parse_docs(tokens)?;
1642
1643
        // if we found an end token then we're done
1644
3.20k
        if tokens.eat(end)? {
1645
759
            break;
1646
2.45k
        }
1647
1648
2.45k
        let item = parse(docs, tokens)?;
1649
2.45k
        items.push(item);
1650
1651
        // if there's no trailing comma then this is required to be the end,
1652
        // otherwise we go through the loop to try to get another item
1653
2.45k
        if !tokens.eat(Token::Comma)? {
1654
0
            tokens.expect(end)?;
1655
0
            break;
1656
2.45k
        }
1657
    }
1658
759
    Ok(items)
1659
759
}
wit_parser::ast::parse_list_trailer::<wit_parser::ast::Type, <wit_parser::ast::Type>::parse_at_depth::{closure#0}>
Line
Count
Source
1633
23.8k
fn parse_list_trailer<'a, T>(
1634
23.8k
    tokens: &mut Tokenizer<'a>,
1635
23.8k
    end: Token,
1636
23.8k
    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637
23.8k
) -> ParseResult<Vec<T>> {
1638
23.8k
    let mut items = Vec::new();
1639
    loop {
1640
        // get docs before we skip them to try to eat the end token
1641
86.3k
        let docs = parse_docs(tokens)?;
1642
1643
        // if we found an end token then we're done
1644
86.3k
        if tokens.eat(end)? {
1645
0
            break;
1646
86.3k
        }
1647
1648
86.3k
        let item = parse(docs, tokens)?;
1649
86.3k
        items.push(item);
1650
1651
        // if there's no trailing comma then this is required to be the end,
1652
        // otherwise we go through the loop to try to get another item
1653
86.3k
        if !tokens.eat(Token::Comma)? {
1654
23.8k
            tokens.expect(end)?;
1655
23.8k
            break;
1656
62.5k
        }
1657
    }
1658
23.8k
    Ok(items)
1659
23.8k
}
wit_parser::ast::parse_list_trailer::<wit_parser::ast::Field, <wit_parser::ast::TypeDef>::parse_record::{closure#0}>
Line
Count
Source
1633
2.17k
fn parse_list_trailer<'a, T>(
1634
2.17k
    tokens: &mut Tokenizer<'a>,
1635
2.17k
    end: Token,
1636
2.17k
    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637
2.17k
) -> ParseResult<Vec<T>> {
1638
2.17k
    let mut items = Vec::new();
1639
    loop {
1640
        // get docs before we skip them to try to eat the end token
1641
9.92k
        let docs = parse_docs(tokens)?;
1642
1643
        // if we found an end token then we're done
1644
9.92k
        if tokens.eat(end)? {
1645
2.17k
            break;
1646
7.74k
        }
1647
1648
7.74k
        let item = parse(docs, tokens)?;
1649
7.74k
        items.push(item);
1650
1651
        // if there's no trailing comma then this is required to be the end,
1652
        // otherwise we go through the loop to try to get another item
1653
7.74k
        if !tokens.eat(Token::Comma)? {
1654
0
            tokens.expect(end)?;
1655
0
            break;
1656
7.74k
        }
1657
    }
1658
2.17k
    Ok(items)
1659
2.17k
}
wit_parser::ast::parse_list_trailer::<wit_parser::ast::EnumCase, <wit_parser::ast::TypeDef>::parse_enum::{closure#0}>
Line
Count
Source
1633
10.8k
fn parse_list_trailer<'a, T>(
1634
10.8k
    tokens: &mut Tokenizer<'a>,
1635
10.8k
    end: Token,
1636
10.8k
    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637
10.8k
) -> ParseResult<Vec<T>> {
1638
10.8k
    let mut items = Vec::new();
1639
    loop {
1640
        // get docs before we skip them to try to eat the end token
1641
68.3k
        let docs = parse_docs(tokens)?;
1642
1643
        // if we found an end token then we're done
1644
68.3k
        if tokens.eat(end)? {
1645
10.8k
            break;
1646
57.5k
        }
1647
1648
57.5k
        let item = parse(docs, tokens)?;
1649
57.5k
        items.push(item);
1650
1651
        // if there's no trailing comma then this is required to be the end,
1652
        // otherwise we go through the loop to try to get another item
1653
57.5k
        if !tokens.eat(Token::Comma)? {
1654
0
            tokens.expect(end)?;
1655
0
            break;
1656
57.5k
        }
1657
    }
1658
10.8k
    Ok(items)
1659
10.8k
}
wit_parser::ast::parse_list_trailer::<(wit_parser::ast::Id, wit_parser::ast::Type), <wit_parser::ast::ResourceFunc>::parse::{closure#0}>
Line
Count
Source
1633
526
fn parse_list_trailer<'a, T>(
1634
526
    tokens: &mut Tokenizer<'a>,
1635
526
    end: Token,
1636
526
    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637
526
) -> ParseResult<Vec<T>> {
1638
526
    let mut items = Vec::new();
1639
    loop {
1640
        // get docs before we skip them to try to eat the end token
1641
1.16k
        let docs = parse_docs(tokens)?;
1642
1643
        // if we found an end token then we're done
1644
1.16k
        if tokens.eat(end)? {
1645
216
            break;
1646
946
        }
1647
1648
946
        let item = parse(docs, tokens)?;
1649
946
        items.push(item);
1650
1651
        // if there's no trailing comma then this is required to be the end,
1652
        // otherwise we go through the loop to try to get another item
1653
946
        if !tokens.eat(Token::Comma)? {
1654
310
            tokens.expect(end)?;
1655
310
            break;
1656
636
        }
1657
    }
1658
526
    Ok(items)
1659
526
}
wit_parser::ast::parse_list_trailer::<(wit_parser::ast::Id, wit_parser::ast::Type), <wit_parser::ast::Func>::parse::parse_params::{closure#0}>
Line
Count
Source
1633
19.8k
fn parse_list_trailer<'a, T>(
1634
19.8k
    tokens: &mut Tokenizer<'a>,
1635
19.8k
    end: Token,
1636
19.8k
    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637
19.8k
) -> ParseResult<Vec<T>> {
1638
19.8k
    let mut items = Vec::new();
1639
    loop {
1640
        // get docs before we skip them to try to eat the end token
1641
48.3k
        let docs = parse_docs(tokens)?;
1642
1643
        // if we found an end token then we're done
1644
48.3k
        if tokens.eat(end)? {
1645
3.54k
            break;
1646
44.8k
        }
1647
1648
44.8k
        let item = parse(docs, tokens)?;
1649
44.8k
        items.push(item);
1650
1651
        // if there's no trailing comma then this is required to be the end,
1652
        // otherwise we go through the loop to try to get another item
1653
44.8k
        if !tokens.eat(Token::Comma)? {
1654
16.3k
            tokens.expect(end)?;
1655
16.3k
            break;
1656
28.4k
        }
1657
    }
1658
19.8k
    Ok(items)
1659
19.8k
}
1660
1661
0
fn err_expected(
1662
0
    tokens: &Tokenizer<'_>,
1663
0
    expected: &'static str,
1664
0
    found: Option<(Span, Token)>,
1665
0
) -> ParseError {
1666
0
    match found {
1667
0
        Some((span, token)) => ParseError::new_syntax(
1668
0
            span,
1669
0
            format!("expected {}, found {}", expected, token.describe()),
1670
        ),
1671
        None => {
1672
0
            ParseError::new_syntax(tokens.eof_span(), format!("expected {expected}, found eof"))
1673
        }
1674
    }
1675
0
}
1676
1677
enum Attribute<'a> {
1678
    Since { span: Span, version: Version },
1679
    Unstable { span: Span, feature: Id<'a> },
1680
    Deprecated { span: Span, version: Version },
1681
    ExternalId { span: Span, id: String },
1682
}
1683
1684
impl<'a> Attribute<'a> {
1685
138k
    fn parse_list(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<Attribute<'a>>> {
1686
138k
        let mut ret = Vec::new();
1687
210k
        while tokens.eat(Token::At)? {
1688
72.3k
            let id = parse_id(tokens)?;
1689
72.3k
            let attr = match id.name {
1690
72.3k
                "since" => {
1691
2.04k
                    tokens.expect(Token::LeftParen)?;
1692
2.04k
                    eat_id(tokens, "version")?;
1693
2.04k
                    tokens.expect(Token::Equals)?;
1694
2.04k
                    let (_span, version) = parse_version(tokens)?;
1695
2.04k
                    tokens.expect(Token::RightParen)?;
1696
2.04k
                    Attribute::Since {
1697
2.04k
                        span: id.span,
1698
2.04k
                        version,
1699
2.04k
                    }
1700
                }
1701
70.3k
                "unstable" => {
1702
834
                    tokens.expect(Token::LeftParen)?;
1703
834
                    eat_id(tokens, "feature")?;
1704
834
                    tokens.expect(Token::Equals)?;
1705
834
                    let feature = parse_id(tokens)?;
1706
834
                    tokens.expect(Token::RightParen)?;
1707
834
                    Attribute::Unstable {
1708
834
                        span: id.span,
1709
834
                        feature,
1710
834
                    }
1711
                }
1712
69.4k
                "deprecated" => {
1713
715
                    tokens.expect(Token::LeftParen)?;
1714
715
                    eat_id(tokens, "version")?;
1715
715
                    tokens.expect(Token::Equals)?;
1716
715
                    let (_span, version) = parse_version(tokens)?;
1717
715
                    tokens.expect(Token::RightParen)?;
1718
715
                    Attribute::Deprecated {
1719
715
                        span: id.span,
1720
715
                        version,
1721
715
                    }
1722
                }
1723
68.7k
                "external-id" => {
1724
68.7k
                    tokens.expect(Token::LeftParen)?;
1725
68.7k
                    let span = tokens.expect(Token::StringLiteral)?;
1726
68.7k
                    tokens.expect(Token::RightParen)?;
1727
                    Attribute::ExternalId {
1728
68.7k
                        span: id.span,
1729
68.7k
                        id: tokens.string_literal(span)?,
1730
                    }
1731
                }
1732
0
                other => {
1733
0
                    return Err(ParseError::new_syntax(
1734
0
                        id.span,
1735
0
                        format!("unknown attribute `{other}`"),
1736
0
                    ));
1737
                }
1738
            };
1739
72.3k
            ret.push(attr);
1740
        }
1741
138k
        Ok(ret)
1742
138k
    }
1743
}
1744
1745
3.59k
fn eat_id(tokens: &mut Tokenizer<'_>, expected: &str) -> ParseResult<Span> {
1746
3.59k
    let id = parse_id(tokens)?;
1747
3.59k
    if id.name != expected {
1748
0
        return Err(ParseError::new_syntax(
1749
0
            id.span,
1750
0
            format!("expected `{expected}`, found `{}`", id.name),
1751
0
        ));
1752
3.59k
    }
1753
3.59k
    Ok(id.span)
1754
3.59k
}
1755
1756
/// A listing of source files which are used to get parsed into an
1757
/// [`UnresolvedPackage`].
1758
///
1759
/// [`UnresolvedPackage`]: crate::UnresolvedPackage
1760
#[derive(Clone, Default, Debug, PartialEq, Eq)]
1761
pub struct SourceMap {
1762
    sources: Vec<Source>,
1763
    offset: u32,
1764
}
1765
1766
#[derive(Clone, Debug, PartialEq, Eq)]
1767
struct Source {
1768
    offset: u32,
1769
    path: String,
1770
    contents: String,
1771
}
1772
1773
impl SourceMap {
1774
    /// Creates a new empty source map.
1775
5.62k
    pub fn new() -> SourceMap {
1776
5.62k
        SourceMap::default()
1777
5.62k
    }
1778
1779
    /// Reads the file `path` on the filesystem and appends its contents to this
1780
    /// [`SourceMap`].
1781
    #[cfg(feature = "std")]
1782
0
    pub fn push_file(&mut self, path: &Path) -> anyhow::Result<()> {
1783
0
        let contents = std::fs::read_to_string(path)
1784
0
            .with_context(|| format!("failed to read file {path:?}"))?;
1785
0
        self.push(path, contents);
1786
0
        Ok(())
1787
0
    }
1788
1789
    /// Reads all `*.wit` files in the directory `path` (non-recursively) and
1790
    /// appends their contents to this [`SourceMap`].
1791
    ///
1792
    /// Subdirectories, non-`*.wit` files, and symlinks to directories are
1793
    /// ignored. Note that a `deps` subdirectory is not probed here; that is
1794
    /// handled by [`crate::Resolve::push_dir`].
1795
    #[cfg(feature = "std")]
1796
0
    pub fn push_dir(&mut self, path: &Path) -> anyhow::Result<()> {
1797
0
        let cx = || format!("failed to read directory {path:?}");
1798
0
        for entry in path.read_dir().with_context(&cx)? {
1799
0
            let entry = entry.with_context(&cx)?;
1800
0
            let entry_path = entry.path();
1801
0
            let ty = entry.file_type().with_context(&cx)?;
1802
0
            if ty.is_dir() {
1803
0
                continue;
1804
0
            }
1805
0
            if ty.is_symlink() {
1806
0
                if entry_path.is_dir() {
1807
0
                    continue;
1808
0
                }
1809
0
            }
1810
0
            let filename = match entry_path.file_name().and_then(|s| s.to_str()) {
1811
0
                Some(name) => name,
1812
0
                None => continue,
1813
            };
1814
0
            if !filename.ends_with(".wit") {
1815
0
                continue;
1816
0
            }
1817
0
            self.push_file(&entry_path)?;
1818
        }
1819
0
        Ok(())
1820
0
    }
1821
1822
    /// Appends the given contents with the given path into this source map.
1823
    ///
1824
    /// The `path` provided is not read from the filesystem and is instead only
1825
    /// used during error messages. Each file added to a [`SourceMap`] is
1826
    /// used to create the final parsed package namely by unioning all the
1827
    /// interfaces and worlds defined together. Note that each file has its own
1828
    /// personal namespace, however, for top-level `use` and such.
1829
    #[cfg(feature = "std")]
1830
13.1k
    pub fn push(&mut self, path: &Path, contents: impl Into<String>) {
1831
13.1k
        self.push_str(&path.display().to_string(), contents);
1832
13.1k
    }
<wit_parser::ast::SourceMap>::push::<&alloc::string::String>
Line
Count
Source
1830
13.1k
    pub fn push(&mut self, path: &Path, contents: impl Into<String>) {
1831
13.1k
        self.push_str(&path.display().to_string(), contents);
1832
13.1k
    }
Unexecuted instantiation: <wit_parser::ast::SourceMap>::push::<alloc::string::String>
Unexecuted instantiation: <wit_parser::ast::SourceMap>::push::<&str>
1833
1834
    /// Appends the given contents with the given source name into this source map.
1835
    ///
1836
    /// The `path` provided is not read from the filesystem and is instead only
1837
    /// used during error messages. Each file added to a [`SourceMap`] is
1838
    /// used to create the final parsed package namely by unioning all the
1839
    /// interfaces and worlds defined together. Note that each file has its own
1840
    /// personal namespace, however, for top-level `use` and such.
1841
17.0k
    pub fn push_str(&mut self, path: &str, contents: impl Into<String>) {
1842
17.0k
        let mut contents = contents.into();
1843
        // Guarantee that there's at least one character in these contents by
1844
        // appending a single newline to the end. This is excluded from
1845
        // tokenization below so it's only here to ensure that spans which point
1846
        // one byte beyond the end of a file (eof) point to the same original
1847
        // file.
1848
17.0k
        contents.push('\n');
1849
17.0k
        let new_offset = self.offset + u32::try_from(contents.len()).unwrap();
1850
17.0k
        self.sources.push(Source {
1851
17.0k
            offset: self.offset,
1852
17.0k
            path: path.to_string(),
1853
17.0k
            contents,
1854
17.0k
        });
1855
17.0k
        self.offset = new_offset;
1856
17.0k
    }
<wit_parser::ast::SourceMap>::push_str::<&alloc::string::String>
Line
Count
Source
1841
13.1k
    pub fn push_str(&mut self, path: &str, contents: impl Into<String>) {
1842
13.1k
        let mut contents = contents.into();
1843
        // Guarantee that there's at least one character in these contents by
1844
        // appending a single newline to the end. This is excluded from
1845
        // tokenization below so it's only here to ensure that spans which point
1846
        // one byte beyond the end of a file (eof) point to the same original
1847
        // file.
1848
13.1k
        contents.push('\n');
1849
13.1k
        let new_offset = self.offset + u32::try_from(contents.len()).unwrap();
1850
13.1k
        self.sources.push(Source {
1851
13.1k
            offset: self.offset,
1852
13.1k
            path: path.to_string(),
1853
13.1k
            contents,
1854
13.1k
        });
1855
13.1k
        self.offset = new_offset;
1856
13.1k
    }
Unexecuted instantiation: <wit_parser::ast::SourceMap>::push_str::<alloc::string::String>
<wit_parser::ast::SourceMap>::push_str::<&str>
Line
Count
Source
1841
3.90k
    pub fn push_str(&mut self, path: &str, contents: impl Into<String>) {
1842
3.90k
        let mut contents = contents.into();
1843
        // Guarantee that there's at least one character in these contents by
1844
        // appending a single newline to the end. This is excluded from
1845
        // tokenization below so it's only here to ensure that spans which point
1846
        // one byte beyond the end of a file (eof) point to the same original
1847
        // file.
1848
3.90k
        contents.push('\n');
1849
3.90k
        let new_offset = self.offset + u32::try_from(contents.len()).unwrap();
1850
3.90k
        self.sources.push(Source {
1851
3.90k
            offset: self.offset,
1852
3.90k
            path: path.to_string(),
1853
3.90k
            contents,
1854
3.90k
        });
1855
3.90k
        self.offset = new_offset;
1856
3.90k
    }
1857
1858
    /// Appends all sources from another `SourceMap` into this one.
1859
    ///
1860
    /// Returns the byte offset that should be added to all `Span.start` and
1861
    /// `Span.end` values from the appended source map to make them valid
1862
    /// in the combined source map.
1863
15.4k
    pub fn append(&mut self, other: SourceMap) -> u32 {
1864
15.4k
        let base = self.offset;
1865
16.9k
        for mut source in other.sources {
1866
16.9k
            source.offset += base;
1867
16.9k
            self.sources.push(source);
1868
16.9k
        }
1869
15.4k
        self.offset += other.offset;
1870
15.4k
        base
1871
15.4k
    }
1872
1873
    /// Parses the files added to this source map into a
1874
    /// [`UnresolvedPackageGroup`].
1875
    ///
1876
    /// On failure returns `Err((self, e))` so the caller can use the source
1877
    /// map for error formatting if needed.
1878
9.51k
    pub fn parse(self) -> Result<UnresolvedPackageGroup, (Self, ParseError)> {
1879
9.51k
        match self.parse_inner() {
1880
9.51k
            Ok((main, nested)) => Ok(UnresolvedPackageGroup {
1881
9.51k
                main,
1882
9.51k
                nested,
1883
9.51k
                source_map: self,
1884
9.51k
            }),
1885
0
            Err(e) => Err((self, e)),
1886
        }
1887
9.51k
    }
1888
1889
9.51k
    fn parse_inner(&self) -> ParseResult<(UnresolvedPackage, Vec<UnresolvedPackage>)> {
1890
9.51k
        let mut nested = Vec::new();
1891
9.51k
        let mut resolver = Resolver::default();
1892
9.51k
        let mut srcs = self.sources.iter().collect::<Vec<_>>();
1893
9.51k
        srcs.sort_by_key(|src| &src.path);
1894
1895
        // Parse each source file individually. A tokenizer is created here
1896
        // from settings and then `PackageFile` is used to parse the whole
1897
        // stream of tokens.
1898
16.9k
        for src in srcs {
1899
16.9k
            let mut tokens = Tokenizer::new(
1900
                // chop off the forcibly appended `\n` character when
1901
                // passing through the source to get tokenized.
1902
16.9k
                &src.contents[..src.contents.len() - 1],
1903
16.9k
                src.offset,
1904
0
            )?;
1905
16.9k
            let mut file = PackageFile::parse(&mut tokens)?;
1906
1907
            // Filter out any nested packages and resolve them separately.
1908
            // Nested packages have only a single "file" so only one item
1909
            // is pushed into a `Resolver`. Note that a nested `Resolver`
1910
            // is used here, not the outer one.
1911
            //
1912
            // Note that filtering out `Package` items is required due to
1913
            // how the implementation of disallowing nested packages in
1914
            // nested packages currently works.
1915
57.1k
            for item in mem::take(&mut file.decl_list.items) {
1916
57.1k
                match item {
1917
620
                    AstItem::Package(nested_pkg) => {
1918
620
                        let mut resolve = Resolver::default();
1919
620
                        resolve.push(nested_pkg)?;
1920
620
                        nested.push(resolve.resolve()?);
1921
                    }
1922
56.5k
                    other => file.decl_list.items.push(other),
1923
                }
1924
            }
1925
1926
            // With nested packages handled push this file into the resolver.
1927
16.9k
            resolver.push(file)?;
1928
        }
1929
1930
9.51k
        Ok((resolver.resolve()?, nested))
1931
9.51k
    }
1932
1933
0
    pub(crate) fn highlight_span(&self, span: Span, err: impl fmt::Display) -> Option<String> {
1934
0
        if !span.is_known() {
1935
0
            return None;
1936
0
        }
1937
0
        Some(self.highlight_err(span.start(), Some(span.end()), err))
1938
0
    }
Unexecuted instantiation: <wit_parser::ast::SourceMap>::highlight_span::<&wit_parser::ast::error::ParseErrorKind>
Unexecuted instantiation: <wit_parser::ast::SourceMap>::highlight_span::<&alloc::string::String>
1939
1940
0
    fn highlight_err(&self, start: u32, end: Option<u32>, err: impl fmt::Display) -> String {
1941
0
        let src = self.source_for_offset(start);
1942
0
        let start = src.to_relative_offset(start);
1943
0
        let end = end.map(|end| src.to_relative_offset(end));
Unexecuted instantiation: <wit_parser::ast::SourceMap>::highlight_err::<&wit_parser::ast::error::ParseErrorKind>::{closure#0}
Unexecuted instantiation: <wit_parser::ast::SourceMap>::highlight_err::<&alloc::string::String>::{closure#0}
1944
0
        let (line, col) = src.linecol(start);
1945
0
        let snippet = src.contents.lines().nth(line).unwrap_or("");
1946
0
        let line = line + 1;
1947
0
        let col = col + 1;
1948
1949
        // If the snippet is too large then don't overload output on a terminal
1950
        // for example and instead just print the error. This also sidesteps
1951
        // Rust's restriction that `>0$` below has to be less than `u16::MAX`.
1952
0
        if snippet.len() > 500 {
1953
0
            return format!("{}:{line}:{col}: {err}", src.path);
1954
0
        }
1955
0
        let mut msg = format!(
1956
            "\
1957
{err}
1958
     --> {file}:{line}:{col}
1959
      |
1960
 {line:4} | {snippet}
1961
      | {marker:>0$}",
1962
            col,
1963
            file = src.path,
1964
            marker = "^",
1965
        );
1966
0
        if let Some(end) = end {
1967
0
            if let Some(s) = src.contents.get(start..end) {
1968
0
                for _ in s.chars().skip(1) {
1969
0
                    msg.push('-');
1970
0
                }
1971
0
            }
1972
0
        }
1973
0
        return msg;
1974
0
    }
Unexecuted instantiation: <wit_parser::ast::SourceMap>::highlight_err::<&wit_parser::ast::error::ParseErrorKind>
Unexecuted instantiation: <wit_parser::ast::SourceMap>::highlight_err::<&alloc::string::String>
1975
1976
    /// Resolves a global `span` to a location within a single source file.
1977
    ///
1978
    /// Returns the path the source was registered with and the span's byte
1979
    /// range (UTF-8) relative to that file's contents. Returns `None` if
1980
    /// `span` is unknown or does not fall within any source in this map.
1981
0
    pub fn resolve_span(&self, span: Span) -> Option<SpanLocation<'_>> {
1982
0
        if !span.is_known() || span.start() >= self.offset {
1983
0
            return None;
1984
0
        }
1985
0
        let src = self.source_for_offset(span.start());
1986
        // Exclude the synthetic `\n` appended by `push_str` so that spans
1987
        // pointing at eof resolve to an empty range at the end of the file.
1988
0
        let len = src.contents.len() - 1;
1989
0
        let start = src.to_relative_offset(span.start()).min(len);
1990
0
        let end = usize::try_from(span.end().saturating_sub(src.offset))
1991
0
            .unwrap()
1992
0
            .clamp(start, len);
1993
0
        Some(SpanLocation {
1994
0
            path: &src.path,
1995
0
            range: start..end,
1996
0
        })
1997
0
    }
1998
1999
    /// Renders a span as a human-readable location string (e.g., "file.wit:10:5").
2000
0
    pub fn render_location(&self, span: Span) -> String {
2001
0
        if !span.is_known() {
2002
0
            return "<unknown>".to_string();
2003
0
        }
2004
0
        let start = span.start();
2005
0
        let src = self.source_for_offset(start);
2006
0
        let rel_start = src.to_relative_offset(start);
2007
0
        let (line, col) = src.linecol(rel_start);
2008
0
        format!(
2009
            "{file}:{line}:{col}",
2010
            file = src.path,
2011
0
            line = line + 1,
2012
0
            col = col + 1,
2013
        )
2014
0
    }
2015
2016
0
    fn source_for_offset(&self, start: u32) -> &Source {
2017
0
        let i = match self.sources.binary_search_by_key(&start, |src| src.offset) {
2018
0
            Ok(i) => i,
2019
0
            Err(i) => i - 1,
2020
        };
2021
0
        &self.sources[i]
2022
0
    }
2023
2024
    /// Returns an iterator over all filenames added to this source map.
2025
    #[cfg(feature = "std")]
2026
0
    pub fn source_files(&self) -> impl Iterator<Item = &Path> {
2027
0
        self.sources.iter().map(|src| Path::new(&src.path))
2028
0
    }
2029
2030
    /// Returns an iterator over all source names added to this source map.
2031
9.49k
    pub fn source_names(&self) -> impl Iterator<Item = &str> {
2032
16.8k
        self.sources.iter().map(|src| src.path.as_str())
2033
9.49k
    }
2034
}
2035
2036
/// A [`Span`] resolved to a location within a single source file.
2037
#[derive(Clone, Debug, PartialEq, Eq)]
2038
pub struct SpanLocation<'a> {
2039
    /// The path of the source, as it was registered with the [`SourceMap`].
2040
    pub path: &'a str,
2041
    /// The byte range (UTF-8) within the file's contents.
2042
    pub range: core::ops::Range<usize>,
2043
}
2044
2045
impl Source {
2046
0
    fn to_relative_offset(&self, offset: u32) -> usize {
2047
0
        usize::try_from(offset - self.offset).unwrap()
2048
0
    }
2049
2050
0
    fn linecol(&self, relative_offset: usize) -> (usize, usize) {
2051
0
        let mut cur = 0;
2052
        // Use split_terminator instead of lines so that if there is a `\r`,
2053
        // it is included in the offset calculation. The `+1` values below
2054
        // account for the `\n`.
2055
0
        for (i, line) in self.contents.split_terminator('\n').enumerate() {
2056
0
            if cur + line.len() + 1 > relative_offset {
2057
0
                return (i, relative_offset - cur);
2058
0
            }
2059
0
            cur += line.len() + 1;
2060
        }
2061
0
        (self.contents.lines().count(), 0)
2062
0
    }
2063
}
2064
2065
pub enum ParsedUsePath {
2066
    Name(String),
2067
    Package(crate::PackageName, String),
2068
}
2069
2070
0
pub fn parse_use_path(s: &str) -> anyhow::Result<ParsedUsePath> {
2071
0
    let mut tokens = Tokenizer::new(s, 0)?;
2072
0
    let path = UsePath::parse(&mut tokens)?;
2073
0
    if tokens.next()?.is_some() {
2074
0
        anyhow::bail!("trailing tokens in path specifier");
2075
0
    }
2076
0
    Ok(match path {
2077
0
        UsePath::Id(id) => ParsedUsePath::Name(id.name.to_string()),
2078
0
        UsePath::Package { id, name } => {
2079
0
            ParsedUsePath::Package(id.package_name(), name.name.to_string())
2080
        }
2081
    })
2082
0
}
2083
2084
#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
2085
#[cfg_attr(
2086
    feature = "serde",
2087
    derive(serde_derive::Serialize, serde_derive::Deserialize)
2088
)]
2089
#[cfg_attr(feature = "serde", serde(into = "String", try_from = "String"))]
2090
/// The fully-qualified name of a Component Model item (function,
2091
/// type, or resource) as can be defined by wit. An item is optionally in a
2092
/// package, the package optionally has a version, and the item is optionally
2093
/// inside a namespace.
2094
///
2095
/// The syntax for an ItemName always uses the package version as a suffix, if
2096
/// it is given. The following tests show examples of the syntax for ItemName:
2097
/// ```rust
2098
/// # use wit_parser::{ItemName, PackageName};
2099
/// assert_eq!(
2100
///     "foo".parse::<ItemName>().unwrap(),
2101
///     ItemName {
2102
///         package: None,
2103
///         interface: None,
2104
///         name: "foo".to_owned()
2105
///     }
2106
/// );
2107
/// assert_eq!(
2108
///     "foo.bar".parse::<ItemName>().unwrap(),
2109
///     ItemName {
2110
///         package: None,
2111
///         interface: Some("foo".to_owned()),
2112
///         name: "bar".to_owned()
2113
///     }
2114
/// );
2115
/// assert_eq!(
2116
///     "foo:bar/baz".parse::<ItemName>().unwrap(),
2117
///     ItemName {
2118
///         package: Some(PackageName {
2119
///             namespace: "foo".to_owned(),
2120
///             name: "bar".to_owned(),
2121
///             version: None
2122
///         }),
2123
///         interface: None,
2124
///         name: "baz".to_owned()
2125
///     }
2126
/// );
2127
/// assert_eq!(
2128
///     "foo:bar/baz@0.1.0".parse::<ItemName>().unwrap(),
2129
///     ItemName {
2130
///         package: Some(PackageName {
2131
///             namespace: "foo".to_owned(),
2132
///             name: "bar".to_owned(),
2133
///             version: Some("0.1.0".parse().unwrap())
2134
///         }),
2135
///         interface: None,
2136
///         name: "baz".to_owned()
2137
///     }
2138
/// );
2139
/// assert_eq!(
2140
///     "foo:bar/baz.bat".parse::<ItemName>().unwrap(),
2141
///     ItemName {
2142
///         package: Some(PackageName {
2143
///             namespace: "foo".to_owned(),
2144
///             name: "bar".to_owned(),
2145
///             version: None
2146
///         }),
2147
///         interface: Some("baz".to_owned()),
2148
///         name: "bat".to_owned()
2149
///     }
2150
/// );
2151
/// assert_eq!(
2152
///     "foo:bar/baz.bat@0.1.0".parse::<ItemName>().unwrap(),
2153
///     ItemName {
2154
///         package: Some(PackageName {
2155
///             namespace: "foo".to_owned(),
2156
///             name: "bar".to_owned(),
2157
///             version: Some("0.1.0".parse().unwrap()),
2158
///         }),
2159
///         interface: Some("baz".to_owned()),
2160
///         name: "bat".to_owned()
2161
///     }
2162
/// );
2163
/// assert!("foo@0.1.0".parse::<ItemName>().is_err());
2164
/// assert!("foo:bar@0.1.0".parse::<ItemName>().is_err());
2165
/// assert!("foo:bar/baz@0.1.0.bat".parse::<ItemName>().is_err());
2166
/// assert!("foo.bar@0.1.0".parse::<ItemName>().is_err());
2167
/// assert!("foo@0.1.0.bar".parse::<ItemName>().is_err());
2168
/// ```
2169
///
2170
/// Parse this from a string using its [`FromStr`](core::str::FromStr) or
2171
/// [`TryFrom<String>`](core::convert::TryFrom) impls.
2172
/// [`Display`](core::fmt::Display) to render to the same string syntax.
2173
pub struct ItemName {
2174
    pub package: Option<crate::PackageName>,
2175
    pub interface: Option<String>,
2176
    pub name: String,
2177
}
2178
impl ItemName {
2179
    /// Get the name of the component instance containing this item, if any.
2180
    /// The instance name will be formed like:
2181
    /// "namespace.packagename/interfacename@0.1.0"
2182
    /// ```rust
2183
    /// # use wit_parser::ItemName;
2184
    /// assert_eq!(
2185
    ///     "foo".parse::<ItemName>().unwrap().instance_name(),
2186
    ///     None,
2187
    /// );
2188
    /// assert_eq!(
2189
    ///     "foo.bar".parse::<ItemName>().unwrap().instance_name(),
2190
    ///     Some("foo".to_owned())
2191
    /// );
2192
    /// assert_eq!(
2193
    ///     "foo:bar/baz.bat@0.1.0".parse::<ItemName>().unwrap().instance_name(),
2194
    ///     Some("foo:bar/baz@0.1.0".to_owned())
2195
    /// );
2196
    /// ```
2197
0
    pub fn instance_name(&self) -> Option<String> {
2198
0
        if self.package.is_none() && self.interface.is_none() {
2199
0
            return None;
2200
0
        }
2201
0
        let mut s = String::new();
2202
        if let Some(crate::PackageName {
2203
0
            namespace, name, ..
2204
0
        }) = &self.package
2205
0
        {
2206
0
            s.push_str(&format!("{namespace}:{name}/"));
2207
0
        }
2208
0
        if let Some(name) = &self.interface {
2209
0
            s.push_str(&format!("{name}"));
2210
0
        }
2211
        if let Some(crate::PackageName {
2212
0
            version: Some(version),
2213
            ..
2214
0
        }) = &self.package
2215
0
        {
2216
0
            s.push_str(&format!("@{version}"));
2217
0
        }
2218
0
        Some(s)
2219
0
    }
2220
}
2221
impl core::str::FromStr for ItemName {
2222
    type Err = anyhow::Error;
2223
0
    fn from_str(s: &str) -> anyhow::Result<ItemName> {
2224
0
        let mut tokens = Tokenizer::new(s, 0)?;
2225
2226
0
        let id = parse_id(&mut tokens)?;
2227
0
        let (package, name) = if tokens.eat(Token::Colon)? {
2228
0
            let name = parse_id(&mut tokens)?;
2229
0
            tokens.expect(Token::Slash)?;
2230
0
            (Some((id, name)), parse_id(&mut tokens)?)
2231
        } else {
2232
0
            (None, id)
2233
        };
2234
        let interface;
2235
0
        let name = if tokens.eat(Token::Period)? {
2236
0
            interface = Some(name.name.to_string());
2237
0
            parse_id(&mut tokens)?
2238
        } else {
2239
0
            interface = None;
2240
0
            name
2241
        };
2242
2243
0
        let package = package
2244
0
            .map(|(namespace, name)| -> anyhow::Result<crate::PackageName> {
2245
0
                let version = parse_opt_version(&mut tokens)?;
2246
                Ok(PackageName {
2247
0
                    docs: Docs::default(),
2248
0
                    span: Span::new(
2249
0
                        namespace.span.start(),
2250
0
                        version
2251
0
                            .as_ref()
2252
0
                            .map(|(s, _)| s.end())
2253
0
                            .unwrap_or(name.span.end()),
2254
                    ),
2255
0
                    namespace,
2256
0
                    name,
2257
0
                    version,
2258
                }
2259
0
                .package_name())
2260
0
            })
2261
0
            .transpose()?;
2262
2263
0
        if tokens.next()?.is_some() {
2264
0
            anyhow::bail!("trailing tokens in item name specifier");
2265
0
        }
2266
0
        Ok(ItemName {
2267
0
            package,
2268
0
            interface,
2269
0
            name: name.name.to_string(),
2270
0
        })
2271
0
    }
2272
}
2273
impl core::convert::TryFrom<String> for ItemName {
2274
    type Error = anyhow::Error;
2275
0
    fn try_from(s: String) -> anyhow::Result<ItemName> {
2276
0
        s.parse()
2277
0
    }
2278
}
2279
impl fmt::Display for ItemName {
2280
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2281
        if let Some(crate::PackageName {
2282
0
            namespace, name, ..
2283
0
        }) = &self.package
2284
        {
2285
0
            write!(f, "{namespace}:{name}/")?;
2286
0
        }
2287
0
        if let Some(int) = &self.interface {
2288
0
            write!(f, "{int}.")?;
2289
0
        }
2290
0
        write!(f, "{}", self.name)?;
2291
        if let Some(crate::PackageName {
2292
0
            version: Some(version),
2293
            ..
2294
0
        }) = &self.package
2295
        {
2296
0
            write!(f, "@{version}")?;
2297
0
        }
2298
0
        Ok(())
2299
0
    }
2300
}
2301
impl From<ItemName> for String {
2302
0
    fn from(m: ItemName) -> String {
2303
0
        m.to_string()
2304
0
    }
2305
}
2306
2307
#[cfg(test)]
2308
mod item_name_test {
2309
    use super::{ItemName, Version};
2310
    use crate::PackageName;
2311
    use alloc::borrow::ToOwned;
2312
2313
    fn assert_round_trip(s: &str) {
2314
        use alloc::string::ToString;
2315
        let i = s.parse::<ItemName>().unwrap();
2316
        assert_eq!(i.to_string(), s);
2317
    }
2318
2319
    #[test]
2320
    fn bare() {
2321
        assert_eq!(
2322
            "bare-kebab-name".parse::<ItemName>().unwrap(),
2323
            ItemName {
2324
                package: None,
2325
                interface: None,
2326
                name: "bare-kebab-name".to_owned()
2327
            }
2328
        );
2329
        assert_round_trip("bare-kebab-name");
2330
        // Invalid to have a version without a package name
2331
        assert!("bare-kebab-name@0.1.0".parse::<ItemName>().is_err());
2332
    }
2333
    #[test]
2334
    fn in_interface() {
2335
        assert_eq!(
2336
            "foo.bar".parse::<ItemName>().unwrap(),
2337
            ItemName {
2338
                package: None,
2339
                interface: Some("foo".to_owned()),
2340
                name: "bar".to_owned()
2341
            }
2342
        );
2343
        assert_round_trip("foo.bar");
2344
        // Invalid to have a version without a package name
2345
        assert!("foo.bar@0.1.0".parse::<ItemName>().is_err());
2346
    }
2347
    #[test]
2348
    fn in_package() {
2349
        assert_eq!(
2350
            "foo:bar/baz.bat".parse::<ItemName>().unwrap(),
2351
            ItemName {
2352
                package: Some(PackageName {
2353
                    namespace: "foo".to_owned(),
2354
                    name: "bar".to_owned(),
2355
                    version: None
2356
                }),
2357
                interface: Some("baz".to_owned()),
2358
                name: "bat".to_owned()
2359
            }
2360
        );
2361
        assert_round_trip("foo:bar/baz.bat");
2362
        assert_eq!(
2363
            "foo:bar/baz.bat@0.1.0".parse::<ItemName>().unwrap(),
2364
            ItemName {
2365
                package: Some(PackageName {
2366
                    namespace: "foo".to_owned(),
2367
                    name: "bar".to_owned(),
2368
                    version: Some(Version::parse("0.1.0").unwrap()),
2369
                }),
2370
                interface: Some("baz".to_owned()),
2371
                name: "bat".to_owned()
2372
            }
2373
        );
2374
        assert_round_trip("foo:bar/baz.bat@0.1.0");
2375
        assert_eq!(
2376
            "foo:bar/baz".parse::<ItemName>().unwrap(),
2377
            ItemName {
2378
                package: Some(PackageName {
2379
                    namespace: "foo".to_owned(),
2380
                    name: "bar".to_owned(),
2381
                    version: None
2382
                }),
2383
                interface: None,
2384
                name: "baz".to_owned()
2385
            }
2386
        );
2387
        assert_round_trip("foo:bar/baz@0.1.0");
2388
        assert_eq!(
2389
            "foo:bar/baz@0.1.0".parse::<ItemName>().unwrap(),
2390
            ItemName {
2391
                package: Some(PackageName {
2392
                    namespace: "foo".to_owned(),
2393
                    name: "bar".to_owned(),
2394
                    version: Some(Version::parse("0.1.0").unwrap()),
2395
                }),
2396
                interface: None,
2397
                name: "baz".to_owned()
2398
            }
2399
        );
2400
    }
2401
}