diff --git a/crates/wit-compiler/src/access.rs b/crates/wit-compiler/src/access.rs index 96900fdd8..5a7ee0a7c 100644 --- a/crates/wit-compiler/src/access.rs +++ b/crates/wit-compiler/src/access.rs @@ -204,6 +204,18 @@ pub enum AnyFuncItemIndex { StaticMethod(ScopeIndex, ResourceIndex, StaticResourceMethodIndex), } +impl AnyFuncItemIndex { + /// Get the scope this [`crate::hir::FuncItem`] is defined in. + pub fn scope(self) -> ScopeIndex { + match self { + AnyFuncItemIndex::TopLevel(i, _) => ScopeIndex::Interface(i), + AnyFuncItemIndex::Method(scope, _, _) | AnyFuncItemIndex::StaticMethod(scope, _, _) => { + scope + } + } + } +} + impl GetByIndex for Items { type Metadata = WorldMetadata; diff --git a/crates/wit-compiler/src/ast/generated.rs b/crates/wit-compiler/src/ast/generated.rs index 4a4fa9e50..c41b06446 100644 --- a/crates/wit-compiler/src/ast/generated.rs +++ b/crates/wit-compiler/src/ast/generated.rs @@ -102,15 +102,10 @@ impl<'tree> super::AstNode<'tree> for BlockComment<'tree> { #[derive(Debug, Copy, Clone, PartialEq)] pub struct BorrowedHandle<'tree>(tree_sitter::Node<'tree>); impl<'tree> BorrowedHandle<'tree> { - pub fn name(&self) -> Option> { - self.0.child_by_field_name("name").and_then(::cast) - } -} -impl super::HasIdent for BorrowedHandle<'_> { - fn identifier(self, src: &str) -> Option<&str> { - let node = self.name()?.0; - let ident = node.utf8_text(src.as_bytes()).unwrap(); - Some(ident) + pub fn user_defined_type(self) -> Option> { + super::children(self.0) + .filter_map(>::cast) + .next() } } impl<'tree> super::AstNode<'tree> for BorrowedHandle<'tree> { @@ -962,15 +957,10 @@ impl<'tree> super::AstNode<'tree> for Option_<'tree> { #[derive(Debug, Copy, Clone, PartialEq)] pub struct OwnedHandle<'tree>(tree_sitter::Node<'tree>); impl<'tree> OwnedHandle<'tree> { - pub fn name(&self) -> Option> { - self.0.child_by_field_name("name").and_then(::cast) - } -} -impl super::HasIdent for OwnedHandle<'_> { - fn identifier(self, src: &str) -> Option<&str> { - let node = self.name()?.0; - let ident = node.utf8_text(src.as_bytes()).unwrap(); - Some(ident) + pub fn user_defined_type(self) -> Option> { + super::children(self.0) + .filter_map(>::cast) + .next() } } impl<'tree> super::AstNode<'tree> for OwnedHandle<'tree> { @@ -1724,10 +1714,15 @@ impl<'tree> super::AstNode<'tree> for UsePath<'tree> { #[derive(Debug, Copy, Clone, PartialEq)] pub struct UserDefinedType<'tree>(tree_sitter::Node<'tree>); impl<'tree> UserDefinedType<'tree> { - pub fn identifier(self) -> Option> { - super::children(self.0) - .filter_map(>::cast) - .next() + pub fn name(&self) -> Option> { + self.0.child_by_field_name("name").and_then(::cast) + } +} +impl super::HasIdent for UserDefinedType<'_> { + fn identifier(self, src: &str) -> Option<&str> { + let node = self.name()?.0; + let ident = node.utf8_text(src.as_bytes()).unwrap(); + Some(ident) } } impl<'tree> super::AstNode<'tree> for UserDefinedType<'tree> { diff --git a/crates/wit-compiler/src/diagnostics.rs b/crates/wit-compiler/src/diagnostics.rs index 9ddff20c4..a7965082d 100644 --- a/crates/wit-compiler/src/diagnostics.rs +++ b/crates/wit-compiler/src/diagnostics.rs @@ -55,7 +55,7 @@ impl Diagnostic { }) } - pub fn unknown_name(name: Text, filename: Text, range: Range) -> Self { + pub fn unknown_name(filename: FilePath, name: Text, range: Range) -> Self { Diagnostic::UnknownName(UnknownName { name, location: Location::new(filename, range), diff --git a/crates/wit-compiler/src/hir.rs b/crates/wit-compiler/src/hir.rs index 78b2b995c..366d3ab13 100644 --- a/crates/wit-compiler/src/hir.rs +++ b/crates/wit-compiler/src/hir.rs @@ -4,9 +4,10 @@ use im::{OrdMap, Vector}; use crate::{ access::{ - AnyFuncItemIndex, EnumIndex, FlagsIndex, InterfaceIndex, RecordIndex, ResourceIndex, - TypeAliasIndex, VariantIndex, WorldIndex, + AnyFuncItemIndex, EnumIndex, FlagsIndex, FuncItemIndex, InterfaceIndex, RecordIndex, + ResourceIndex, ScopeIndex, TypeAliasIndex, VariantIndex, WorldIndex, }, + queries::FilePath, Text, }; @@ -156,6 +157,7 @@ pub enum Type { Builtin(Builtin), Handle { borrowed: bool, + ty: Box, }, List(Box), Option(Box), @@ -164,9 +166,71 @@ pub enum Type { err: Option>, }, Tuple(Vector), + UserDefinedType(ItemReference), Error, } +/// A reference to an item defined elsewhere. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ItemReference { + pub file: FilePath, + pub scope: ScopeIndex, + pub item: ItemReferenceKind, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum ItemReferenceKind { + Enum(EnumIndex), + Variant(VariantIndex), + Flags(FlagsIndex), + Record(RecordIndex), + Resource(ResourceIndex), + Func(FuncItemIndex), + TypeAlias(TypeAliasIndex), +} + +impl From for ItemReferenceKind { + fn from(v: EnumIndex) -> Self { + Self::Enum(v) + } +} + +impl From for ItemReferenceKind { + fn from(v: TypeAliasIndex) -> Self { + Self::TypeAlias(v) + } +} + +impl From for ItemReferenceKind { + fn from(v: FuncItemIndex) -> Self { + Self::Func(v) + } +} + +impl From for ItemReferenceKind { + fn from(v: ResourceIndex) -> Self { + Self::Resource(v) + } +} + +impl From for ItemReferenceKind { + fn from(v: RecordIndex) -> Self { + Self::Record(v) + } +} + +impl From for ItemReferenceKind { + fn from(v: FlagsIndex) -> Self { + Self::Flags(v) + } +} + +impl From for ItemReferenceKind { + fn from(v: VariantIndex) -> Self { + Self::Variant(v) + } +} + impl From for Type { fn from(value: Builtin) -> Self { Type::Builtin(value) diff --git a/crates/wit-compiler/src/lib.rs b/crates/wit-compiler/src/lib.rs index 22c698d0f..52c8a64e8 100644 --- a/crates/wit-compiler/src/lib.rs +++ b/crates/wit-compiler/src/lib.rs @@ -25,6 +25,7 @@ pub struct Jar( crate::queries::Items, crate::queries::lower, crate::queries::lowering::lower_enum, + crate::queries::lowering::lower_flags, crate::queries::lowering::lower_func_item, crate::queries::lowering::lower_interface, crate::queries::lowering::lower_record, @@ -32,8 +33,9 @@ pub struct Jar( crate::queries::lowering::lower_type_alias, crate::queries::lowering::lower_variant, crate::queries::lowering::lower_world, - crate::queries::lowering::lower_flags, crate::queries::parse, + crate::queries::resolve_name, + crate::queries::resolve_namespace, crate::queries::selection_ranges, crate::queries::SourceFile, crate::queries::Workspace, diff --git a/crates/wit-compiler/src/queries/items.rs b/crates/wit-compiler/src/queries/items.rs index 1ce8617df..f83fb2495 100644 --- a/crates/wit-compiler/src/queries/items.rs +++ b/crates/wit-compiler/src/queries/items.rs @@ -13,6 +13,7 @@ use crate::{ }, ast::{self, AstNode, HasIdent}, diagnostics::{Diagnostic, Diagnostics, Location}, + hir, queries::SourceFile, Db, Text, }; @@ -45,7 +46,7 @@ pub fn file_items(db: &dyn Db, file: SourceFile) -> Items { } else if let Some(interface) = top_level_item.interface_item() { if let Some((name, interface)) = walk_interface(db, interface, src, file) { if names.insert(name.clone(), node) { - let ix = InterfaceIndex::from_raw(RawIndex::new(worlds.len())); + let ix = InterfaceIndex::from_raw(RawIndex::new(interfaces.len())); interfaces.push_back(interface); interfaces_by_name.insert(name, ix); } @@ -475,15 +476,37 @@ impl ItemDefinitionMetadata { iter(&self.variants) } + pub fn reference_kinds(&self) -> impl Iterator { + let ItemDefinitionMetadata { + enums_by_name, + flags_by_name, + functions_by_name, + records_by_name, + resources_by_name, + typedefs_by_name, + variants_by_name, + .. + } = self; + + fn m<'a, Ix>((name, ix): (&'a Text, &Ix)) -> (&'a Text, hir::ItemReferenceKind) + where + Ix: Into + Clone, + { + (name, ix.clone().into()) + } + + std::iter::empty() + .chain(enums_by_name.iter().map(m)) + .chain(flags_by_name.iter().map(m)) + .chain(functions_by_name.iter().map(m)) + .chain(records_by_name.iter().map(m)) + .chain(resources_by_name.iter().map(m)) + .chain(typedefs_by_name.iter().map(m)) + .chain(variants_by_name.iter().map(m)) + } + pub fn names(&self) -> impl Iterator { - self.enums_by_name - .keys() - .chain(self.flags_by_name.keys()) - .chain(self.functions_by_name.keys()) - .chain(self.records_by_name.keys()) - .chain(self.resources_by_name.keys()) - .chain(self.typedefs_by_name.keys()) - .chain(self.variants_by_name.keys()) + self.reference_kinds().map(|(n, _)| n) } } diff --git a/crates/wit-compiler/src/queries/lowering.rs b/crates/wit-compiler/src/queries/lowering.rs index f0639793c..67d1b34a7 100644 --- a/crates/wit-compiler/src/queries/lowering.rs +++ b/crates/wit-compiler/src/queries/lowering.rs @@ -31,15 +31,13 @@ pub fn lower(db: &dyn Db, _ws: Workspace, file: SourceFile) -> hir::Package { let mut interfaces = OrdMap::new(); for index in items.worlds_by_name(db).values().copied() { - if let Some(world) = lower_world(db, file, index) { - worlds.insert(index, world); - } + let world = lower_world(db, file, index); + worlds.insert(index, world); } for index in items.interfaces_by_name(db).values().copied() { - if let Some(interface) = lower_interface(db, file, index) { - interfaces.insert(index, interface); - } + let interface = lower_interface(db, file, index); + interfaces.insert(index, interface); } hir::Package { @@ -70,7 +68,7 @@ fn lower_package_decl(node: ast::PackageDecl, src: &str) -> Option Option { +pub(crate) fn lower_world(db: &dyn Db, file: SourceFile, index: WorldIndex) -> hir::World { let ast = crate::queries::parse(db, file); let tree = ast.tree(db); let items = crate::queries::file_items(db, file); @@ -79,7 +77,7 @@ pub(crate) fn lower_world(db: &dyn Db, file: SourceFile, index: WorldIndex) -> O let node = meta.location(db).ast_node(tree); let src = ast.src(db); - let name = node.identifier(src)?.into(); + let name = meta.name(db); let mut world_items = Vector::new(); @@ -89,11 +87,11 @@ pub(crate) fn lower_world(db: &dyn Db, file: SourceFile, index: WorldIndex) -> O } } - Some(hir::World { + hir::World { name, docs: node.docs(src), items: world_items, - }) + } } fn lower_world_item(_db: &dyn Db, _item: ast::WorldItems<'_>) -> Option { @@ -105,7 +103,7 @@ pub(crate) fn lower_interface( db: &dyn Db, file: SourceFile, index: InterfaceIndex, -) -> Option { +) -> hir::Interface { let ast = crate::queries::parse(db, file); let tree = ast.tree(db); let items = crate::queries::file_items(db, file); @@ -159,11 +157,9 @@ pub(crate) fn lower_interface( } } - Some(hir::Interface { - name: meta.name(db), - docs: node.docs(ast.src(db)), - items, - }) + let name = meta.name(db); + let docs = node.docs(ast.src(db)); + hir::Interface { name, docs, items } } #[salsa::tracked] @@ -272,13 +268,13 @@ pub(crate) fn lower_func_item( let mut params = Vector::new(); for param in func_type.params()?.iter_params() { - let param = lower_param(src, param)?; + let param = lower_param(db, file, interface.into(), param)?; params.push_back(param); } let return_value = func_type .result_opt() - .and_then(|r| lower_return_value(db, src, file, r)); + .and_then(|r| lower_return_value(db, file, interface.into(), r)); Some(hir::FuncItem { index: AnyFuncItemIndex::TopLevel(interface, index), @@ -289,22 +285,30 @@ pub(crate) fn lower_func_item( }) } -fn lower_param(src: &str, param: ast::NamedType<'_>) -> Option { +fn lower_param( + db: &dyn Db, + file: SourceFile, + scope: ScopeIndex, + param: ast::NamedType<'_>, +) -> Option { + let src = file.contents(db); let name = param.identifier(src)?.into(); let ty = param.ty()?; - let ty = resolve_type(src, ty)?; + let ty = resolve_type(db, file, scope, ty)?; Some(hir::Parameter { name, ty }) } fn lower_return_value( db: &dyn Db, - src: &str, file: SourceFile, + scope: ScopeIndex, ret: ast::ResultList<'_>, ) -> Option { + let src = file.contents(db); + if let Some(ty) = ret.ty_opt() { - let ty = resolve_type(src, ty)?; + let ty = resolve_type(db, file, scope, ty)?; Some(hir::ReturnValue::Single(ty)) } else if let Some(list) = ret.named_result_list_opt() { let mut return_types = OrdMap::new(); @@ -312,7 +316,7 @@ fn lower_return_value( for pair in list.iter_named_types() { let name = Text::from(pair.identifier(src)?); let ty_node = pair.ty()?; - let ty = resolve_type(src, ty_node).unwrap_or(hir::Type::Error); + let ty = resolve_type(db, file, scope, ty_node).unwrap_or(hir::Type::Error); match return_types.entry(name) { im::ordmap::Entry::Vacant(entry) => { @@ -362,7 +366,7 @@ pub(crate) fn lower_record( let mut fields = Vector::new(); for field in node.iter_fields() { - if let Some(f) = lower_field(src, field) { + if let Some(f) = lower_field(db, file, scope, field) { if names.insert(f.name.clone(), field.syntax()) { fields.push_back(f); } @@ -377,11 +381,17 @@ pub(crate) fn lower_record( }) } -fn lower_field(src: &str, node: ast::RecordField<'_>) -> Option { +fn lower_field( + db: &dyn Db, + file: SourceFile, + scope: ScopeIndex, + node: ast::RecordField<'_>, +) -> Option { + let src = file.contents(db); let name = node.identifier(src)?.into(); let docs = node.docs(src); let ty = node.ty()?; - let ty = resolve_type(src, ty)?; + let ty = resolve_type(db, file, scope, ty)?; Some(hir::RecordField { name, docs, ty }) } @@ -425,7 +435,7 @@ pub(crate) fn lower_resource( let constructor = meta .constructor .map(|c| c.ast_node(tree)) - .map(|c| lower_constructor(c, src)); + .map(|c| lower_constructor(db, file, scope, c)); Some(hir::Resource { constructor, @@ -448,7 +458,7 @@ fn lower_method( let ty = node.ty()?; let docs = node.docs(src); - let (params, return_value) = lower_func_type(db, ty, src, file)?; + let (params, return_value) = lower_func_type(db, file, index.scope(), ty)?; Some(hir::ResourceMethod(hir::FuncItem { name, @@ -461,18 +471,18 @@ fn lower_method( fn lower_func_type( db: &dyn Db, - node: ast::FuncType<'_>, - src: &str, file: SourceFile, + scope: ScopeIndex, + node: ast::FuncType<'_>, ) -> Option<(Vector, Option)> { let mut params = Vector::new(); for param in node.params()?.iter_params() { - let param = lower_param(src, param)?; + let param = lower_param(db, file, scope, param)?; params.push_back(param); } let return_value = node .result_opt() - .and_then(|r| lower_return_value(db, src, file, r)); + .and_then(|r| lower_return_value(db, file, scope, r)); Some((params, return_value)) } @@ -488,7 +498,7 @@ fn lower_static_method( let ty = node.func_type()?; let docs = node.docs(src); - let (params, return_value) = lower_func_type(db, ty, src, file)?; + let (params, return_value) = lower_func_type(db, file, index.scope(), ty)?; Some(hir::StaticResourceMethod(hir::FuncItem { name, @@ -499,13 +509,20 @@ fn lower_static_method( })) } -fn lower_constructor(node: ast::ResourceConstructor<'_>, src: &str) -> hir::Constructor { +fn lower_constructor( + db: &dyn Db, + file: SourceFile, + scope: ScopeIndex, + node: ast::ResourceConstructor<'_>, +) -> hir::Constructor { + let src = file.contents(db); let docs = node.docs(src); + let params = node .params() .into_iter() .flat_map(|params| params.iter_params()) - .filter_map(|p| lower_param(src, p)) + .filter_map(|p| lower_param(db, file, scope, p)) .collect(); hir::Constructor { docs, params } @@ -530,7 +547,7 @@ pub(crate) fn lower_type_alias( let name = node.identifier(src)?.into(); let ty = node.ty()?; - let ty = resolve_type(src, ty)?; + let ty = resolve_type(db, file, scope, ty)?; Some(hir::TypeAlias { name, @@ -564,7 +581,7 @@ pub(crate) fn lower_variant( let mut cases = Vector::new(); for c in node.iter_cases() { - if let Some(case) = lower_variant_case(c, src) { + if let Some(case) = lower_variant_case(db, file, scope, c) { if names.insert(case.name.clone(), c.syntax()) { cases.push_back(case); } @@ -579,12 +596,18 @@ pub(crate) fn lower_variant( }) } -fn lower_variant_case(node: ast::VariantCase<'_>, src: &str) -> Option { +fn lower_variant_case( + db: &dyn Db, + file: SourceFile, + scope: ScopeIndex, + node: ast::VariantCase<'_>, +) -> Option { + let src = file.contents(db); let name = node.identifier(src)?.into(); let docs = node.docs(src); let ty = if let Some(ty) = node.ty_opt() { - Some(resolve_type(src, ty)?) + Some(resolve_type(db, file, scope, ty)?) } else { None }; @@ -592,16 +615,34 @@ fn lower_variant_case(node: ast::VariantCase<'_>, src: &str) -> Option) -> Option { - let resolver = TypeResolver { src }; +fn resolve_type( + db: &dyn Db, + file: SourceFile, + scope: ScopeIndex, + ty: ast::Ty<'_>, +) -> Option { + let resolver = TypeResolver::new(db, file, scope); resolver.resolve_type(ty) } struct TypeResolver<'a> { + db: &'a dyn Db, src: &'a str, + file: SourceFile, + scope: ScopeIndex, } impl<'a> TypeResolver<'a> { + fn new(db: &'a dyn Db, file: SourceFile, scope: ScopeIndex) -> Self { + let src = file.contents(db).as_str(); + TypeResolver { + db, + src, + file, + scope, + } + } + fn resolve_type(&self, ty: ast::Ty<'_>) -> Option { if let Some(builtin) = ty.builtins() { self.resolve_builtin(builtin) @@ -651,9 +692,23 @@ impl<'a> TypeResolver<'a> { fn resolve_user_defined_type( &self, - _user_defined_type: ast::UserDefinedType<'_>, + user_defined_type: ast::UserDefinedType<'_>, ) -> Option { - todo!() + let name = user_defined_type.identifier(self.src)?; + let name = Text::from(name); + + match crate::queries::resolve_name(self.db, self.file, self.scope, name.clone()) { + Some(reference) => Some(hir::Type::UserDefinedType(reference)), + None => { + let diag = Diagnostic::unknown_name( + self.file.path(self.db).clone(), + name, + user_defined_type.range(), + ); + Diagnostics::push(self.db, diag); + Some(hir::Type::Error) + } + } } fn resolve_list(&self, list: ast::List<'_>) -> Option { @@ -662,8 +717,23 @@ impl<'a> TypeResolver<'a> { Some(hir::Type::List(Box::new(element_type))) } - fn resolve_handle(&self, _handle: ast::Handle<'_>) -> Option { - todo!() + fn resolve_handle(&self, handle: ast::Handle<'_>) -> Option { + let (ty, borrowed) = if let Some(h) = handle.borrowed_handle() { + (h.user_defined_type()?, true) + } else if let Some(h) = handle.owned_handle() { + (h.user_defined_type()?, false) + } else { + return None; + }; + + let ty = self + .resolve_user_defined_type(ty) + .unwrap_or(hir::Type::Error); + + Some(hir::Type::Handle { + borrowed, + ty: Box::new(ty), + }) } fn resolve_builtin(&self, builtin: ast::Builtins<'_>) -> Option { @@ -856,6 +926,18 @@ mod tests { resource_with_constructor: "interface i { resource r { constructor(arg1: string, arg2: bool); } }", resource_with_method: "interface i { resource r { method: func(arg1: string, arg2: bool) -> u32; } }", resource_with_static_method: "interface i { resource r { method: static func(arg1: string, arg2: bool) -> u32; } }", + refer_to_user_defined_type: "interface i { + record r {} + type x = list; + }", + #[ignore] + refer_to_user_defined_type_from_other_interface: " + interface first { record r {} } + interface second { + use first.{r}; + type x = r; + } + ", empty_variant: "interface i { variant v {} }", varant_with_one_field: "interface i { variant v { field } }", diff --git a/crates/wit-compiler/src/queries/mod.rs b/crates/wit-compiler/src/queries/mod.rs index b68ed26d2..69c2216d2 100644 --- a/crates/wit-compiler/src/queries/mod.rs +++ b/crates/wit-compiler/src/queries/mod.rs @@ -3,6 +3,7 @@ mod hover; mod items; pub(crate) mod lowering; +mod namespaces; mod parsing; mod selection; @@ -13,6 +14,7 @@ pub use self::{ WorldMetadata, }, lowering::lower, + namespaces::{resolve_name, resolve_namespace, Namespace}, parsing::{parse, Ast, FilePath, SourceFile, Workspace}, selection::selection_ranges, }; diff --git a/crates/wit-compiler/src/queries/namespaces.rs b/crates/wit-compiler/src/queries/namespaces.rs new file mode 100644 index 000000000..dbc4e34d1 --- /dev/null +++ b/crates/wit-compiler/src/queries/namespaces.rs @@ -0,0 +1,71 @@ +use im::OrdMap; + +use crate::{ + access::{GetAstNode, GetByIndex, ScopeIndex}, + hir, + queries::SourceFile, + Db, Text, +}; + +#[salsa::tracked] +pub fn resolve_name( + db: &dyn Db, + file: SourceFile, + scope: ScopeIndex, + name: Text, +) -> Option { + resolve_namespace(db, file, scope).lookup(&name) +} + +#[salsa::tracked] +pub fn resolve_namespace(db: &dyn Db, file: SourceFile, scope: ScopeIndex) -> Namespace { + let defined_types = match scope { + ScopeIndex::World(index) => file.get_by_index(db, index).items(db), + ScopeIndex::Interface(index) => file.get_by_index(db, index).items(db), + }; + + let mut names = OrdMap::new(); + + for (name, item) in defined_types.reference_kinds() { + let reference = hir::ItemReference { + file: file.path(db).clone(), + scope, + item, + }; + names.insert(name.clone(), reference); + } + + let ast = crate::queries::parse(db, file); + let tree = ast.tree(db); + + let imports: Vec<_> = match scope { + ScopeIndex::World(index) => file + .get_by_index(db, index) + .location(db) + .ast_node(tree) + .iter_items() + .filter_map(|n| n.use_item()) + .collect(), + ScopeIndex::Interface(index) => file + .get_by_index(db, index) + .location(db) + .ast_node(tree) + .iter_items() + .filter_map(|n| n.use_item()) + .collect(), + }; + if !imports.is_empty() { + todo!("Resolve imports from other files"); + } + + Namespace(names) +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Namespace(pub OrdMap); + +impl Namespace { + pub fn lookup(&self, name: &str) -> Option { + self.0.get(name).cloned() + } +} diff --git a/crates/wit-compiler/src/queries/snapshots/wit_compiler__queries__lowering__tests__refer_to_user_defined_type.snap b/crates/wit-compiler/src/queries/snapshots/wit_compiler__queries__lowering__tests__refer_to_user_defined_type.snap new file mode 100644 index 000000000..911a77f75 --- /dev/null +++ b/crates/wit-compiler/src/queries/snapshots/wit_compiler__queries__lowering__tests__refer_to_user_defined_type.snap @@ -0,0 +1,48 @@ +--- +source: crates/wit-compiler/src/queries/lowering.rs +info: + src: "interface i {\n record r {}\n type x = list;\n }" + ast: "(source_file (top_level_item (interface_item name: (identifier) items: (interface_items (typedef_item (record_item name: (identifier)))) items: (interface_items (typedef_item (type_item name: (identifier) ty: (ty (list (ty (user_defined_type name: (identifier)))))))))))" +--- +Package { + decl: None, + worlds: {}, + interfaces: { + InterfaceIndex(0): Interface { + name: i, + docs: None, + items: [ + Record( + Record { + name: r, + index: RecordIndex(0), + docs: None, + fields: [], + }, + ), + TypeAlias( + TypeAlias { + name: x, + index: TypeAliasIndex(0), + docs: None, + ty: List( + UserDefinedType( + ItemReference { + file: FilePath( + refer_to_user_defined_type.wit, + ), + scope: Interface( + InterfaceIndex(0), + ), + item: Record( + RecordIndex(0), + ), + }, + ), + ), + }, + ), + ], + }, + }, +}