@@ -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
@@ -226,6 +239,25 @@ abstract class ItemNode extends Locatable {
226239 )
227240 }
228241
242+ /** Gets the immediately enclosing item of this item, if any. */
243+ pragma [ nomagic]
244+ ItemNode getACanonicalChild ( string name ) {
245+ this = result .getImmediateParent ( ) and
246+ name = result .getName ( )
247+ or
248+ exists ( UseItemNode use |
249+ use .( Use ) .hasVisibility ( ) and
250+ use = this .getACanonicalChild ( _) and
251+ useImportEdge ( use , name , result ) and
252+ not result instanceof Crate
253+ )
254+ or
255+ exists ( MacroCallItemNode call |
256+ call = this .getACanonicalChild ( _) and
257+ result = call .getACanonicalChild ( name )
258+ )
259+ }
260+
229261 /** Holds if this item has a canonical path belonging to the crate `c`. */
230262 abstract predicate hasCanonicalPath ( Crate c ) ;
231263
@@ -353,7 +385,7 @@ class CrateItemNode extends ItemNode instanceof Crate {
353385
354386 override predicate providesCanonicalPathPrefixFor ( Crate c , ItemNode child ) {
355387 this .hasCanonicalPath ( c ) and
356- exists ( ModuleLikeNode m |
388+ exists ( SourceFileItemNode m |
357389 child .getImmediateParent ( ) = m and
358390 not m = child .( SourceFileItemNode ) .getSuper ( ) and
359391 m = super .getSourceFile ( )
@@ -363,6 +395,20 @@ class CrateItemNode extends ItemNode instanceof Crate {
363395 override string getCanonicalPath ( Crate c ) { c = this and result = Crate .super .getName ( ) }
364396}
365397
398+ class ExternCrateItemNode extends ItemNode instanceof ExternCrate {
399+ override string getName ( ) { result = super .getRename ( ) .getName ( ) .getText ( ) }
400+
401+ override Namespace getNamespace ( ) { none ( ) }
402+
403+ override Visibility getVisibility ( ) { none ( ) }
404+
405+ override TypeParam getTypeParam ( int i ) { none ( ) }
406+
407+ override predicate hasCanonicalPath ( Crate c ) { none ( ) }
408+
409+ override string getCanonicalPath ( Crate c ) { none ( ) }
410+ }
411+
366412/** An item that can occur in a trait or an `impl` block. */
367413abstract private class AssocItemNode extends ItemNode , AssocItem {
368414 /** Holds if this associated item has an implementation. */
@@ -793,6 +839,10 @@ class TypeAliasItemNode extends AssocItemNode instanceof TypeAlias {
793839 override Visibility getVisibility ( ) { result = TypeAlias .super .getVisibility ( ) }
794840
795841 override TypeParam getTypeParam ( int i ) { result = super .getGenericParamList ( ) .getTypeParam ( i ) }
842+
843+ override predicate hasCanonicalPath ( Crate c ) { none ( ) }
844+
845+ override string getCanonicalPath ( Crate c ) { none ( ) }
796846}
797847
798848private class UnionItemNode extends ItemNode instanceof Union {
@@ -1062,12 +1112,12 @@ private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
10621112}
10631113
10641114/**
1065- * Holds if `m ` depends on crate `dep` named `name`.
1115+ * Holds if `file ` depends on crate `dep` named `name`.
10661116 */
1067- private predicate crateDependencyEdge ( ModuleLikeNode m , string name , CrateItemNode dep ) {
1117+ private predicate crateDependencyEdge ( SourceFileItemNode file , string name , CrateItemNode dep ) {
10681118 exists ( CrateItemNode c |
10691119 dep = c .( Crate ) .getDependency ( name ) and
1070- m = c .getASourceFile ( )
1120+ file = c .getASourceFile ( )
10711121 )
10721122}
10731123
@@ -1403,6 +1453,22 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
14031453 )
14041454}
14051455
1456+ /** Holds if `ec` imports `crate` as `name`. */
1457+ pragma [ nomagic]
1458+ private predicate externCrateEdge ( ExternCrateItemNode ec , string name , CrateItemNode crate ) {
1459+ name = ec .getName ( ) and
1460+ exists ( SourceFile f , string s |
1461+ ec .getFile ( ) = f .getFile ( ) and
1462+ s = ec .( ExternCrate ) .getIdentifier ( ) .getText ( )
1463+ |
1464+ crateDependencyEdge ( f , s , crate )
1465+ or
1466+ // `extern crate` is used to import the current crate
1467+ s = "self" and
1468+ ec .getFile ( ) = crate .getASourceFile ( ) .getFile ( )
1469+ )
1470+ }
1471+
14061472/**
14071473 * Holds if `i` is available inside `f` because it is reexported in
14081474 * [the `core` prelude][1] or [the `std` prelude][2].
0 commit comments