@@ -198,13 +198,9 @@ module API {
198198 }
199199
200200 /** A node corresponding to the use of an API component. */
201- class Use extends Node , Impl:: TUse {
201+ class Use extends Node , Impl:: MkUse {
202202 override string toString ( ) {
203- exists ( string type |
204- this = Impl:: MkUse ( _) and type = "Use "
205- or
206- this = Impl:: MkModule ( _) and type = "ModuleUse "
207- |
203+ exists ( string type | this = Impl:: MkUse ( _) and type = "Use " |
208204 result = type + getPath ( )
209205 or
210206 not exists ( this .getPath ( ) ) and result = type + "with no path"
@@ -216,27 +212,15 @@ module API {
216212 Root root ( ) { any ( ) }
217213
218214 /**
219- * Gets a node corresponding to an import of module `m`.
215+ * Gets a node corresponding to a top-level member `m` (typically a module).
216+ *
217+ * This is equivalent to `root().getAMember("m")`.
220218 *
221219 * Note: You should only use this predicate for top level modules or classes. If you want nodes corresponding to a nested module or class,
222220 * you should use `.getMember` on the parent module/class. For example, for nodes corresponding to the class `Gem::Version`,
223- * use `moduleImport ("Gem").getMember("Version")`.
221+ * use `getTopLevelMember ("Gem").getMember("Version")`.
224222 */
225- Node moduleImport ( string m ) {
226- result = Impl:: MkModule ( m ) and not m .matches ( "%::%" )
227- or
228- result = Impl:: MkUse ( unresolvedModuleReference ( m ) )
229- }
230-
231- DataFlow:: Node unresolvedModuleReference ( string m ) {
232- exists ( ConstantReadAccess iexpr , DataFlow:: Node node |
233- not exists ( resolveScopeExpr ( iexpr ) ) and
234- not exists ( iexpr .getScopeExpr ( ) ) and
235- m = iexpr .getName ( ) and
236- result = node and
237- node .asExpr ( ) .getExpr ( ) = iexpr
238- )
239- }
223+ Node getTopLevelMember ( string m ) { result = root ( ) .getMember ( m ) }
240224
241225 /**
242226 * Provides the actual implementation of API graphs, cached for performance.
@@ -266,23 +250,29 @@ module API {
266250 newtype TApiNode =
267251 /** The root of the API graph. */
268252 MkRoot ( ) or
269- /** An abstract representative for imports of the module called `name`. */
270- MkModule ( string name ) { exists ( TResolved ( name ) ) } or
271253 /** A use of an API member at the node `nd`. */
272- MkUse ( DataFlow:: Node nd ) {
273- use ( _, _, nd )
274- or
275- nd = unresolvedModuleReference ( _)
276- }
277-
278- class TUse = MkModule or MkUse ;
254+ MkUse ( DataFlow:: Node nd ) { use ( _, _, nd ) }
279255
280256 /**
281257 * Holds if `ref` is a use of a node that should have an incoming edge from `base` labeled
282258 * `lbl` in the API graph.
283259 */
284260 cached
285261 predicate use ( TApiNode base , string lbl , DataFlow:: Node ref ) {
262+ base = MkRoot ( ) and
263+ exists ( string name , ExprNodes:: ConstantAccessCfgNode access , ConstantReadAccess read |
264+ access = ref .asExpr ( ) and
265+ lbl = Label:: member ( read .getName ( ) ) and
266+ read = access .getExpr ( )
267+ |
268+ TResolved ( name ) = resolveScopeExpr ( read ) and
269+ not name .matches ( "%::%" )
270+ or
271+ name = read .getName ( ) and
272+ not exists ( resolveScopeExpr ( read ) ) and
273+ not exists ( read .getScopeExpr ( ) )
274+ )
275+ or
286276 exists ( DataFlow:: LocalSourceNode src , DataFlow:: LocalSourceNode pred |
287277 // First, we find a predecessor of the node `ref` that we want to determine. The predecessor
288278 // is any node that is a type-tracked use of a data flow node (`src`), which is itself a
@@ -331,16 +321,7 @@ module API {
331321 * Holds if `ref` is a use of node `nd`.
332322 */
333323 cached
334- predicate use ( TApiNode nd , DataFlow:: Node ref ) {
335- exists ( string name , ExprNodes:: ConstantAccessCfgNode access , ConstantReadAccess read |
336- access = ref .asExpr ( ) and
337- nd = MkModule ( name ) and
338- read = access .getExpr ( ) and
339- TResolved ( name ) = resolveScopeExpr ( read )
340- )
341- or
342- nd = MkUse ( ref )
343- }
324+ predicate use ( TApiNode nd , DataFlow:: Node ref ) { nd = MkUse ( ref ) }
344325
345326 /**
346327 * Gets a data-flow node to which `src`, which is a use of an API-graph node, flows.
@@ -370,14 +351,6 @@ module API {
370351 */
371352 cached
372353 predicate edge ( TApiNode pred , string lbl , TApiNode succ ) {
373- /* There's an edge from the root node for each imported module. */
374- exists ( string m |
375- pred = MkRoot ( ) and
376- lbl = Label:: mod ( m )
377- |
378- succ = moduleImport ( m )
379- )
380- or
381354 /* Every node that is a use of an API component is itself added to the API graph. */
382355 exists ( DataFlow:: LocalSourceNode ref |
383356 use ( pred , lbl , ref ) and
@@ -397,11 +370,6 @@ module API {
397370}
398371
399372private module Label {
400- /** Gets the edge label for the module `m`. */
401- bindingset [ m]
402- bindingset [ result ]
403- string mod ( string m ) { result = "moduleImport(\"" + m + "\")" }
404-
405373 /** Gets the `member` edge label for member `m`. */
406374 bindingset [ m]
407375 bindingset [ result ]
0 commit comments