@@ -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 {
@@ -1063,12 +1094,12 @@ private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
10631094}
10641095
10651096/**
1066- * Holds if `m ` depends on crate `dep` named `name`.
1097+ * Holds if `file ` depends on crate `dep` named `name`.
10671098 */
1068- private predicate crateDependencyEdge ( ModuleLikeNode m , string name , CrateItemNode dep ) {
1099+ private predicate crateDependencyEdge ( SourceFileItemNode file , string name , CrateItemNode dep ) {
10691100 exists ( CrateItemNode c |
10701101 dep = c .( Crate ) .getDependency ( name ) and
1071- m = c .getASourceFile ( )
1102+ file = c .getASourceFile ( )
10721103 )
10731104}
10741105
@@ -1404,6 +1435,22 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
14041435 )
14051436}
14061437
1438+ /** Holds if `ec` imports `crate` as `name`. */
1439+ pragma [ nomagic]
1440+ private predicate externCrateEdge ( ExternCrateItemNode ec , string name , CrateItemNode crate ) {
1441+ name = ec .getName ( ) and
1442+ exists ( SourceFile f , string s |
1443+ ec .getFile ( ) = f .getFile ( ) and
1444+ s = ec .( ExternCrate ) .getIdentifier ( ) .getText ( )
1445+ |
1446+ crateDependencyEdge ( f , s , crate )
1447+ or
1448+ // `extern crate` is used to import the current crate
1449+ s = "self" and
1450+ ec .getFile ( ) = crate .getASourceFile ( ) .getFile ( )
1451+ )
1452+ }
1453+
14071454/**
14081455 * Holds if `i` is available inside `f` because it is reexported in
14091456 * [the `core` prelude][1] or [the `std` prelude][2].
0 commit comments