Skip to main content

wit_parser/
ast.rs

1use crate::ast::error::ParseError;
2use crate::{ParseResult, UnresolvedPackage, UnresolvedPackageGroup};
3use alloc::borrow::Cow;
4use alloc::boxed::Box;
5use alloc::format;
6use alloc::string::{String, ToString};
7use alloc::vec::Vec;
8#[cfg(feature = "std")]
9use anyhow::Context as _;
10use core::fmt;
11use core::mem;
12use core::result::Result;
13use lex::{Span, Token, Tokenizer};
14use semver::Version;
15#[cfg(feature = "std")]
16use std::path::Path;
17
18pub mod error;
19pub mod lex;
20
21pub use resolve::Resolver;
22mod resolve;
23pub mod toposort;
24
25pub use lex::validate_id;
26
27/// Representation of a single WIT `*.wit` file and nested packages.
28struct 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.
36const MAX_ITEM_DEPTH: usize = 100;
37
38impl<'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    fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
44        let mut package_name_tokens_peek = tokens.clone();
45        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        let package_id = if package_name_tokens_peek.eat(Token::Package)? {
50            let name = PackageName::parse(&mut package_name_tokens_peek, docs)?;
51            if package_name_tokens_peek.eat(Token::Semicolon)? {
52                *tokens = package_name_tokens_peek;
53                Some(name)
54            } else {
55                None
56            }
57        } else {
58            None
59        };
60        let decl_list = DeclList::parse_until(tokens, None, 0)?;
61        Ok(PackageFile {
62            package_id,
63            decl_list,
64        })
65    }
66
67    /// Parse a nested package of the form `package foo:bar { ... }`
68    fn parse_nested(
69        tokens: &mut Tokenizer<'a>,
70        docs: Docs<'a>,
71        attributes: Vec<Attribute<'a>>,
72        depth: usize,
73    ) -> ParseResult<Self> {
74        let span = tokens.expect(Token::Package)?;
75        if !attributes.is_empty() {
76            return Err(ParseError::new_syntax(
77                span,
78                format!("cannot place attributes on nested packages"),
79            ));
80        }
81        if depth >= MAX_ITEM_DEPTH {
82            return Err(ParseError::new_syntax(span, "package nesting too deep"));
83        }
84        let package_id = PackageName::parse(tokens, docs)?;
85        tokens.expect(Token::LeftBrace)?;
86        let decl_list = DeclList::parse_until(tokens, Some(Token::RightBrace), depth + 1)?;
87        Ok(PackageFile {
88            package_id: Some(package_id),
89            decl_list,
90        })
91    }
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)]
130pub struct DeclList<'a> {
131    items: Vec<AstItem<'a>>,
132}
133
134impl<'a> DeclList<'a> {
135    fn parse_until(
136        tokens: &mut Tokenizer<'a>,
137        end: Option<Token>,
138        depth: usize,
139    ) -> ParseResult<DeclList<'a>> {
140        let mut items = Vec::new();
141        let mut docs = parse_docs(tokens)?;
142        loop {
143            match end {
144                Some(end) => {
145                    if tokens.eat(end)? {
146                        break;
147                    }
148                }
149                None => {
150                    if tokens.clone().next()?.is_none() {
151                        break;
152                    }
153                }
154            }
155            items.push(AstItem::parse(tokens, docs, depth)?);
156            docs = parse_docs(tokens)?;
157        }
158        Ok(DeclList { items })
159    }
160
161    fn for_each_path<'b>(
162        &'b self,
163        f: &mut dyn FnMut(
164            Option<&'b Id<'a>>,
165            &'b [Attribute<'a>],
166            &'b UsePath<'a>,
167            Option<&'b [UseName<'a>]>,
168            WorldOrInterface,
169        ) -> ParseResult<()>,
170    ) -> ParseResult<()> {
171        for item in self.items.iter() {
172            match item {
173                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                    let mut imports = Vec::new();
179                    let mut exports = Vec::new();
180                    for item in world.items.iter() {
181                        match item {
182                            WorldItem::Use(u) => f(
183                                None,
184                                &u.attributes,
185                                &u.from,
186                                Some(&u.names),
187                                WorldOrInterface::Interface,
188                            )?,
189                            WorldItem::Include(i) => f(
190                                Some(&world.name),
191                                &i.attributes,
192                                &i.from,
193                                None,
194                                WorldOrInterface::World,
195                            )?,
196                            WorldItem::Type(_) => {}
197                            WorldItem::Import(Import {
198                                kind, attributes, ..
199                            }) => imports.push((kind, attributes)),
200                            WorldItem::Export(Export {
201                                kind, attributes, ..
202                            }) => exports.push((kind, attributes)),
203                        }
204                    }
205
206                    let mut visit_kind =
207                        |kind: &'b ExternKind<'a>, attrs: &'b [Attribute<'a>]| match kind {
208                            ExternKind::Interface(_, items) => {
209                                for item in items {
210                                    match item {
211                                        InterfaceItem::Use(u) => f(
212                                            None,
213                                            &u.attributes,
214                                            &u.from,
215                                            Some(&u.names),
216                                            WorldOrInterface::Interface,
217                                        )?,
218                                        _ => {}
219                                    }
220                                }
221                                Ok(())
222                            }
223                            ExternKind::Path(path) | ExternKind::NamedPath(_, path) => {
224                                f(None, attrs, path, None, WorldOrInterface::Interface)
225                            }
226                            ExternKind::Func(..) => Ok(()),
227                        };
228
229                    for (kind, attrs) in imports {
230                        visit_kind(kind, attrs)?;
231                    }
232                    for (kind, attrs) in exports {
233                        visit_kind(kind, attrs)?;
234                    }
235                }
236                AstItem::Interface(i) => {
237                    for item in i.items.iter() {
238                        match item {
239                            InterfaceItem::Use(u) => f(
240                                Some(&i.name),
241                                &u.attributes,
242                                &u.from,
243                                Some(&u.names),
244                                WorldOrInterface::Interface,
245                            )?,
246                            _ => {}
247                        }
248                    }
249                }
250                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                    f(
254                        None,
255                        &u.attributes,
256                        &u.item,
257                        None,
258                        WorldOrInterface::Unknown,
259                    )?;
260                }
261
262                AstItem::Package(pkg) => pkg.decl_list.for_each_path(f)?,
263            }
264        }
265        Ok(())
266    }
267}
268
269enum AstItem<'a> {
270    Interface(Interface<'a>),
271    World(World<'a>),
272    Use(ToplevelUse<'a>),
273    Package(PackageFile<'a>),
274}
275
276impl<'a> AstItem<'a> {
277    fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>, depth: usize) -> ParseResult<Self> {
278        let attributes = Attribute::parse_list(tokens)?;
279        match tokens.clone().next()? {
280            Some((_span, Token::Interface)) => {
281                Interface::parse(tokens, docs, attributes).map(Self::Interface)
282            }
283            Some((_span, Token::World)) => World::parse(tokens, docs, attributes).map(Self::World),
284            Some((_span, Token::Use)) => ToplevelUse::parse(tokens, attributes).map(Self::Use),
285            Some((_span, Token::Package)) => {
286                PackageFile::parse_nested(tokens, docs, attributes, depth).map(Self::Package)
287            }
288            other => Err(err_expected(tokens, "`world`, `interface` or `use`", other).into()),
289        }
290    }
291}
292
293#[derive(Debug, Clone)]
294struct PackageName<'a> {
295    docs: Docs<'a>,
296    span: Span,
297    namespace: Id<'a>,
298    name: Id<'a>,
299    version: Option<(Span, Version)>,
300}
301
302impl<'a> PackageName<'a> {
303    fn parse(tokens: &mut Tokenizer<'a>, docs: Docs<'a>) -> ParseResult<Self> {
304        let namespace = parse_id(tokens)?;
305        tokens.expect(Token::Colon)?;
306        let name = parse_id(tokens)?;
307        let version = parse_opt_version(tokens)?;
308        Ok(PackageName {
309            docs,
310            span: Span::new(
311                namespace.span.start(),
312                version
313                    .as_ref()
314                    .map(|(s, _)| s.end())
315                    .unwrap_or(name.span.end()),
316            ),
317            namespace,
318            name,
319            version,
320        })
321    }
322
323    fn package_name(&self) -> crate::PackageName {
324        crate::PackageName {
325            namespace: self.namespace.name.to_string(),
326            name: self.name.name.to_string(),
327            version: self.version.as_ref().map(|(_, v)| v.clone()),
328        }
329    }
330}
331
332struct ToplevelUse<'a> {
333    span: Span,
334    attributes: Vec<Attribute<'a>>,
335    item: UsePath<'a>,
336    as_: Option<Id<'a>>,
337}
338
339impl<'a> ToplevelUse<'a> {
340    fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
341        let span = tokens.expect(Token::Use)?;
342        let item = UsePath::parse(tokens)?;
343        let as_ = if tokens.eat(Token::As)? {
344            Some(parse_id(tokens)?)
345        } else {
346            None
347        };
348        tokens.expect_semicolon()?;
349        Ok(ToplevelUse {
350            span,
351            attributes,
352            item,
353            as_,
354        })
355    }
356}
357
358struct World<'a> {
359    docs: Docs<'a>,
360    attributes: Vec<Attribute<'a>>,
361    name: Id<'a>,
362    items: Vec<WorldItem<'a>>,
363}
364
365impl<'a> World<'a> {
366    fn parse(
367        tokens: &mut Tokenizer<'a>,
368        docs: Docs<'a>,
369        attributes: Vec<Attribute<'a>>,
370    ) -> ParseResult<Self> {
371        tokens.expect(Token::World)?;
372        let name = parse_id(tokens)?;
373        let items = Self::parse_items(tokens)?;
374        Ok(World {
375            docs,
376            attributes,
377            name,
378            items,
379        })
380    }
381
382    fn parse_items(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<WorldItem<'a>>> {
383        tokens.expect(Token::LeftBrace)?;
384        let mut items = Vec::new();
385        loop {
386            let docs = parse_docs(tokens)?;
387            if tokens.eat(Token::RightBrace)? {
388                break;
389            }
390            let attributes = Attribute::parse_list(tokens)?;
391            items.push(WorldItem::parse(tokens, docs, attributes)?);
392        }
393        Ok(items)
394    }
395}
396
397enum WorldItem<'a> {
398    Import(Import<'a>),
399    Export(Export<'a>),
400    Use(Use<'a>),
401    Type(TypeDef<'a>),
402    Include(Include<'a>),
403}
404
405impl<'a> WorldItem<'a> {
406    fn parse(
407        tokens: &mut Tokenizer<'a>,
408        docs: Docs<'a>,
409        attributes: Vec<Attribute<'a>>,
410    ) -> ParseResult<WorldItem<'a>> {
411        match tokens.clone().next()? {
412            Some((_span, Token::Import)) => {
413                Import::parse(tokens, docs, attributes).map(WorldItem::Import)
414            }
415            Some((_span, Token::Export)) => {
416                Export::parse(tokens, docs, attributes).map(WorldItem::Export)
417            }
418            Some((_span, Token::Use)) => Use::parse(tokens, attributes).map(WorldItem::Use),
419            Some((_span, Token::Type)) => {
420                TypeDef::parse(tokens, docs, attributes).map(WorldItem::Type)
421            }
422            Some((_span, Token::Flags)) => {
423                TypeDef::parse_flags(tokens, docs, attributes).map(WorldItem::Type)
424            }
425            Some((_span, Token::Resource)) => {
426                TypeDef::parse_resource(tokens, docs, attributes).map(WorldItem::Type)
427            }
428            Some((_span, Token::Record)) => {
429                TypeDef::parse_record(tokens, docs, attributes).map(WorldItem::Type)
430            }
431            Some((_span, Token::Variant)) => {
432                TypeDef::parse_variant(tokens, docs, attributes).map(WorldItem::Type)
433            }
434            Some((_span, Token::Enum)) => {
435                TypeDef::parse_enum(tokens, docs, attributes).map(WorldItem::Type)
436            }
437            Some((_span, Token::Include)) => {
438                Include::parse(tokens, attributes).map(WorldItem::Include)
439            }
440            other => Err(err_expected(
441                tokens,
442                "`import`, `export`, `include`, `use`, or type definition",
443                other,
444            )
445            .into()),
446        }
447    }
448}
449
450struct Import<'a> {
451    docs: Docs<'a>,
452    attributes: Vec<Attribute<'a>>,
453    kind: ExternKind<'a>,
454}
455
456impl<'a> Import<'a> {
457    fn parse(
458        tokens: &mut Tokenizer<'a>,
459        docs: Docs<'a>,
460        attributes: Vec<Attribute<'a>>,
461    ) -> ParseResult<Import<'a>> {
462        tokens.expect(Token::Import)?;
463        let kind = ExternKind::parse(tokens)?;
464        Ok(Import {
465            docs,
466            attributes,
467            kind,
468        })
469    }
470}
471
472struct Export<'a> {
473    docs: Docs<'a>,
474    attributes: Vec<Attribute<'a>>,
475    kind: ExternKind<'a>,
476}
477
478impl<'a> Export<'a> {
479    fn parse(
480        tokens: &mut Tokenizer<'a>,
481        docs: Docs<'a>,
482        attributes: Vec<Attribute<'a>>,
483    ) -> ParseResult<Export<'a>> {
484        tokens.expect(Token::Export)?;
485        let kind = ExternKind::parse(tokens)?;
486        Ok(Export {
487            docs,
488            attributes,
489            kind,
490        })
491    }
492}
493
494enum 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
502impl<'a> ExternKind<'a> {
503    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        let mut clone = tokens.clone();
513        let id = parse_id(&mut clone)?;
514        if clone.eat(Token::Colon)? {
515            // import foo: async? func(...)
516            if clone.clone().eat(Token::Func)? || clone.clone().eat(Token::Async)? {
517                *tokens = clone;
518                let ret = ExternKind::Func(id, Func::parse(tokens)?);
519                tokens.expect_semicolon()?;
520                return Ok(ret);
521            }
522
523            // import foo: interface { ... }
524            if clone.eat(Token::Interface)? {
525                *tokens = clone;
526                return Ok(ExternKind::Interface(id, Interface::parse_items(tokens)?));
527            }
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            let mut peek = clone.clone();
540            let is_qualified_path =
541                parse_id(&mut peek).is_ok() && peek.clone().eat(Token::Slash).unwrap_or(false);
542            if !is_qualified_path {
543                *tokens = clone;
544                let path = UsePath::parse(tokens)?;
545                tokens.expect_semicolon()?;
546                return Ok(ExternKind::NamedPath(id, path));
547            }
548        }
549
550        // import foo
551        // import foo/bar
552        // import foo:bar/baz
553        let ret = ExternKind::Path(UsePath::parse(tokens)?);
554        tokens.expect_semicolon()?;
555        Ok(ret)
556    }
557
558    fn span(&self) -> Span {
559        match self {
560            ExternKind::Interface(id, _) => id.span,
561            ExternKind::Path(UsePath::Id(id)) => id.span,
562            ExternKind::Path(UsePath::Package { name, .. }) => name.span,
563            ExternKind::Func(id, _) => id.span,
564            ExternKind::NamedPath(id, _) => id.span,
565        }
566    }
567}
568
569struct Interface<'a> {
570    docs: Docs<'a>,
571    attributes: Vec<Attribute<'a>>,
572    name: Id<'a>,
573    items: Vec<InterfaceItem<'a>>,
574}
575
576impl<'a> Interface<'a> {
577    fn parse(
578        tokens: &mut Tokenizer<'a>,
579        docs: Docs<'a>,
580        attributes: Vec<Attribute<'a>>,
581    ) -> ParseResult<Self> {
582        tokens.expect(Token::Interface)?;
583        let name = parse_id(tokens)?;
584        let items = Self::parse_items(tokens)?;
585        Ok(Interface {
586            docs,
587            attributes,
588            name,
589            items,
590        })
591    }
592
593    pub(super) fn parse_items(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<InterfaceItem<'a>>> {
594        tokens.expect(Token::LeftBrace)?;
595        let mut items = Vec::new();
596        loop {
597            let docs = parse_docs(tokens)?;
598            if tokens.eat(Token::RightBrace)? {
599                break;
600            }
601            let attributes = Attribute::parse_list(tokens)?;
602            items.push(InterfaceItem::parse(tokens, docs, attributes)?);
603        }
604        Ok(items)
605    }
606}
607
608#[derive(Debug)]
609pub enum WorldOrInterface {
610    World,
611    Interface,
612    Unknown,
613}
614
615enum InterfaceItem<'a> {
616    TypeDef(TypeDef<'a>),
617    Func(NamedFunc<'a>),
618    Use(Use<'a>),
619}
620
621struct Use<'a> {
622    attributes: Vec<Attribute<'a>>,
623    from: UsePath<'a>,
624    names: Vec<UseName<'a>>,
625}
626
627#[derive(Debug)]
628enum UsePath<'a> {
629    Id(Id<'a>),
630    Package { id: PackageName<'a>, name: Id<'a> },
631}
632
633impl<'a> UsePath<'a> {
634    fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
635        let id = parse_id(tokens)?;
636        if tokens.eat(Token::Colon)? {
637            // `foo:bar/baz@1.0`
638            let namespace = id;
639            let pkg_name = parse_id(tokens)?;
640            tokens.expect(Token::Slash)?;
641            let name = parse_id(tokens)?;
642            let version = parse_opt_version(tokens)?;
643            Ok(UsePath::Package {
644                id: PackageName {
645                    docs: Default::default(),
646                    span: Span::new(namespace.span.start(), pkg_name.span.end()),
647                    namespace,
648                    name: pkg_name,
649                    version,
650                },
651                name,
652            })
653        } else {
654            // `foo`
655            Ok(UsePath::Id(id))
656        }
657    }
658
659    fn name(&self) -> &Id<'a> {
660        match self {
661            UsePath::Id(id) => id,
662            UsePath::Package { name, .. } => name,
663        }
664    }
665}
666
667struct UseName<'a> {
668    name: Id<'a>,
669    as_: Option<Id<'a>>,
670}
671
672impl<'a> Use<'a> {
673    fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
674        tokens.expect(Token::Use)?;
675        let from = UsePath::parse(tokens)?;
676        tokens.expect(Token::Period)?;
677        tokens.expect(Token::LeftBrace)?;
678
679        let mut names = Vec::new();
680        while !tokens.eat(Token::RightBrace)? {
681            let mut name = UseName {
682                name: parse_id(tokens)?,
683                as_: None,
684            };
685            if tokens.eat(Token::As)? {
686                name.as_ = Some(parse_id(tokens)?);
687            }
688            names.push(name);
689            if !tokens.eat(Token::Comma)? {
690                tokens.expect(Token::RightBrace)?;
691                break;
692            }
693        }
694        tokens.expect_semicolon()?;
695        Ok(Use {
696            attributes,
697            from,
698            names,
699        })
700    }
701}
702
703struct Include<'a> {
704    from: UsePath<'a>,
705    attributes: Vec<Attribute<'a>>,
706    names: Vec<IncludeName<'a>>,
707}
708
709struct IncludeName<'a> {
710    name: Id<'a>,
711    as_: Id<'a>,
712}
713
714impl<'a> Include<'a> {
715    fn parse(tokens: &mut Tokenizer<'a>, attributes: Vec<Attribute<'a>>) -> ParseResult<Self> {
716        tokens.expect(Token::Include)?;
717        let from = UsePath::parse(tokens)?;
718
719        let names = if tokens.eat(Token::With)? {
720            parse_list(
721                tokens,
722                Token::LeftBrace,
723                Token::RightBrace,
724                |_docs, tokens| {
725                    let name = parse_id(tokens)?;
726                    tokens.expect(Token::As)?;
727                    let as_ = parse_id(tokens)?;
728                    Ok(IncludeName { name, as_ })
729                },
730            )?
731        } else {
732            tokens.expect_semicolon()?;
733            Vec::new()
734        };
735
736        Ok(Include {
737            attributes,
738            from,
739            names,
740        })
741    }
742}
743
744#[derive(Debug, Clone)]
745pub struct Id<'a> {
746    name: &'a str,
747    span: Span,
748}
749
750impl<'a> From<&'a str> for Id<'a> {
751    fn from(s: &'a str) -> Id<'a> {
752        Id {
753            name: s.into(),
754            span: Default::default(),
755        }
756    }
757}
758
759#[derive(Debug, Clone)]
760pub struct Docs<'a> {
761    docs: Vec<Cow<'a, str>>,
762    span: Span,
763}
764
765impl<'a> Default for Docs<'a> {
766    fn default() -> Self {
767        Self {
768            docs: Default::default(),
769            span: Default::default(),
770        }
771    }
772}
773
774struct TypeDef<'a> {
775    docs: Docs<'a>,
776    attributes: Vec<Attribute<'a>>,
777    name: Id<'a>,
778    ty: Type<'a>,
779}
780
781enum 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
813enum Handle<'a> {
814    Own { resource: Id<'a> },
815    Borrow { resource: Id<'a> },
816}
817
818impl Handle<'_> {
819    fn span(&self) -> Span {
820        match self {
821            Handle::Own { resource } | Handle::Borrow { resource } => resource.span,
822        }
823    }
824}
825
826struct Resource<'a> {
827    span: Span,
828    funcs: Vec<ResourceFunc<'a>>,
829}
830
831enum ResourceFunc<'a> {
832    Method(NamedFunc<'a>),
833    Static(NamedFunc<'a>),
834    Constructor(NamedFunc<'a>),
835}
836
837impl<'a> ResourceFunc<'a> {
838    fn parse(
839        docs: Docs<'a>,
840        attributes: Vec<Attribute<'a>>,
841        tokens: &mut Tokenizer<'a>,
842    ) -> ParseResult<Self> {
843        match tokens.clone().next()? {
844            Some((span, Token::Constructor)) => {
845                tokens.expect(Token::Constructor)?;
846                tokens.expect(Token::LeftParen)?;
847                let params = parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
848                    let name = parse_id(tokens)?;
849                    tokens.expect(Token::Colon)?;
850                    let ty = Type::parse(tokens)?;
851                    Ok((name, ty))
852                })?;
853                let result = if tokens.eat(Token::RArrow)? {
854                    let ty = Type::parse(tokens)?;
855                    Some(ty)
856                } else {
857                    None
858                };
859                tokens.expect_semicolon()?;
860                Ok(ResourceFunc::Constructor(NamedFunc {
861                    docs,
862                    attributes,
863                    name: Id {
864                        span,
865                        name: "constructor",
866                    },
867                    func: Func {
868                        span,
869                        async_: false,
870                        params,
871                        result,
872                    },
873                }))
874            }
875            Some((_span, Token::Id | Token::ExplicitId)) => {
876                let name = parse_id(tokens)?;
877                tokens.expect(Token::Colon)?;
878                let ctor = if tokens.eat(Token::Static)? {
879                    ResourceFunc::Static
880                } else {
881                    ResourceFunc::Method
882                };
883                let func = Func::parse(tokens)?;
884                tokens.expect_semicolon()?;
885                Ok(ctor(NamedFunc {
886                    docs,
887                    attributes,
888                    name,
889                    func,
890                }))
891            }
892            other => Err(err_expected(tokens, "`constructor` or identifier", other).into()),
893        }
894    }
895
896    fn named_func(&self) -> &NamedFunc<'a> {
897        use ResourceFunc::*;
898        match self {
899            Method(f) | Static(f) | Constructor(f) => f,
900        }
901    }
902}
903
904struct Record<'a> {
905    span: Span,
906    fields: Vec<Field<'a>>,
907}
908
909struct Field<'a> {
910    docs: Docs<'a>,
911    name: Id<'a>,
912    ty: Type<'a>,
913}
914
915struct Flags<'a> {
916    span: Span,
917    flags: Vec<Flag<'a>>,
918}
919
920struct Flag<'a> {
921    docs: Docs<'a>,
922    name: Id<'a>,
923}
924
925struct Variant<'a> {
926    span: Span,
927    cases: Vec<Case<'a>>,
928}
929
930struct Case<'a> {
931    docs: Docs<'a>,
932    name: Id<'a>,
933    ty: Option<Type<'a>>,
934}
935
936struct Enum<'a> {
937    span: Span,
938    cases: Vec<EnumCase<'a>>,
939}
940
941struct EnumCase<'a> {
942    docs: Docs<'a>,
943    name: Id<'a>,
944}
945
946struct Option_<'a> {
947    span: Span,
948    ty: Box<Type<'a>>,
949}
950
951struct List<'a> {
952    span: Span,
953    ty: Box<Type<'a>>,
954}
955
956struct Map<'a> {
957    span: Span,
958    key: Box<Type<'a>>,
959    value: Box<Type<'a>>,
960}
961
962struct FixedLengthList<'a> {
963    span: Span,
964    ty: Box<Type<'a>>,
965    size: u32,
966}
967
968struct Future<'a> {
969    span: Span,
970    ty: Option<Box<Type<'a>>>,
971}
972
973struct Tuple<'a> {
974    span: Span,
975    types: Vec<Type<'a>>,
976}
977
978struct Result_<'a> {
979    span: Span,
980    ok: Option<Box<Type<'a>>>,
981    err: Option<Box<Type<'a>>>,
982}
983
984struct Stream<'a> {
985    span: Span,
986    ty: Option<Box<Type<'a>>>,
987}
988
989struct NamedFunc<'a> {
990    docs: Docs<'a>,
991    attributes: Vec<Attribute<'a>>,
992    name: Id<'a>,
993    func: Func<'a>,
994}
995
996type ParamList<'a> = Vec<(Id<'a>, Type<'a>)>;
997
998struct Func<'a> {
999    span: Span,
1000    async_: bool,
1001    params: ParamList<'a>,
1002    result: Option<Type<'a>>,
1003}
1004
1005impl<'a> Func<'a> {
1006    fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Func<'a>> {
1007        fn parse_params<'a>(
1008            tokens: &mut Tokenizer<'a>,
1009            left_paren: bool,
1010        ) -> ParseResult<ParamList<'a>> {
1011            if left_paren {
1012                tokens.expect(Token::LeftParen)?;
1013            };
1014            parse_list_trailer(tokens, Token::RightParen, |_docs, tokens| {
1015                let name = parse_id(tokens)?;
1016                tokens.expect(Token::Colon)?;
1017                let ty = Type::parse(tokens)?;
1018                Ok((name, ty))
1019            })
1020        }
1021
1022        let async_ = tokens.eat(Token::Async)?;
1023        let span = tokens.expect(Token::Func)?;
1024        let params = parse_params(tokens, true)?;
1025        let result = if tokens.eat(Token::RArrow)? {
1026            let ty = Type::parse(tokens)?;
1027            Some(ty)
1028        } else {
1029            None
1030        };
1031        Ok(Func {
1032            span,
1033            async_,
1034            params,
1035            result,
1036        })
1037    }
1038}
1039
1040impl<'a> InterfaceItem<'a> {
1041    fn parse(
1042        tokens: &mut Tokenizer<'a>,
1043        docs: Docs<'a>,
1044        attributes: Vec<Attribute<'a>>,
1045    ) -> ParseResult<InterfaceItem<'a>> {
1046        match tokens.clone().next()? {
1047            Some((_span, Token::Type)) => {
1048                TypeDef::parse(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1049            }
1050            Some((_span, Token::Flags)) => {
1051                TypeDef::parse_flags(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1052            }
1053            Some((_span, Token::Enum)) => {
1054                TypeDef::parse_enum(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1055            }
1056            Some((_span, Token::Variant)) => {
1057                TypeDef::parse_variant(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1058            }
1059            Some((_span, Token::Resource)) => {
1060                TypeDef::parse_resource(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1061            }
1062            Some((_span, Token::Record)) => {
1063                TypeDef::parse_record(tokens, docs, attributes).map(InterfaceItem::TypeDef)
1064            }
1065            Some((_span, Token::Id)) | Some((_span, Token::ExplicitId)) => {
1066                NamedFunc::parse(tokens, docs, attributes).map(InterfaceItem::Func)
1067            }
1068            Some((_span, Token::Use)) => Use::parse(tokens, attributes).map(InterfaceItem::Use),
1069            other => Err(err_expected(tokens, "`type`, `resource` or `func`", other).into()),
1070        }
1071    }
1072}
1073
1074impl<'a> TypeDef<'a> {
1075    fn parse(
1076        tokens: &mut Tokenizer<'a>,
1077        docs: Docs<'a>,
1078        attributes: Vec<Attribute<'a>>,
1079    ) -> ParseResult<Self> {
1080        tokens.expect(Token::Type)?;
1081        let name = parse_id(tokens)?;
1082        tokens.expect(Token::Equals)?;
1083        let ty = Type::parse(tokens)?;
1084        tokens.expect_semicolon()?;
1085        Ok(TypeDef {
1086            docs,
1087            attributes,
1088            name,
1089            ty,
1090        })
1091    }
1092
1093    fn parse_flags(
1094        tokens: &mut Tokenizer<'a>,
1095        docs: Docs<'a>,
1096        attributes: Vec<Attribute<'a>>,
1097    ) -> ParseResult<Self> {
1098        tokens.expect(Token::Flags)?;
1099        let name = parse_id(tokens)?;
1100        let ty = Type::Flags(Flags {
1101            span: name.span,
1102            flags: parse_list(
1103                tokens,
1104                Token::LeftBrace,
1105                Token::RightBrace,
1106                |docs, tokens| {
1107                    let name = parse_id(tokens)?;
1108                    Ok(Flag { docs, name })
1109                },
1110            )?,
1111        });
1112        Ok(TypeDef {
1113            docs,
1114            attributes,
1115            name,
1116            ty,
1117        })
1118    }
1119
1120    fn parse_resource(
1121        tokens: &mut Tokenizer<'a>,
1122        docs: Docs<'a>,
1123        attributes: Vec<Attribute<'a>>,
1124    ) -> ParseResult<Self> {
1125        tokens.expect(Token::Resource)?;
1126        let name = parse_id(tokens)?;
1127        let mut funcs = Vec::new();
1128        if tokens.eat(Token::LeftBrace)? {
1129            while !tokens.eat(Token::RightBrace)? {
1130                let docs = parse_docs(tokens)?;
1131                let attributes = Attribute::parse_list(tokens)?;
1132                funcs.push(ResourceFunc::parse(docs, attributes, tokens)?);
1133            }
1134        } else {
1135            tokens.expect_semicolon()?;
1136        }
1137        let ty = Type::Resource(Resource {
1138            span: name.span,
1139            funcs,
1140        });
1141        Ok(TypeDef {
1142            docs,
1143            attributes,
1144            name,
1145            ty,
1146        })
1147    }
1148
1149    fn parse_record(
1150        tokens: &mut Tokenizer<'a>,
1151        docs: Docs<'a>,
1152        attributes: Vec<Attribute<'a>>,
1153    ) -> ParseResult<Self> {
1154        tokens.expect(Token::Record)?;
1155        let name = parse_id(tokens)?;
1156        let ty = Type::Record(Record {
1157            span: name.span,
1158            fields: parse_list(
1159                tokens,
1160                Token::LeftBrace,
1161                Token::RightBrace,
1162                |docs, tokens| {
1163                    let name = parse_id(tokens)?;
1164                    tokens.expect(Token::Colon)?;
1165                    let ty = Type::parse(tokens)?;
1166                    Ok(Field { docs, name, ty })
1167                },
1168            )?,
1169        });
1170        Ok(TypeDef {
1171            docs,
1172            attributes,
1173            name,
1174            ty,
1175        })
1176    }
1177
1178    fn parse_variant(
1179        tokens: &mut Tokenizer<'a>,
1180        docs: Docs<'a>,
1181        attributes: Vec<Attribute<'a>>,
1182    ) -> ParseResult<Self> {
1183        tokens.expect(Token::Variant)?;
1184        let name = parse_id(tokens)?;
1185        let ty = Type::Variant(Variant {
1186            span: name.span,
1187            cases: parse_list(
1188                tokens,
1189                Token::LeftBrace,
1190                Token::RightBrace,
1191                |docs, tokens| {
1192                    let name = parse_id(tokens)?;
1193                    let ty = if tokens.eat(Token::LeftParen)? {
1194                        let ty = Type::parse(tokens)?;
1195                        tokens.expect(Token::RightParen)?;
1196                        Some(ty)
1197                    } else {
1198                        None
1199                    };
1200                    Ok(Case { docs, name, ty })
1201                },
1202            )?,
1203        });
1204        Ok(TypeDef {
1205            docs,
1206            attributes,
1207            name,
1208            ty,
1209        })
1210    }
1211
1212    fn parse_enum(
1213        tokens: &mut Tokenizer<'a>,
1214        docs: Docs<'a>,
1215        attributes: Vec<Attribute<'a>>,
1216    ) -> ParseResult<Self> {
1217        tokens.expect(Token::Enum)?;
1218        let name = parse_id(tokens)?;
1219        let ty = Type::Enum(Enum {
1220            span: name.span,
1221            cases: parse_list(
1222                tokens,
1223                Token::LeftBrace,
1224                Token::RightBrace,
1225                |docs, tokens| {
1226                    let name = parse_id(tokens)?;
1227                    Ok(EnumCase { docs, name })
1228                },
1229            )?,
1230        });
1231        Ok(TypeDef {
1232            docs,
1233            attributes,
1234            name,
1235            ty,
1236        })
1237    }
1238}
1239
1240impl<'a> NamedFunc<'a> {
1241    fn parse(
1242        tokens: &mut Tokenizer<'a>,
1243        docs: Docs<'a>,
1244        attributes: Vec<Attribute<'a>>,
1245    ) -> ParseResult<Self> {
1246        let name = parse_id(tokens)?;
1247        tokens.expect(Token::Colon)?;
1248        let func = Func::parse(tokens)?;
1249        tokens.expect_semicolon()?;
1250        Ok(NamedFunc {
1251            docs,
1252            attributes,
1253            name,
1254            func,
1255        })
1256    }
1257}
1258
1259fn parse_id<'a>(tokens: &mut Tokenizer<'a>) -> ParseResult<Id<'a>> {
1260    match tokens.next()? {
1261        Some((span, Token::Id)) => Ok(Id {
1262            name: tokens.parse_id(span)?,
1263            span,
1264        }),
1265        Some((span, Token::ExplicitId)) => Ok(Id {
1266            name: tokens.parse_explicit_id(span)?,
1267            span,
1268        }),
1269        other => Err(err_expected(tokens, "an identifier or string", other)),
1270    }
1271}
1272
1273fn parse_opt_version(tokens: &mut Tokenizer<'_>) -> ParseResult<Option<(Span, Version)>> {
1274    if tokens.eat(Token::At)? {
1275        parse_version(tokens).map(Some)
1276    } else {
1277        Ok(None)
1278    }
1279}
1280
1281fn parse_version(tokens: &mut Tokenizer<'_>) -> ParseResult<(Span, Version)> {
1282    let start = tokens.expect(Token::Integer)?.start();
1283    tokens.expect(Token::Period)?;
1284    tokens.expect(Token::Integer)?;
1285    tokens.expect(Token::Period)?;
1286    let end = tokens.expect(Token::Integer)?.end();
1287    let mut span = Span::new(start, end);
1288    eat_ids(tokens, Token::Minus, &mut span)?;
1289    eat_ids(tokens, Token::Plus, &mut span)?;
1290    let string = tokens.get_span(span);
1291    let version =
1292        Version::parse(string).map_err(|e| ParseError::new_syntax(span, e.to_string()))?;
1293    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    fn eat_ids(
1349        tokens: &mut Tokenizer<'_>,
1350        prefix: Token,
1351        end: &mut Span,
1352    ) -> Result<(), lex::Error> {
1353        if !tokens.eat(prefix)? {
1354            return Ok(());
1355        }
1356        loop {
1357            let mut clone = tokens.clone();
1358            match clone.next()? {
1359                Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1360                    end.set_end(span.end());
1361                    *tokens = clone;
1362                }
1363                Some((_span, Token::Period)) => match clone.next()? {
1364                    Some((span, Token::Id | Token::Integer | Token::Minus)) => {
1365                        end.set_end(span.end());
1366                        *tokens = clone;
1367                    }
1368                    _ => break Ok(()),
1369                },
1370                _ => break Ok(()),
1371            }
1372        }
1373    }
1374}
1375
1376fn parse_docs<'a>(tokens: &mut Tokenizer<'a>) -> Result<Docs<'a>, lex::Error> {
1377    let mut docs = Docs::default();
1378    let mut clone = tokens.clone();
1379    let mut started = false;
1380    while let Some((span, token)) = clone.next_raw()? {
1381        match token {
1382            Token::Whitespace => {}
1383            Token::Comment => {
1384                let comment = tokens.get_span(span);
1385                if !started {
1386                    docs.span.set_start(span.start());
1387                    started = true;
1388                }
1389                let trailing_ws = comment
1390                    .bytes()
1391                    .rev()
1392                    .take_while(|ch| ch.is_ascii_whitespace())
1393                    .count();
1394                docs.span.set_end(span.end() - (trailing_ws as u32));
1395                docs.docs.push(comment.into());
1396            }
1397            _ => break,
1398        };
1399        *tokens = clone.clone();
1400    }
1401    Ok(docs)
1402}
1403
1404/// Maximum nesting depth of types parsed with `Type::parse`, e.g.
1405/// `list<list<list<...>>>`.
1406const MAX_TYPE_DEPTH: usize = 100;
1407
1408impl<'a> Type<'a> {
1409    fn parse(tokens: &mut Tokenizer<'a>) -> ParseResult<Self> {
1410        Type::parse_at_depth(tokens, 0)
1411    }
1412
1413    fn parse_at_depth(tokens: &mut Tokenizer<'a>, depth: usize) -> ParseResult<Self> {
1414        let token = tokens.next()?;
1415        if depth >= MAX_TYPE_DEPTH {
1416            let span = match token {
1417                Some((span, _)) => span,
1418                None => tokens.eof_span(),
1419            };
1420            return Err(ParseError::new_syntax(span, "type nesting too deep"));
1421        }
1422        match token {
1423            Some((span, Token::U8)) => Ok(Type::U8(span)),
1424            Some((span, Token::U16)) => Ok(Type::U16(span)),
1425            Some((span, Token::U32)) => Ok(Type::U32(span)),
1426            Some((span, Token::U64)) => Ok(Type::U64(span)),
1427            Some((span, Token::S8)) => Ok(Type::S8(span)),
1428            Some((span, Token::S16)) => Ok(Type::S16(span)),
1429            Some((span, Token::S32)) => Ok(Type::S32(span)),
1430            Some((span, Token::S64)) => Ok(Type::S64(span)),
1431            Some((span, Token::F32)) => Ok(Type::F32(span)),
1432            Some((span, Token::F64)) => Ok(Type::F64(span)),
1433            Some((span, Token::Char)) => Ok(Type::Char(span)),
1434
1435            // tuple<T, U, ...>
1436            Some((span, Token::Tuple)) => {
1437                let types = parse_list(
1438                    tokens,
1439                    Token::LessThan,
1440                    Token::GreaterThan,
1441                    |_docs, tokens| Type::parse_at_depth(tokens, depth + 1),
1442                )?;
1443                Ok(Type::Tuple(Tuple { span, types }))
1444            }
1445
1446            Some((span, Token::Bool)) => Ok(Type::Bool(span)),
1447            Some((span, Token::String_)) => Ok(Type::String(span)),
1448
1449            // list<T>
1450            // list<T, N>
1451            Some((span, Token::List)) => {
1452                tokens.expect(Token::LessThan)?;
1453                let ty = Type::parse_at_depth(tokens, depth + 1)?;
1454                let size = if tokens.eat(Token::Comma)? {
1455                    let number = tokens.next()?;
1456                    if let Some((span, Token::Integer)) = number {
1457                        let size: u32 = tokens.get_span(span).parse().map_err(|e| {
1458                            ParseError::new_syntax(span, format!("invalid list size: {e}"))
1459                        })?;
1460                        Some(size)
1461                    } else {
1462                        return Err(err_expected(tokens, "fixed-length", number).into());
1463                    }
1464                } else {
1465                    None
1466                };
1467                tokens.expect(Token::GreaterThan)?;
1468                if let Some(size) = size {
1469                    Ok(Type::FixedLengthList(FixedLengthList {
1470                        span,
1471                        ty: Box::new(ty),
1472                        size,
1473                    }))
1474                } else {
1475                    Ok(Type::List(List {
1476                        span,
1477                        ty: Box::new(ty),
1478                    }))
1479                }
1480            }
1481
1482            // map<K, V>
1483            Some((span, Token::Map)) => {
1484                tokens.expect(Token::LessThan)?;
1485                let key = Type::parse_at_depth(tokens, depth + 1)?;
1486                tokens.expect(Token::Comma)?;
1487                let value = Type::parse_at_depth(tokens, depth + 1)?;
1488                tokens.expect(Token::GreaterThan)?;
1489                Ok(Type::Map(Map {
1490                    span,
1491                    key: Box::new(key),
1492                    value: Box::new(value),
1493                }))
1494            }
1495
1496            // option<T>
1497            Some((span, Token::Option_)) => {
1498                tokens.expect(Token::LessThan)?;
1499                let ty = Type::parse_at_depth(tokens, depth + 1)?;
1500                tokens.expect(Token::GreaterThan)?;
1501                Ok(Type::Option(Option_ {
1502                    span,
1503                    ty: Box::new(ty),
1504                }))
1505            }
1506
1507            // result<T, E>
1508            // result<_, E>
1509            // result<T>
1510            // result
1511            Some((span, Token::Result_)) => {
1512                let mut ok = None;
1513                let mut err = None;
1514
1515                if tokens.eat(Token::LessThan)? {
1516                    if tokens.eat(Token::Underscore)? {
1517                        tokens.expect(Token::Comma)?;
1518                        err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1519                    } else {
1520                        ok = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1521                        if tokens.eat(Token::Comma)? {
1522                            err = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1523                        }
1524                    };
1525                    tokens.expect(Token::GreaterThan)?;
1526                };
1527                Ok(Type::Result(Result_ { span, ok, err }))
1528            }
1529
1530            // future<T>
1531            // future
1532            Some((span, Token::Future)) => {
1533                let mut ty = None;
1534
1535                if tokens.eat(Token::LessThan)? {
1536                    ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1537                    tokens.expect(Token::GreaterThan)?;
1538                };
1539                Ok(Type::Future(Future { span, ty }))
1540            }
1541
1542            // stream<T>
1543            // stream
1544            Some((span, Token::Stream)) => {
1545                let mut ty = None;
1546
1547                if tokens.eat(Token::LessThan)? {
1548                    ty = Some(Box::new(Type::parse_at_depth(tokens, depth + 1)?));
1549                    tokens.expect(Token::GreaterThan)?;
1550                };
1551                Ok(Type::Stream(Stream { span, ty }))
1552            }
1553
1554            // error-context
1555            Some((span, Token::ErrorContext)) => Ok(Type::ErrorContext(span)),
1556
1557            // own<T>
1558            Some((_span, Token::Own)) => {
1559                tokens.expect(Token::LessThan)?;
1560                let resource = parse_id(tokens)?;
1561                tokens.expect(Token::GreaterThan)?;
1562                Ok(Type::Handle(Handle::Own { resource }))
1563            }
1564
1565            // borrow<T>
1566            Some((_span, Token::Borrow)) => {
1567                tokens.expect(Token::LessThan)?;
1568                let resource = parse_id(tokens)?;
1569                tokens.expect(Token::GreaterThan)?;
1570                Ok(Type::Handle(Handle::Borrow { resource }))
1571            }
1572
1573            // `foo`
1574            Some((span, Token::Id)) => Ok(Type::Name(Id {
1575                name: tokens.parse_id(span)?.into(),
1576                span,
1577            })),
1578            // `%foo`
1579            Some((span, Token::ExplicitId)) => Ok(Type::Name(Id {
1580                name: tokens.parse_explicit_id(span)?.into(),
1581                span,
1582            })),
1583
1584            other => Err(err_expected(tokens, "a type", other).into()),
1585        }
1586    }
1587
1588    fn span(&self) -> Span {
1589        match self {
1590            Type::Bool(span)
1591            | Type::U8(span)
1592            | Type::U16(span)
1593            | Type::U32(span)
1594            | Type::U64(span)
1595            | Type::S8(span)
1596            | Type::S16(span)
1597            | Type::S32(span)
1598            | Type::S64(span)
1599            | Type::F32(span)
1600            | Type::F64(span)
1601            | Type::Char(span)
1602            | Type::String(span)
1603            | Type::ErrorContext(span) => *span,
1604            Type::Name(id) => id.span,
1605            Type::List(l) => l.span,
1606            Type::Map(m) => m.span,
1607            Type::FixedLengthList(l) => l.span,
1608            Type::Handle(h) => h.span(),
1609            Type::Resource(r) => r.span,
1610            Type::Record(r) => r.span,
1611            Type::Flags(f) => f.span,
1612            Type::Variant(v) => v.span,
1613            Type::Tuple(t) => t.span,
1614            Type::Enum(e) => e.span,
1615            Type::Option(o) => o.span,
1616            Type::Result(r) => r.span,
1617            Type::Future(f) => f.span,
1618            Type::Stream(s) => s.span,
1619        }
1620    }
1621}
1622
1623fn parse_list<'a, T>(
1624    tokens: &mut Tokenizer<'a>,
1625    start: Token,
1626    end: Token,
1627    parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1628) -> ParseResult<Vec<T>> {
1629    tokens.expect(start)?;
1630    parse_list_trailer(tokens, end, parse)
1631}
1632
1633fn parse_list_trailer<'a, T>(
1634    tokens: &mut Tokenizer<'a>,
1635    end: Token,
1636    mut parse: impl FnMut(Docs<'a>, &mut Tokenizer<'a>) -> ParseResult<T>,
1637) -> ParseResult<Vec<T>> {
1638    let mut items = Vec::new();
1639    loop {
1640        // get docs before we skip them to try to eat the end token
1641        let docs = parse_docs(tokens)?;
1642
1643        // if we found an end token then we're done
1644        if tokens.eat(end)? {
1645            break;
1646        }
1647
1648        let item = parse(docs, tokens)?;
1649        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        if !tokens.eat(Token::Comma)? {
1654            tokens.expect(end)?;
1655            break;
1656        }
1657    }
1658    Ok(items)
1659}
1660
1661fn err_expected(
1662    tokens: &Tokenizer<'_>,
1663    expected: &'static str,
1664    found: Option<(Span, Token)>,
1665) -> ParseError {
1666    match found {
1667        Some((span, token)) => ParseError::new_syntax(
1668            span,
1669            format!("expected {}, found {}", expected, token.describe()),
1670        ),
1671        None => {
1672            ParseError::new_syntax(tokens.eof_span(), format!("expected {expected}, found eof"))
1673        }
1674    }
1675}
1676
1677enum 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
1684impl<'a> Attribute<'a> {
1685    fn parse_list(tokens: &mut Tokenizer<'a>) -> ParseResult<Vec<Attribute<'a>>> {
1686        let mut ret = Vec::new();
1687        while tokens.eat(Token::At)? {
1688            let id = parse_id(tokens)?;
1689            let attr = match id.name {
1690                "since" => {
1691                    tokens.expect(Token::LeftParen)?;
1692                    eat_id(tokens, "version")?;
1693                    tokens.expect(Token::Equals)?;
1694                    let (_span, version) = parse_version(tokens)?;
1695                    tokens.expect(Token::RightParen)?;
1696                    Attribute::Since {
1697                        span: id.span,
1698                        version,
1699                    }
1700                }
1701                "unstable" => {
1702                    tokens.expect(Token::LeftParen)?;
1703                    eat_id(tokens, "feature")?;
1704                    tokens.expect(Token::Equals)?;
1705                    let feature = parse_id(tokens)?;
1706                    tokens.expect(Token::RightParen)?;
1707                    Attribute::Unstable {
1708                        span: id.span,
1709                        feature,
1710                    }
1711                }
1712                "deprecated" => {
1713                    tokens.expect(Token::LeftParen)?;
1714                    eat_id(tokens, "version")?;
1715                    tokens.expect(Token::Equals)?;
1716                    let (_span, version) = parse_version(tokens)?;
1717                    tokens.expect(Token::RightParen)?;
1718                    Attribute::Deprecated {
1719                        span: id.span,
1720                        version,
1721                    }
1722                }
1723                "external-id" => {
1724                    tokens.expect(Token::LeftParen)?;
1725                    let span = tokens.expect(Token::StringLiteral)?;
1726                    tokens.expect(Token::RightParen)?;
1727                    Attribute::ExternalId {
1728                        span: id.span,
1729                        id: tokens.string_literal(span)?,
1730                    }
1731                }
1732                other => {
1733                    return Err(ParseError::new_syntax(
1734                        id.span,
1735                        format!("unknown attribute `{other}`"),
1736                    ));
1737                }
1738            };
1739            ret.push(attr);
1740        }
1741        Ok(ret)
1742    }
1743}
1744
1745fn eat_id(tokens: &mut Tokenizer<'_>, expected: &str) -> ParseResult<Span> {
1746    let id = parse_id(tokens)?;
1747    if id.name != expected {
1748        return Err(ParseError::new_syntax(
1749            id.span,
1750            format!("expected `{expected}`, found `{}`", id.name),
1751        ));
1752    }
1753    Ok(id.span)
1754}
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)]
1761pub struct SourceMap {
1762    sources: Vec<Source>,
1763    offset: u32,
1764}
1765
1766#[derive(Clone, Debug, PartialEq, Eq)]
1767struct Source {
1768    offset: u32,
1769    path: String,
1770    contents: String,
1771}
1772
1773impl SourceMap {
1774    /// Creates a new empty source map.
1775    pub fn new() -> SourceMap {
1776        SourceMap::default()
1777    }
1778
1779    /// Reads the file `path` on the filesystem and appends its contents to this
1780    /// [`SourceMap`].
1781    #[cfg(feature = "std")]
1782    pub fn push_file(&mut self, path: &Path) -> anyhow::Result<()> {
1783        let contents = std::fs::read_to_string(path)
1784            .with_context(|| format!("failed to read file {path:?}"))?;
1785        self.push(path, contents);
1786        Ok(())
1787    }
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    pub fn push_dir(&mut self, path: &Path) -> anyhow::Result<()> {
1797        let cx = || format!("failed to read directory {path:?}");
1798        for entry in path.read_dir().with_context(&cx)? {
1799            let entry = entry.with_context(&cx)?;
1800            let entry_path = entry.path();
1801            let ty = entry.file_type().with_context(&cx)?;
1802            if ty.is_dir() {
1803                continue;
1804            }
1805            if ty.is_symlink() {
1806                if entry_path.is_dir() {
1807                    continue;
1808                }
1809            }
1810            let filename = match entry_path.file_name().and_then(|s| s.to_str()) {
1811                Some(name) => name,
1812                None => continue,
1813            };
1814            if !filename.ends_with(".wit") {
1815                continue;
1816            }
1817            self.push_file(&entry_path)?;
1818        }
1819        Ok(())
1820    }
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    pub fn push(&mut self, path: &Path, contents: impl Into<String>) {
1831        self.push_str(&path.display().to_string(), contents);
1832    }
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    pub fn push_str(&mut self, path: &str, contents: impl Into<String>) {
1842        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        contents.push('\n');
1849        let new_offset = self.offset + u32::try_from(contents.len()).unwrap();
1850        self.sources.push(Source {
1851            offset: self.offset,
1852            path: path.to_string(),
1853            contents,
1854        });
1855        self.offset = new_offset;
1856    }
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    pub fn append(&mut self, other: SourceMap) -> u32 {
1864        let base = self.offset;
1865        for mut source in other.sources {
1866            source.offset += base;
1867            self.sources.push(source);
1868        }
1869        self.offset += other.offset;
1870        base
1871    }
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    pub fn parse(self) -> Result<UnresolvedPackageGroup, (Self, ParseError)> {
1879        match self.parse_inner() {
1880            Ok((main, nested)) => Ok(UnresolvedPackageGroup {
1881                main,
1882                nested,
1883                source_map: self,
1884            }),
1885            Err(e) => Err((self, e)),
1886        }
1887    }
1888
1889    fn parse_inner(&self) -> ParseResult<(UnresolvedPackage, Vec<UnresolvedPackage>)> {
1890        let mut nested = Vec::new();
1891        let mut resolver = Resolver::default();
1892        let mut srcs = self.sources.iter().collect::<Vec<_>>();
1893        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        for src in srcs {
1899            let mut tokens = Tokenizer::new(
1900                // chop off the forcibly appended `\n` character when
1901                // passing through the source to get tokenized.
1902                &src.contents[..src.contents.len() - 1],
1903                src.offset,
1904            )?;
1905            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            for item in mem::take(&mut file.decl_list.items) {
1916                match item {
1917                    AstItem::Package(nested_pkg) => {
1918                        let mut resolve = Resolver::default();
1919                        resolve.push(nested_pkg)?;
1920                        nested.push(resolve.resolve()?);
1921                    }
1922                    other => file.decl_list.items.push(other),
1923                }
1924            }
1925
1926            // With nested packages handled push this file into the resolver.
1927            resolver.push(file)?;
1928        }
1929
1930        Ok((resolver.resolve()?, nested))
1931    }
1932
1933    pub(crate) fn highlight_span(&self, span: Span, err: impl fmt::Display) -> Option<String> {
1934        if !span.is_known() {
1935            return None;
1936        }
1937        Some(self.highlight_err(span.start(), Some(span.end()), err))
1938    }
1939
1940    fn highlight_err(&self, start: u32, end: Option<u32>, err: impl fmt::Display) -> String {
1941        let src = self.source_for_offset(start);
1942        let start = src.to_relative_offset(start);
1943        let end = end.map(|end| src.to_relative_offset(end));
1944        let (line, col) = src.linecol(start);
1945        let snippet = src.contents.lines().nth(line).unwrap_or("");
1946        let line = line + 1;
1947        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        if snippet.len() > 500 {
1953            return format!("{}:{line}:{col}: {err}", src.path);
1954        }
1955        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        if let Some(end) = end {
1967            if let Some(s) = src.contents.get(start..end) {
1968                for _ in s.chars().skip(1) {
1969                    msg.push('-');
1970                }
1971            }
1972        }
1973        return msg;
1974    }
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    pub fn resolve_span(&self, span: Span) -> Option<SpanLocation<'_>> {
1982        if !span.is_known() || span.start() >= self.offset {
1983            return None;
1984        }
1985        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        let len = src.contents.len() - 1;
1989        let start = src.to_relative_offset(span.start()).min(len);
1990        let end = usize::try_from(span.end().saturating_sub(src.offset))
1991            .unwrap()
1992            .clamp(start, len);
1993        Some(SpanLocation {
1994            path: &src.path,
1995            range: start..end,
1996        })
1997    }
1998
1999    /// Renders a span as a human-readable location string (e.g., "file.wit:10:5").
2000    pub fn render_location(&self, span: Span) -> String {
2001        if !span.is_known() {
2002            return "<unknown>".to_string();
2003        }
2004        let start = span.start();
2005        let src = self.source_for_offset(start);
2006        let rel_start = src.to_relative_offset(start);
2007        let (line, col) = src.linecol(rel_start);
2008        format!(
2009            "{file}:{line}:{col}",
2010            file = src.path,
2011            line = line + 1,
2012            col = col + 1,
2013        )
2014    }
2015
2016    fn source_for_offset(&self, start: u32) -> &Source {
2017        let i = match self.sources.binary_search_by_key(&start, |src| src.offset) {
2018            Ok(i) => i,
2019            Err(i) => i - 1,
2020        };
2021        &self.sources[i]
2022    }
2023
2024    /// Returns an iterator over all filenames added to this source map.
2025    #[cfg(feature = "std")]
2026    pub fn source_files(&self) -> impl Iterator<Item = &Path> {
2027        self.sources.iter().map(|src| Path::new(&src.path))
2028    }
2029
2030    /// Returns an iterator over all source names added to this source map.
2031    pub fn source_names(&self) -> impl Iterator<Item = &str> {
2032        self.sources.iter().map(|src| src.path.as_str())
2033    }
2034}
2035
2036/// A [`Span`] resolved to a location within a single source file.
2037#[derive(Clone, Debug, PartialEq, Eq)]
2038pub 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
2045impl Source {
2046    fn to_relative_offset(&self, offset: u32) -> usize {
2047        usize::try_from(offset - self.offset).unwrap()
2048    }
2049
2050    fn linecol(&self, relative_offset: usize) -> (usize, usize) {
2051        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        for (i, line) in self.contents.split_terminator('\n').enumerate() {
2056            if cur + line.len() + 1 > relative_offset {
2057                return (i, relative_offset - cur);
2058            }
2059            cur += line.len() + 1;
2060        }
2061        (self.contents.lines().count(), 0)
2062    }
2063}
2064
2065pub enum ParsedUsePath {
2066    Name(String),
2067    Package(crate::PackageName, String),
2068}
2069
2070pub fn parse_use_path(s: &str) -> anyhow::Result<ParsedUsePath> {
2071    let mut tokens = Tokenizer::new(s, 0)?;
2072    let path = UsePath::parse(&mut tokens)?;
2073    if tokens.next()?.is_some() {
2074        anyhow::bail!("trailing tokens in path specifier");
2075    }
2076    Ok(match path {
2077        UsePath::Id(id) => ParsedUsePath::Name(id.name.to_string()),
2078        UsePath::Package { id, name } => {
2079            ParsedUsePath::Package(id.package_name(), name.name.to_string())
2080        }
2081    })
2082}
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.
2173pub struct ItemName {
2174    pub package: Option<crate::PackageName>,
2175    pub interface: Option<String>,
2176    pub name: String,
2177}
2178impl 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    pub fn instance_name(&self) -> Option<String> {
2198        if self.package.is_none() && self.interface.is_none() {
2199            return None;
2200        }
2201        let mut s = String::new();
2202        if let Some(crate::PackageName {
2203            namespace, name, ..
2204        }) = &self.package
2205        {
2206            s.push_str(&format!("{namespace}:{name}/"));
2207        }
2208        if let Some(name) = &self.interface {
2209            s.push_str(&format!("{name}"));
2210        }
2211        if let Some(crate::PackageName {
2212            version: Some(version),
2213            ..
2214        }) = &self.package
2215        {
2216            s.push_str(&format!("@{version}"));
2217        }
2218        Some(s)
2219    }
2220}
2221impl core::str::FromStr for ItemName {
2222    type Err = anyhow::Error;
2223    fn from_str(s: &str) -> anyhow::Result<ItemName> {
2224        let mut tokens = Tokenizer::new(s, 0)?;
2225
2226        let id = parse_id(&mut tokens)?;
2227        let (package, name) = if tokens.eat(Token::Colon)? {
2228            let name = parse_id(&mut tokens)?;
2229            tokens.expect(Token::Slash)?;
2230            (Some((id, name)), parse_id(&mut tokens)?)
2231        } else {
2232            (None, id)
2233        };
2234        let interface;
2235        let name = if tokens.eat(Token::Period)? {
2236            interface = Some(name.name.to_string());
2237            parse_id(&mut tokens)?
2238        } else {
2239            interface = None;
2240            name
2241        };
2242
2243        let package = package
2244            .map(|(namespace, name)| -> anyhow::Result<crate::PackageName> {
2245                let version = parse_opt_version(&mut tokens)?;
2246                Ok(PackageName {
2247                    docs: Docs::default(),
2248                    span: Span::new(
2249                        namespace.span.start(),
2250                        version
2251                            .as_ref()
2252                            .map(|(s, _)| s.end())
2253                            .unwrap_or(name.span.end()),
2254                    ),
2255                    namespace,
2256                    name,
2257                    version,
2258                }
2259                .package_name())
2260            })
2261            .transpose()?;
2262
2263        if tokens.next()?.is_some() {
2264            anyhow::bail!("trailing tokens in item name specifier");
2265        }
2266        Ok(ItemName {
2267            package,
2268            interface,
2269            name: name.name.to_string(),
2270        })
2271    }
2272}
2273impl core::convert::TryFrom<String> for ItemName {
2274    type Error = anyhow::Error;
2275    fn try_from(s: String) -> anyhow::Result<ItemName> {
2276        s.parse()
2277    }
2278}
2279impl fmt::Display for ItemName {
2280    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2281        if let Some(crate::PackageName {
2282            namespace, name, ..
2283        }) = &self.package
2284        {
2285            write!(f, "{namespace}:{name}/")?;
2286        }
2287        if let Some(int) = &self.interface {
2288            write!(f, "{int}.")?;
2289        }
2290        write!(f, "{}", self.name)?;
2291        if let Some(crate::PackageName {
2292            version: Some(version),
2293            ..
2294        }) = &self.package
2295        {
2296            write!(f, "@{version}")?;
2297        }
2298        Ok(())
2299    }
2300}
2301impl From<ItemName> for String {
2302    fn from(m: ItemName) -> String {
2303        m.to_string()
2304    }
2305}
2306
2307#[cfg(test)]
2308mod 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}