@@ -45,6 +45,12 @@ signature module UniversalFlowInput<LocationSig Location> {
4545 Location getLocation ( ) ;
4646 }
4747
48+ /**
49+ * Gets an identifier for node `n`, if any. When not implemented for a given node,
50+ * the library will use location-based ranking.
51+ */
52+ default int getFlowNodeId ( FlowNode n ) { none ( ) }
53+
4854 /**
4955 * Holds if data can flow from `n1` to `n2` in one step.
5056 *
@@ -149,17 +155,40 @@ module Make<LocationSig Location, UniversalFlowInput<Location> I> {
149155 private module RankEdge< Edge E> implements RankedEdge< E:: Node > {
150156 private import E
151157
158+ private int getFlowNodeIdByLoc ( FlowNode n ) {
159+ n =
160+ rank [ result ] ( FlowNode n0 , string filePath , int startline , int startcolumn |
161+ not exists ( getFlowNodeId ( n0 ) ) and
162+ n0 .getLocation ( ) .hasLocationInfo ( filePath , startline , startcolumn , _, _)
163+ |
164+ n0 order by filePath , startline , startcolumn
165+ )
166+ }
167+
168+ private int getFlowNodeIdExt ( FlowNode n ) {
169+ n =
170+ rank [ result ] ( FlowNode n0 , int a , int b |
171+ a = 0 and
172+ b = getFlowNodeId ( n0 )
173+ or
174+ a = 1 and
175+ b = getFlowNodeIdByLoc ( n0 )
176+ |
177+ n0 order by a , b
178+ )
179+ }
180+
152181 /**
153182 * Holds if `r` is a ranking of the incoming edges `(n1,n2)` to `n2`. The used
154183 * ordering is not necessarily total, so the ranking may have gaps.
155184 */
156185 private predicate edgeRank1 ( int r , FlowNode n1 , Node n2 ) {
157186 n1 =
158- rank [ r ] ( FlowNode n , int startline , int startcolumn |
187+ rank [ r ] ( FlowNode n , int id |
159188 edge ( n , n2 ) and
160- n . getLocation ( ) . hasLocationInfo ( _ , startline , startcolumn , _ , _ )
189+ id = getFlowNodeIdExt ( n )
161190 |
162- n order by startline , startcolumn
191+ n order by id
163192 )
164193 }
165194
0 commit comments