@@ -127,12 +127,25 @@ abstract class ItemNode extends Locatable {
127127 or
128128 crateDependencyEdge ( this , name , result )
129129 or
130+ externCrateEdge ( this , name , result )
131+ or
130132 // items made available through `use` are available to nodes that contain the `use`
131133 exists ( UseItemNode use |
132134 use = this .getASuccessorRec ( _) and
133135 result = use .( ItemNode ) .getASuccessorRec ( name )
134136 )
135137 or
138+ exists ( ExternCrateItemNode ec | result = ec .( ItemNode ) .getASuccessorRec ( name ) |
139+ ec = this .getASuccessorRec ( _)
140+ or
141+ // if the extern crate appears in the crate root, then the crate name is also added
142+ // to the 'extern prelude', see https://doc.rust-lang.org/reference/items/extern-crates.html
143+ exists ( Crate c |
144+ ec = c .getSourceFile ( ) .( ItemNode ) .getASuccessorRec ( _) and
145+ this = c .getASourceFile ( )
146+ )
147+ )
148+ or
136149 // items made available through macro calls are available to nodes that contain the macro call
137150 exists ( MacroCallItemNode call |
138151 call = this .getASuccessorRec ( _) and
@@ -353,16 +366,30 @@ class CrateItemNode extends ItemNode instanceof Crate {
353366
354367 override predicate providesCanonicalPathPrefixFor ( Crate c , ItemNode child ) {
355368 this .hasCanonicalPath ( c ) and
356- exists ( ModuleLikeNode m |
357- child .getImmediateParent ( ) = m and
358- not m = child .( SourceFileItemNode ) .getSuper ( ) and
359- m = super .getSourceFile ( )
369+ exists ( SourceFileItemNode file |
370+ child .getImmediateParent ( ) = file and
371+ not file = child .( SourceFileItemNode ) .getSuper ( ) and
372+ file = super .getSourceFile ( )
360373 )
361374 }
362375
363376 override string getCanonicalPath ( Crate c ) { c = this and result = Crate .super .getName ( ) }
364377}
365378
379+ class ExternCrateItemNode extends ItemNode instanceof ExternCrate {
380+ override string getName ( ) { result = super .getRename ( ) .getName ( ) .getText ( ) }
381+
382+ override Namespace getNamespace ( ) { none ( ) }
383+
384+ override Visibility getVisibility ( ) { none ( ) }
385+
386+ override TypeParam getTypeParam ( int i ) { none ( ) }
387+
388+ override predicate hasCanonicalPath ( Crate c ) { none ( ) }
389+
390+ override string getCanonicalPath ( Crate c ) { none ( ) }
391+ }
392+
366393/** An item that can occur in a trait or an `impl` block. */
367394abstract private class AssocItemNode extends ItemNode , AssocItem {
368395 /** Holds if this associated item has an implementation. */
@@ -793,6 +820,10 @@ class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
793820 override Visibility getVisibility ( ) { result = TypeAlias .super .getVisibility ( ) }
794821
795822 override TypeParam getTypeParam ( int i ) { result = super .getGenericParamList ( ) .getTypeParam ( i ) }
823+
824+ override predicate hasCanonicalPath ( Crate c ) { none ( ) }
825+
826+ override string getCanonicalPath ( Crate c ) { none ( ) }
796827}
797828
798829private class UnionItemNode extends ItemNode instanceof Union {
@@ -1062,12 +1093,12 @@ private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
10621093}
10631094
10641095/**
1065- * Holds if `m ` depends on crate `dep` named `name`.
1096+ * Holds if `file ` depends on crate `dep` named `name`.
10661097 */
1067- private predicate crateDependencyEdge ( ModuleLikeNode m , string name , CrateItemNode dep ) {
1098+ private predicate crateDependencyEdge ( SourceFileItemNode file , string name , CrateItemNode dep ) {
10681099 exists ( CrateItemNode c |
10691100 dep = c .( Crate ) .getDependency ( name ) and
1070- m = c .getASourceFile ( )
1101+ file = c .getASourceFile ( )
10711102 )
10721103}
10731104
@@ -1403,6 +1434,22 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
14031434 )
14041435}
14051436
1437+ /** Holds if `ec` imports `crate` as `name`. */
1438+ pragma [ nomagic]
1439+ private predicate externCrateEdge ( ExternCrateItemNode ec , string name , CrateItemNode crate ) {
1440+ name = ec .getName ( ) and
1441+ exists ( SourceFile f , string s |
1442+ ec .getFile ( ) = f .getFile ( ) and
1443+ s = ec .( ExternCrate ) .getIdentifier ( ) .getText ( )
1444+ |
1445+ crateDependencyEdge ( f , s , crate )
1446+ or
1447+ // `extern crate` is used to import the current crate
1448+ s = "self" and
1449+ ec .getFile ( ) = crate .getASourceFile ( ) .getFile ( )
1450+ )
1451+ }
1452+
14061453/**
14071454 * Holds if `i` is available inside `f` because it is reexported in
14081455 * [the `core` prelude][1] or [the `std` prelude][2].
0 commit comments