+
+
+ protected void computeLeafSESEs() {
+ for( Iterator<FlatSESEEnterNode> itr = allSESEs.iterator();
+ itr.hasNext();
+ ) {
+ FlatSESEEnterNode fsen = itr.next();
+
+ boolean hasNoNestedChildren = !fsen.getChildren().isEmpty();
+ boolean hasNoChildrenByCall = !hasChildrenByCall( fsen );
+
+ fsen.setIsLeafSESE( hasNoNestedChildren &&
+ hasNoChildrenByCall );
+ }
+ }
+
+
+ protected boolean hasChildrenByCall( FlatSESEEnterNode fsen ) {
+
+ // visit every flat node in SESE body, find method calls that
+ // may transitively call methods with SESEs enclosed
+ Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+ flatNodesToVisit.add( fsen );
+
+ Set<FlatNode> visited = new HashSet<FlatNode>();
+
+ while( !flatNodesToVisit.isEmpty() ) {
+ Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
+ FlatNode fn = fnItr.next();
+
+ flatNodesToVisit.remove( fn );
+ visited.add( fn );
+
+ if( fn.kind() == FKind.FlatCall ) {
+ FlatCall fc = (FlatCall) fn;
+ MethodDescriptor mdCallee = fc.getMethod();
+ Set reachable = new HashSet();
+
+ reachable.addAll( callGraph.getAllMethods( mdCallee ) );
+ reachable.retainAll( methodsContainingSESEs );
+
+ if( !reachable.isEmpty() ) {
+ return true;
+ }
+ }
+
+ if( fn == fsen.getFlatExit() ) {
+ // don't enqueue any futher nodes
+ continue;
+ }
+
+ for( int i = 0; i < fn.numNext(); i++ ) {
+ FlatNode nn = fn.getNext( i );
+
+ if( !visited.contains( nn ) ) {
+ flatNodesToVisit.add( nn );
+ }
+ }
+ }
+
+ return false;
+ }
+