2222import java .util .stream .Collectors ;
2323
2424import org .eclipse .core .runtime .CoreException ;
25- import org .eclipse .core .runtime .NullProgressMonitor ;
25+ import org .eclipse .core .runtime .IProgressMonitor ;
26+ import org .eclipse .core .runtime .SubMonitor ;
2627import org .eclipse .jdt .core .JavaModelException ;
2728
2829import com .google .common .collect .HashBasedTable ;
@@ -567,8 +568,11 @@ private boolean deriveRomForNonScalarMethod(Collection<TypeAbstraction> possible
567568 }
568569
569570 private void discoverIfReduceOrderingPossiblyMatters (EclipseProjectAnalysisEngine <InstanceKey > engine ,
570- OrderingInference orderingInference ) throws UTFDataFormatException , JavaModelException ,
571- NoniterableException , NoninstantiableException , CannotExtractSpliteratorException {
571+ OrderingInference orderingInference , IProgressMonitor monitor ) throws UTFDataFormatException ,
572+ JavaModelException , NoniterableException , NoninstantiableException , CannotExtractSpliteratorException {
573+ monitor .beginTask ("Discovering if reduce order matters..." ,
574+ this .terminalBlockToPossibleReceivers .keySet ().size ());
575+
572576 // for each terminal operation call, I think?
573577 for (BasicBlockInContext <IExplodedBasicBlock > block : this .terminalBlockToPossibleReceivers .keySet ()) {
574578 int processedInstructions = 0 ;
@@ -648,6 +652,7 @@ private void discoverIfReduceOrderingPossiblyMatters(EclipseProjectAnalysisEngin
648652 ++processedInstructions ;
649653 }
650654 assert processedInstructions == 1 : "Expecting to process one and only one instruction here." ;
655+ monitor .worked (1 );
651656 }
652657 }
653658
@@ -721,8 +726,10 @@ private void discoverLambdaSideEffects(EclipseProjectAnalysisEngine<InstanceKey>
721726 LOGGER .warning ("Def was an instance of a: " + def .getClass ());
722727 }
723728
724- private void discoverPossibleSideEffects (EclipseProjectAnalysisEngine <InstanceKey > engine )
729+ private void discoverPossibleSideEffects (EclipseProjectAnalysisEngine <InstanceKey > engine , IProgressMonitor monitor )
725730 throws IOException , CoreException {
731+ SubMonitor subMonitor = SubMonitor .convert (monitor , "Discovering side-effects..." , 100 );
732+
726733 // create the ModRef analysis.
727734 ModRef <InstanceKey > modRef = ModRef .make ();
728735
@@ -732,6 +739,9 @@ private void discoverPossibleSideEffects(EclipseProjectAnalysisEngine<InstanceKe
732739 Map <CGNode , OrdinalSet <PointerKey >> mod = modRef .computeMod (engine .getCallGraph (), engine .getPointerAnalysis ());
733740
734741 // for each terminal operation call, I think?
742+ SubMonitor loopMonitor = subMonitor .split (50 , SubMonitor .SUPPRESS_NONE )
743+ .setWorkRemaining (this .terminalBlockToPossibleReceivers .keySet ().size ());
744+
735745 for (BasicBlockInContext <IExplodedBasicBlock > block : this .terminalBlockToPossibleReceivers .keySet ()) {
736746 int processedInstructions = 0 ;
737747 for (SSAInstruction instruction : block ) {
@@ -760,10 +770,13 @@ private void discoverPossibleSideEffects(EclipseProjectAnalysisEngine<InstanceKe
760770 }
761771
762772 assert processedInstructions == 1 : "Expecting to process one and only one instruction here." ;
773+ loopMonitor .worked (1 );
763774 }
764775
765776 // for each instance in the analysis result (these should be the
766777 // "intermediate" streams).
778+ loopMonitor = subMonitor .split (50 , SubMonitor .SUPPRESS_NONE ).setWorkRemaining (this .trackedInstances .size ());
779+
767780 for (InstanceKey instance : this .trackedInstances ) {
768781 // make sure that the stream is the result of an intermediate
769782 // operation.
@@ -792,14 +805,18 @@ private void discoverPossibleSideEffects(EclipseProjectAnalysisEngine<InstanceKe
792805 this .discoverLambdaSideEffects (engine , mod , Collections .singleton (instance ),
793806 callString .getMethods ()[0 ].getReference (), ir , use );
794807 }
808+
809+ loopMonitor .worked (1 );
795810 }
796811 }
797812
798- private void discoverPossibleStatefulIntermediateOperations (IClassHierarchy hierarchy , CallGraph callGraph )
799- throws IOException , CoreException {
813+ private void discoverPossibleStatefulIntermediateOperations (IClassHierarchy hierarchy , CallGraph callGraph ,
814+ IProgressMonitor monitor ) throws IOException , CoreException {
815+ monitor .beginTask ("Discovering stateful intermediate operations..." , this .trackedInstances .size ());
816+
800817 // for each instance in the analysis result (these should be the
801818 // "intermediate" streams).
802- for (InstanceKey instance : this .trackedInstances )
819+ for (InstanceKey instance : this .trackedInstances ) {
803820 if (!this .instanceToStatefulIntermediateOperationContainment .containsKey (instance )) {
804821 // make sure that the stream is the result of an intermediate
805822 // operation.
@@ -816,21 +833,26 @@ private void discoverPossibleStatefulIntermediateOperations(IClassHierarchy hier
816833 }
817834 this .instanceToStatefulIntermediateOperationContainment .put (instance , found );
818835 }
836+ monitor .worked (1 );
837+ }
819838 }
820839
821- private void discoverTerminalOperations () {
840+ private void discoverTerminalOperations (IProgressMonitor monitor ) {
822841 Collection <OrdinalSet <InstanceKey >> receiverSetsThatHaveTerminalOperations = this .terminalBlockToPossibleReceivers
823842 .values ();
824843
825844 // This will be the OK set.
826845 Collection <InstanceKey > validStreams = new HashSet <>();
827846
828847 // Now, we need to flatten the receiver sets.
829- for (OrdinalSet <InstanceKey > receiverSet : receiverSetsThatHaveTerminalOperations )
848+ monitor .beginTask ("Flattening..." , receiverSetsThatHaveTerminalOperations .size ());
849+ for (OrdinalSet <InstanceKey > receiverSet : receiverSetsThatHaveTerminalOperations ) {
830850 // for each receiver set
831851 for (InstanceKey instance : receiverSet )
832852 // add it to the OK set.
833853 validStreams .add (instance );
854+ monitor .worked (1 );
855+ }
834856
835857 // Now, we have the OK set. Let's propagate it.
836858 this .propagateStreamInstanceProperty (validStreams );
@@ -864,8 +886,9 @@ private void fillInstanceToPredecessorMap(EclipseProjectAnalysisEngine<InstanceK
864886 }
865887 }
866888
867- private void fillInstanceToStreamMap (Set <Stream > streamSet , EclipseProjectAnalysisEngine <InstanceKey > engine )
868- throws InvalidClassFileException , IOException , CoreException {
889+ private void fillInstanceToStreamMap (Set <Stream > streamSet , EclipseProjectAnalysisEngine <InstanceKey > engine ,
890+ IProgressMonitor monitor ) throws InvalidClassFileException , IOException , CoreException {
891+ monitor .beginTask ("Propagating..." , streamSet .size ());
869892 int skippedStreams = 0 ;
870893 for (Stream stream : streamSet ) {
871894 InstanceKey instanceKey = null ;
@@ -904,6 +927,7 @@ private void fillInstanceToStreamMap(Set<Stream> streamSet, EclipseProjectAnalys
904927 LOGGER .warning ("Reassociating stream: " + stream .getCreation () + " with: " + instanceKey
905928 + ". Old stream was: " + oldValue .getCreation () + "." );
906929
930+ monitor .worked (1 );
907931 } // end each stream.
908932
909933 // sanity check since it's a bijection.
@@ -952,9 +976,10 @@ private void propagateStreamInstanceProperty(Collection<InstanceKey> streamInsta
952976 }
953977
954978 public Map <TypestateRule , Statistics > start (Set <Stream > streamSet , EclipseProjectAnalysisEngine <InstanceKey > engine ,
955- OrderingInference orderingInference )
979+ OrderingInference orderingInference , IProgressMonitor monitor )
956980 throws PropertiesException , CancelException , IOException , CoreException , NoniterableException ,
957981 NoninstantiableException , CannotExtractSpliteratorException , InvalidClassFileException {
982+ SubMonitor subMonitor = SubMonitor .convert (monitor , "Performing typestate analysis (may take a while)" , 100 );
958983 Map <TypestateRule , Statistics > ret = new HashMap <>();
959984
960985 BenignOracle ora = new ModifiedBenignOracle (engine .getCallGraph (), engine .getPointerAnalysis ());
@@ -973,6 +998,8 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
973998 StreamAttributeTypestateRule [] ruleArray = createStreamAttributeTypestateRules (streamClass );
974999
9751000 // for each rule.
1001+ SubMonitor ruleMonitor = subMonitor .split (70 , SubMonitor .SUPPRESS_NONE ).setWorkRemaining (ruleArray .length );
1002+
9761003 for (StreamAttributeTypestateRule rule : ruleArray ) {
9771004 // create a DFA based on the rule.
9781005 TypeStateProperty dfa = new TypeStateProperty (rule , engine .getClassHierarchy ());
@@ -984,7 +1011,7 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
9841011
9851012 AggregateSolverResult result ;
9861013 try {
987- result = (AggregateSolverResult ) solver .perform (new NullProgressMonitor ( ));
1014+ result = (AggregateSolverResult ) solver .perform (ruleMonitor . split ( 50 , SubMonitor . SUPPRESS_NONE ));
9881015 } catch (SolverTimeoutException | MaxFindingsException | SetUpException | WalaException e ) {
9891016 throw new RuntimeException ("Exception caught during typestate analysis." , e );
9901017 }
@@ -997,6 +1024,9 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
9971024 assert lastStatistics == null : "Reassociating statistics." ;
9981025
9991026 // for each instance in the typestate analysis result.
1027+ SubMonitor instanceMonitor = ruleMonitor .split (20 , SubMonitor .SUPPRESS_NONE )
1028+ .setWorkRemaining (result .totalInstancesNum ());
1029+
10001030 for (Iterator <InstanceKey > iterator = result .iterateInstances (); iterator .hasNext ();) {
10011031 // get the instance's key.
10021032 InstanceKey instanceKey = iterator .next ();
@@ -1140,6 +1170,7 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
11401170 }
11411171 }
11421172 }
1173+ instanceMonitor .worked (1 );
11431174 } // end for each instance in the typestate analysis result.
11441175
11451176 // fill the instance to predecessors map if it's empty.
@@ -1183,23 +1214,26 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
11831214 });
11841215 }
11851216 }
1217+ ruleMonitor .worked (1 );
11861218 } // end for each rule.
11871219
11881220 // create a mapping between stream instances (from the analysis) and stream
11891221 // objects (from the refactoring).
1190- this .fillInstanceToStreamMap (streamSet , engine );
1222+ this .fillInstanceToStreamMap (streamSet , engine , subMonitor . split ( 5 , SubMonitor . SUPPRESS_NONE ) );
11911223
1192- this .discoverTerminalOperations ();
1224+ this .discoverTerminalOperations (subMonitor . split ( 5 , SubMonitor . SUPPRESS_NONE ) );
11931225
11941226 // fill the instance side-effect set.
1195- this .discoverPossibleSideEffects (engine );
1227+ this .discoverPossibleSideEffects (engine , subMonitor . split ( 5 , SubMonitor . SUPPRESS_NONE ) );
11961228
11971229 // discover whether any stateful intermediate operations are
11981230 // present.
1199- this .discoverPossibleStatefulIntermediateOperations (engine .getClassHierarchy (), engine .getCallGraph ());
1231+ this .discoverPossibleStatefulIntermediateOperations (engine .getClassHierarchy (), engine .getCallGraph (),
1232+ subMonitor .split (5 , SubMonitor .SUPPRESS_NONE ));
12001233
12011234 // does reduction order matter?
1202- this .discoverIfReduceOrderingPossiblyMatters (engine , orderingInference );
1235+ this .discoverIfReduceOrderingPossiblyMatters (engine , orderingInference ,
1236+ subMonitor .split (5 , SubMonitor .SUPPRESS_NONE ));
12031237
12041238 // propagate the instances with side-effects.
12051239 this .propagateStreamInstanceProperty (this .instancesWithSideEffects );
0 commit comments