@@ -326,19 +326,25 @@ module API {
326326
327327 /** A node representing a module/class object with epsilon edges to its descendents. */
328328 private class ModuleNode extends Node , Impl:: MkModule {
329- /** Gets the module represented by this API node. */
330- string getModule ( ) { this = Impl :: MkModule ( result ) }
329+ string qualifiedModule ;
330+ int n ;
331331
332- override string toString ( ) { result = "Module(" + this . getModule ( ) + ")" }
332+ ModuleNode ( ) { this = Impl :: MkModule ( qualifiedModule , n ) }
333333
334- TypeNode getType ( string name ) { result .getType ( ) = this .getModule ( ) + "." + name } // TODO: Check that name exists in module
335- }
334+ ModuleNode getNext ( ) { result = Impl:: MkModule ( qualifiedModule , n + 1 ) }
335+
336+ ModuleNode getPred ( ) { result .getNext ( ) = this }
337+
338+ string getComponent ( ) { result = qualifiedModule .splitAt ( "." , n ) }
336339
337- private class TypeNode extends Node , Impl:: MkType {
338- /** Gets the type represented by this API node. */
339- string getType ( ) { this = Impl:: MkType ( result ) }
340+ string getModule ( ) {
341+ not exists ( this .getPred ( ) ) and
342+ result = this .getComponent ( )
343+ or
344+ result = this .getPred ( ) .getModule ( ) + "." + this .getComponent ( )
345+ }
340346
341- override string toString ( ) { result = "Type (" + this .getType ( ) + ")" }
347+ override string toString ( ) { result = "Module (" + this .getModule ( ) + ")" }
342348 }
343349
344350 /** A node representing instances of a module/class with epsilon edges to its ancestors. */
@@ -413,13 +419,7 @@ module API {
413419 * Gets the node that represents the module with qualified
414420 * name `qualifiedModule`.
415421 */
416- ModuleNode mod ( string qualifiedModule ) { result = Impl:: MkModule ( qualifiedModule ) }
417-
418- /**
419- * Gets the node that represents the type with qualified
420- * name `qualifiedType`.
421- */
422- TypeNode type ( string qualifiedType ) { result = Impl:: MkType ( qualifiedType ) }
422+ ModuleNode mod ( string qualifiedModule , int n ) { result = Impl:: MkModule ( qualifiedModule , n ) }
423423
424424 /**
425425 * Gets an unqualified call at the top-level with the given method name.
@@ -466,26 +466,31 @@ module API {
466466
467467 cached
468468 private module Impl {
469+
470+ private predicate isModule ( string s , int n ) {
471+ (
472+ any ( UsingStmt using ) .getName ( ) = s
473+ or
474+ any ( Cmd cmd ) .getNamespaceQualifier ( ) = s
475+ or
476+ any ( TypeNameExpr tn ) .getName ( ) = s
477+ or
478+ any ( ModuleManifest manifest ) .getModuleName ( ) = s
479+ ) and
480+ exists ( s .splitAt ( "." , n ) )
481+ }
482+
469483 cached
470484 newtype TApiNode =
471485 /** The root of the API graph. */
472486 MkRoot ( ) or
473487 /** The method accessed at `call`, synthetically treated as a separate object. */
474488 MkMethodAccessNode ( DataFlow:: CallNode call ) or
475- MkModule ( string qualifiedModule ) {
476- any ( UsingStmt using ) .getName ( ) = qualifiedModule
477- or
478- any ( Cmd cmd ) .getNamespaceQualifier ( ) = qualifiedModule
479- or
480- any ( TypeNameExpr tn ) .getName ( ) = qualifiedModule
481- or
482- any ( ModuleManifest manifest ) .getModuleName ( ) = qualifiedModule
483- } or
484- MkType ( string qualifiedType ) { any ( ConstantValue cv ) .asString ( ) = qualifiedType } or // TODO
489+ MkModule ( string qualifiedModule , int n ) { isModule ( qualifiedModule , n ) } or
485490 /** Instances of `mod` with epsilon edges to its ancestors. */
486- MkInstanceUp ( string qualifiedType ) { exists ( MkType ( qualifiedType ) ) } or
491+ MkInstanceUp ( string qualifiedType ) { exists ( MkModule ( qualifiedType , _ ) ) } or
487492 /** Instances of `mod` with epsilon edges to its descendents, and to its upward node. */
488- MkInstanceDown ( string qualifiedType ) { exists ( MkType ( qualifiedType ) ) } or
493+ MkInstanceDown ( string qualifiedType ) { exists ( MkModule ( qualifiedType , _ ) ) } or
489494 /** Intermediate node for following forward data flow. */
490495 MkForwardNode ( DataFlow:: LocalSourceNode node , TypeTracker t ) { isReachable ( node , t ) } or
491496 /** Intermediate node for following backward data flow. */
@@ -525,14 +530,6 @@ module API {
525530 )
526531 }
527532
528- cached
529- predicate typeEdge ( Node pred , string name , Node succ ) {
530- exists ( ModuleNode mod |
531- pred = mod and
532- succ = mod .getType ( name )
533- )
534- }
535-
536533 cached
537534 predicate memberEdge ( Node pred , string name , Node succ ) {
538535 exists ( MemberExpr member | succ = getForwardStartNode ( getNodeFromExpr ( member ) ) |
@@ -546,8 +543,9 @@ module API {
546543 exists ( DataFlow:: CallNode call | succ = MkMethodAccessNode ( call ) and name = call .getName ( ) |
547544 pred = getForwardEndNode ( getALocalSourceStrict ( call .getQualifier ( ) ) )
548545 or
549- exists ( string qualifiedModule , ModuleManifest manifest |
550- pred = mod ( qualifiedModule ) and
546+ exists ( string qualifiedModule , ModuleManifest manifest , int n |
547+ pred = mod ( qualifiedModule , n ) and
548+ not exists ( mod ( qualifiedModule , n + 1 ) ) and
551549 manifest .getModuleName ( ) = qualifiedModule
552550 |
553551 manifest .getACmdLetToExport ( ) = name
@@ -647,8 +645,15 @@ module API {
647645
648646 cached
649647 predicate instanceEdge ( Node pred , Node succ ) {
650- // An instance of a type
651- exists ( string qualifiedType | pred = MkType ( qualifiedType ) |
648+ exists ( string qualifiedType , int n |
649+ pred = MkModule ( qualifiedType , n ) and
650+ not exists ( MkModule ( qualifiedType , n + 1 ) )
651+ |
652+ exists ( DataFlow:: TypeNameNode typeName |
653+ typeName .getTypeName ( ) = qualifiedType and
654+ succ = getForwardStartNode ( typeName )
655+ )
656+ or
652657 exists ( DataFlow:: ObjectCreationNode objCreation |
653658 objCreation .getConstructedTypeName ( ) = qualifiedType and
654659 succ = getForwardStartNode ( objCreation )
@@ -659,15 +664,6 @@ module API {
659664 succ = getForwardStartNode ( p )
660665 )
661666 )
662- or
663- // A use of a module (or static type?)
664- // TODO: Consider implicit module qualiifers and use instance on all of them
665- exists ( string qualifiedType , DataFlow:: TypeNameNode typeName |
666- pred = MkModule ( qualifiedType ) and
667- typeName .getTypeName ( ) = qualifiedType
668- |
669- succ = getForwardStartNode ( typeName )
670- )
671667 }
672668
673669 cached
0 commit comments