@@ -1259,6 +1259,41 @@ impl CompositionGraph {
12591259 generation : entry. generation ,
12601260 }
12611261 }
1262+
1263+ /// Yields an iterator over the resolved imports (both implicit and explicit) of the graph.
1264+ ///
1265+ /// The iterator returns the name, the `ItemKind`, and an optional node id for explicit imports.
1266+ pub fn imports ( & self ) -> impl Iterator < Item = ( & str , ItemKind , Option < NodeId > ) > {
1267+ let mut imports = Vec :: new ( ) ;
1268+ for index in self . graph . node_indices ( ) {
1269+ let node = & self . graph [ index] ;
1270+ if !matches ! ( node. kind, NodeKind :: Instantiation ( _) ) {
1271+ continue ;
1272+ }
1273+
1274+ let package = & self [ node. package . unwrap ( ) ] ;
1275+ let world = & self . types [ package. ty ( ) ] ;
1276+
1277+ let unsatisfied_args = world
1278+ . imports
1279+ . iter ( )
1280+ . enumerate ( )
1281+ . filter ( |( i, _) | !node. is_arg_satisfied ( * i) ) ;
1282+
1283+ // Go through the unsatisfied arguments and import them
1284+ for ( _, ( name, item_kind) ) in unsatisfied_args {
1285+ imports. push ( ( name. as_str ( ) , * item_kind, None ) ) ;
1286+ }
1287+ }
1288+
1289+ for n in self . node_ids ( ) {
1290+ let node = & self . graph [ n. 0 ] ;
1291+ if let NodeKind :: Import ( name) = & node. kind {
1292+ imports. push ( ( name. as_str ( ) , node. item_kind , Some ( n) ) ) ;
1293+ }
1294+ }
1295+ imports. into_iter ( )
1296+ }
12621297}
12631298
12641299impl Index < NodeId > for CompositionGraph {
@@ -1489,18 +1524,60 @@ impl<'a> CompositionGraphEncoder<'a> {
14891524 }
14901525
14911526 /// Encode both implicit and explicit imports.
1527+ ///
1528+ /// `import_nodes` are expected to only be `NodeKind::Import` nodes.
14921529 fn encode_imports (
14931530 & self ,
14941531 state : & mut State ,
14951532 import_nodes : Vec < NodeIndex > ,
14961533 ) -> Result < ( ) , EncodeError > {
1497- let mut aggregator = TypeAggregator :: default ( ) ;
1498- let mut instantiations = HashMap :: new ( ) ;
1499- let mut arguments = Vec :: new ( ) ;
1534+ let mut explicit_imports = HashMap :: new ( ) ;
1535+ let mut implicit_imports = Vec :: new ( ) ;
1536+ let aggregator =
1537+ self . resolve_imports ( import_nodes, & mut implicit_imports, & mut explicit_imports) ?;
1538+
15001539 let mut encoded = HashMap :: new ( ) ;
1540+
1541+ // Next encode the imports
1542+ for ( name, kind) in aggregator. imports ( ) {
1543+ log:: debug!( "import `{name}` is being imported" ) ;
1544+ let index = self . import ( state, name, aggregator. types ( ) , kind) ;
1545+ encoded. insert ( name, ( kind. into ( ) , index) ) ;
1546+ }
1547+
1548+ // Populate the implicit argument map
1549+ for ( name, node) in implicit_imports {
1550+ let ( kind, index) = encoded[ name] ;
1551+ state
1552+ . implicit_args
1553+ . entry ( node)
1554+ . or_default ( )
1555+ . push ( ( name. to_owned ( ) , kind, index) ) ;
1556+ }
1557+
1558+ // Finally, populate the node indexes with the encoded explicit imports
1559+ for ( name, node_index) in explicit_imports {
1560+ let ( _, encoded_index) = encoded[ name] ;
1561+ state. node_indexes . insert ( node_index, encoded_index) ;
1562+ }
1563+
1564+ Ok ( ( ) )
1565+ }
1566+
1567+ /// Resolves the imports (both implicit and explicit) of the given nodes.
1568+ ///
1569+ /// Populates hashmaps that map the implicit and explicit import nodes to their import names.
1570+ /// Returns a type aggregator that contains the resolved types of the imports.
1571+ fn resolve_imports (
1572+ & ' a self ,
1573+ import_nodes : Vec < NodeIndex > ,
1574+ implicit_imports : & mut Vec < ( & ' a str , NodeIndex ) > ,
1575+ explicit_imports : & mut HashMap < & ' a str , NodeIndex > ,
1576+ ) -> Result < TypeAggregator , EncodeError > {
1577+ let mut instantiations = HashMap :: new ( ) ;
1578+ let mut aggregator = TypeAggregator :: default ( ) ;
15011579 let mut cache = Default :: default ( ) ;
15021580 let mut checker = SubtypeChecker :: new ( & mut cache) ;
1503- let mut explicit_imports = HashMap :: new ( ) ;
15041581
15051582 log:: debug!( "populating implicit imports" ) ;
15061583
@@ -1541,7 +1618,7 @@ impl<'a> CompositionGraphEncoder<'a> {
15411618 second : NodeId ( index) ,
15421619 source : e,
15431620 } ) ?;
1544- arguments . push ( ( index , name ) ) ;
1621+ implicit_imports . push ( ( name , index ) ) ;
15451622 }
15461623 }
15471624
@@ -1556,31 +1633,7 @@ impl<'a> CompositionGraphEncoder<'a> {
15561633 . unwrap ( ) ;
15571634 }
15581635 }
1559-
1560- // Next encode the imports
1561- for ( name, kind) in aggregator. imports ( ) {
1562- log:: debug!( "import `{name}` is being imported" ) ;
1563- let index = self . import ( state, name, aggregator. types ( ) , kind) ;
1564- encoded. insert ( name, ( kind. into ( ) , index) ) ;
1565- }
1566-
1567- // Populate the implicit argument map
1568- for ( node, name) in arguments {
1569- let ( kind, index) = encoded[ name. as_str ( ) ] ;
1570- state
1571- . implicit_args
1572- . entry ( node)
1573- . or_default ( )
1574- . push ( ( name. clone ( ) , kind, index) ) ;
1575- }
1576-
1577- // Finally, populate the node indexes with the encoded explicit imports
1578- for ( name, node_index) in explicit_imports {
1579- let ( _, encoded_index) = encoded[ name] ;
1580- state. node_indexes . insert ( node_index, encoded_index) ;
1581- }
1582-
1583- Ok ( ( ) )
1636+ Ok ( aggregator)
15841637 }
15851638
15861639 fn definition ( & self , state : & mut State , node : & Node ) -> u32 {
0 commit comments