@@ -73,7 +73,7 @@ final class Namespace extends TNamespace {
73
73
* - https://doc.rust-lang.org/reference/visibility-and-privacy.html
74
74
* - https://doc.rust-lang.org/reference/names/namespaces.html
75
75
*/
76
- abstract class ItemNode extends AstNode {
76
+ abstract class ItemNode extends Locatable {
77
77
/** Gets the (original) name of this item. */
78
78
abstract string getName ( ) ;
79
79
@@ -122,6 +122,10 @@ abstract class ItemNode extends AstNode {
122
122
or
123
123
useImportEdge ( this , name , result )
124
124
or
125
+ crateDefEdge ( this , name , result )
126
+ or
127
+ crateDependencyEdge ( this , name , result )
128
+ or
125
129
// items made available through `use` are available to nodes that contain the `use`
126
130
exists ( UseItemNode use |
127
131
use = this .getASuccessorRec ( _) and
@@ -180,7 +184,7 @@ abstract class ItemNode extends AstNode {
180
184
this = result .( ImplOrTraitItemNode ) .getAnItemInSelfScope ( )
181
185
or
182
186
name = "crate" and
183
- result .( SourceFileItemNode ) . getFile ( ) = this . getFile ( )
187
+ this = result .( CrateItemNode ) . getASourceFile ( )
184
188
}
185
189
186
190
/** Gets the location of this item. */
@@ -214,6 +218,51 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
214
218
override TypeParam getTypeParam ( int i ) { none ( ) }
215
219
}
216
220
221
+ class CrateItemNode extends ItemNode instanceof Crate {
222
+ /**
223
+ * Gets the module node that defines this crate.
224
+ *
225
+ * This is either a source file, when the crate is defined in source code,
226
+ * or a module, when the crate is defined in a dependency.
227
+ */
228
+ pragma [ nomagic]
229
+ ModuleLikeNode getModuleNode ( ) {
230
+ result = super .getSourceFile ( )
231
+ or
232
+ not exists ( super .getSourceFile ( ) ) and
233
+ result = super .getModule ( )
234
+ }
235
+
236
+ /**
237
+ * Gets a source file that belongs to this crate, if any.
238
+ *
239
+ * This is calculated as those source files that can be reached from the entry
240
+ * file of this crate using zero or more `mod` imports, without going through
241
+ * the entry point of some other crate.
242
+ */
243
+ pragma [ nomagic]
244
+ SourceFileItemNode getASourceFile ( ) {
245
+ result = super .getSourceFile ( )
246
+ or
247
+ exists ( SourceFileItemNode mid , Module mod |
248
+ mid = this .getASourceFile ( ) and
249
+ mod .getFile ( ) = mid .getFile ( ) and
250
+ fileImport ( mod , result ) and
251
+ not result = any ( Crate other ) .getSourceFile ( )
252
+ )
253
+ }
254
+
255
+ override string getName ( ) { result = Crate .super .getName ( ) }
256
+
257
+ override Namespace getNamespace ( ) {
258
+ result .isType ( ) // can be referenced with `crate`
259
+ }
260
+
261
+ override Visibility getVisibility ( ) { none ( ) }
262
+
263
+ override TypeParam getTypeParam ( int i ) { none ( ) }
264
+ }
265
+
217
266
/** An item that can occur in a trait or an `impl` block. */
218
267
abstract private class AssocItemNode extends ItemNode , AssocItem {
219
268
/** Holds if this associated item has an implementation. */
@@ -595,6 +644,28 @@ private predicate fileImportEdge(Module mod, string name, ItemNode item) {
595
644
)
596
645
}
597
646
647
+ /**
648
+ * Holds if crate `c` defines the item `i` named `name`.
649
+ */
650
+ pragma [ nomagic]
651
+ private predicate crateDefEdge ( CrateItemNode c , string name , ItemNode i ) {
652
+ i = c .getModuleNode ( ) .getASuccessor ( name ) and
653
+ not i instanceof Crate
654
+ }
655
+
656
+ /**
657
+ * Holds if `m` depends on crate `dep` named `name`.
658
+ */
659
+ private predicate crateDependencyEdge ( ModuleLikeNode m , string name , CrateItemNode dep ) {
660
+ exists ( CrateItemNode c | dep = c .( Crate ) .getDependency ( name ) |
661
+ // entry module/entry source file
662
+ m = c .getModuleNode ( )
663
+ or
664
+ // entry/transitive source file
665
+ m = c .getASourceFile ( )
666
+ )
667
+ }
668
+
598
669
private predicate useTreeDeclares ( UseTree tree , string name ) {
599
670
not tree .isGlob ( ) and
600
671
not exists ( tree .getUseTreeList ( ) ) and
@@ -832,3 +903,48 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
832
903
name != "_"
833
904
)
834
905
}
906
+
907
+ /** Provides predicates for debugging the path resolution implementation. */
908
+ private module Debug {
909
+ private Locatable getRelevantLocatable ( ) {
910
+ exists ( string filepath , int startline , int startcolumn , int endline , int endcolumn |
911
+ result .getLocation ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn ) and
912
+ // filepath.matches("%/compile.rs") and
913
+ // startline = 1986
914
+ // filepath.matches("%/build_steps/mod.rs") and
915
+ // startline = 17
916
+ filepath .matches ( "%/main.rs" ) and
917
+ startline = 1
918
+ )
919
+ }
920
+
921
+ predicate debugUnqualifiedPathLookup ( RelevantPath p , string name , Namespace ns , ItemNode encl ) {
922
+ p = getRelevantLocatable ( ) and
923
+ unqualifiedPathLookup ( p , name , ns , encl )
924
+ }
925
+
926
+ ItemNode debugResolvePath ( RelevantPath path ) {
927
+ path = getRelevantLocatable ( ) and
928
+ result = resolvePath ( path )
929
+ }
930
+
931
+ predicate debugUseImportEdge ( Use use , string name , ItemNode item ) {
932
+ use = getRelevantLocatable ( ) and
933
+ useImportEdge ( use , name , item )
934
+ }
935
+
936
+ ItemNode debugGetASuccessorRec ( ItemNode i , string name ) {
937
+ i = getRelevantLocatable ( ) and
938
+ result = i .getASuccessor ( name )
939
+ }
940
+
941
+ predicate debugFileImportEdge ( Module mod , string name , ItemNode item ) {
942
+ mod = getRelevantLocatable ( ) and
943
+ fileImportEdge ( mod , name , item )
944
+ }
945
+
946
+ predicate debugFileImport ( Module m , SourceFile f ) {
947
+ m = getRelevantLocatable ( ) and
948
+ fileImport ( m , f )
949
+ }
950
+ }
0 commit comments