Skip to content

Commit 2c7c377

Browse files
committed
documentation of views
1 parent 320b1b9 commit 2c7c377

12 files changed

Lines changed: 381 additions & 63 deletions

File tree

src/main/java/org/variantsync/diffdetective/experiments/views/Main.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
import java.util.ArrayList;
1717
import java.util.List;
1818

19+
/**
20+
* Main entry point for running the feasibility study (Section 6) of our SPLC'23 paper
21+
* Views on Edits to Variational Software.
22+
*/
1923
public class Main {
2024
/*
2125
* There is a bug in DiffView::naive when ignoreEmptyLines is set to true under
@@ -36,7 +40,13 @@ public class Main {
3640
false
3741
);
3842

39-
public static Analysis AnalysisFactory(Repository repo, Path repoOutputDir) {
43+
/**
44+
* Creates the analysis to perform on the given repository to run our feasibility study.
45+
* @param repo The repository to run the feasibility study on.
46+
* @param repoOutputDir The directory to which output should be written.
47+
* @return The analysis to run.
48+
*/
49+
private static Analysis AnalysisFactory(Repository repo, Path repoOutputDir) {
4050
return new Analysis(
4151
"Views Analysis",
4252
new ArrayList<>(List.of(
@@ -51,6 +61,11 @@ public static Analysis AnalysisFactory(Repository repo, Path repoOutputDir) {
5161
);
5262
}
5363

64+
/**
65+
* Main method for running the feasibility study (Section 6).
66+
* @param args see {@link AnalysisRunner.Options#DEFAULT(String[])}
67+
* @throws IOException When an IO operation within the feasibility study fails.
68+
*/
5469
public static void main(String[] args) throws IOException {
5570
final AnalysisRunner.Options defaultOptions = AnalysisRunner.Options.DEFAULT(args);
5671
final AnalysisRunner.Options analysisOptions = new AnalysisRunner.Options(

src/main/java/org/variantsync/diffdetective/experiments/views/ViewAnalysis.java

Lines changed: 116 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,27 @@
2424

2525
import static org.variantsync.diffdetective.util.fide.FormulaUtils.negate;
2626

27+
/**
28+
* Implementation of the feasibility study from Section 6 of our paper
29+
* Views on Edits to Variational Software
30+
* at SPLC'23.
31+
* This Analysis is run on a batch of commits of a single repository.
32+
* For the whole feasibility study, multiple analysis are run in parallel, each
33+
* processing a part of a repositories history.
34+
*/
2735
public class ViewAnalysis implements Analysis.Hooks {
28-
// Result data
36+
/**
37+
* File extension for csv files created by this analysis.
38+
*/
2939
public static final String VIEW_CSV_EXTENSION = ".views.csv";
40+
/**
41+
* StringBuilder that is used to iteratively create a csv file with this analysis' results.
42+
*/
3043
private StringBuilder csv;
44+
/**
45+
* Random instance to generate random numbers.
46+
* Used to generate random relevance predicates.
47+
*/
3148
private Random random;
3249

3350
@Override
@@ -40,6 +57,18 @@ public void initializeResults(Analysis analysis) {
4057
csv.append(ViewEvaluation.makeHeader(CSV.DEFAULT_CSV_DELIMITER)).append(StringUtils.LINEBREAK);
4158
}
4259

60+
/**
61+
* Benchmark for view generation on the given variation diff with the given relevance.
62+
* This method generates a view once with each algorithm:
63+
* - once with the {@link DiffView#naive(DiffTree, Relevance) naive algorithm} view_naive (Equation 8 from our paper),
64+
* - and once with the {@link DiffView#optimized(DiffTree, Relevance) optimized algorithm} view_smart (Equation 10 in our paper).
65+
* This method measures both algorithms runtimes and stores the runtimes and metadata in terms of a
66+
* {@link ViewEvaluation} in this objects {@link #csv} field.
67+
* @param analysis The current instance of the analysis that is run.
68+
* Used to access metadata of the current commit that is processed.
69+
* @param d The variation diff to benchmark view generation on.
70+
* @param rho A relevance predicate that determines which nodes should be contained in the view.
71+
*/
4372
private void runRelevanceExperiment(Analysis analysis, final DiffTree d, final Relevance rho) {
4473
final long preprocessingTime, naiveTime, optimizedTime;
4574

@@ -84,6 +113,16 @@ private void runRelevanceExperiment(Analysis analysis, final DiffTree d, final R
84113
// return Analysis.Hooks.super.onParsedCommit(analysis);
85114
// }
86115

116+
/**
117+
* Runs the feasibility study on the current variation diff.
118+
* Creates random relevance predicates as explained in Section 6 of our paper.
119+
* Then runs {@link #runRelevanceExperiment(Analysis, DiffTree, Relevance)} for each relevance on the
120+
* current variation diff.
121+
* @param analysis The current instance of the analysis that is run.
122+
* Used to access metadata of the current commit that is processed.
123+
* @return {@link Analysis.Hooks#analyzeDiffTree(Analysis)}
124+
* @throws Exception
125+
*/
87126
@Override
88127
public boolean analyzeDiffTree(Analysis analysis) throws Exception {
89128
final DiffTree d = analysis.getCurrentDiffTree();
@@ -96,6 +135,14 @@ public boolean analyzeDiffTree(Analysis analysis) throws Exception {
96135
return Analysis.Hooks.super.analyzeDiffTree(analysis);
97136
}
98137

138+
/**
139+
* Generates random relevance predicates for creating random views on
140+
* the given variation diff d, as explained in Section 6.1 in our paper.
141+
* If possible, this method will generate one relevance of each type of
142+
* {@link Configure}, {@link Trace}, and {@link Search}.
143+
* @param d The variation diff to generate relevance predicates for.
144+
* @return A list of three random relevance predicates.
145+
*/
99146
private List<Relevance> generateRandomRelevances(final DiffTree d) {
100147
final List<Node> deselectedPCs = new ArrayList<>();
101148
final Set<String> features = new HashSet<>();
@@ -133,7 +180,20 @@ else if (a.isConditionalAnnotation()) {
133180

134181
return relevances;
135182
}
136-
183+
184+
/**
185+
* This is a convenience method for creating a random relevance predicate from a collection of
186+
* potential parameterisations.
187+
* <p>
188+
* If the given collection {@code source} of parameters for relevance predicates is not empty, this method
189+
* picks a random parameterization and creates a relevance predicate from it.
190+
* The created predicate is added to the given target collection.
191+
* @param source A potentially empty collection of arguments for relevance predicates.
192+
* @param pick A function that picks a parameterisation at random and creates a relevance predicate from it.
193+
* @param target A collection to which the randomly created relevance predicate will be added to.
194+
* @param <RelevanceParams> The type of the parameters for the relevance predicates.
195+
* @param <RelevanceCandidates> The type of collection of the parameters.
196+
*/
137197
private static <RelevanceParams, RelevanceCandidates extends Collection<RelevanceParams>> void addRandomRelevance(
138198
RelevanceCandidates source,
139199
Function<RelevanceCandidates, Relevance> pick,
@@ -147,6 +207,17 @@ private static <RelevanceParams, RelevanceCandidates extends Collection<Relevanc
147207
}
148208
}
149209

210+
/**
211+
* This is a convenience method for creating relevance predicates from their parameters.
212+
* <p>
213+
* If the given collection of parameters for relevance predicates is not empty, this method
214+
* generates corresponding relevance predicates for all those predicates and adds them to the given target collection.
215+
* @param source A potentially empty collection of arguments for relevance predicates.
216+
* @param prepare A function that creates a relevance predicate from suitable arguments.
217+
* @param target A collection to which all relevance predicates will be added to.
218+
* @param <RelevanceParams> The type of the parameters for the relevance predicates.
219+
* @param <RelevanceCandidates> The type of collection of the parameters.
220+
*/
150221
private static <RelevanceParams, RelevanceCandidates extends Collection<? extends RelevanceParams>> void addAll(
151222
RelevanceCandidates source,
152223
Function<? super RelevanceCandidates, ? extends Collection<? extends Relevance>> prepare,
@@ -157,6 +228,14 @@ private static <RelevanceParams, RelevanceCandidates extends Collection<? extend
157228
}
158229
}
159230

231+
/**
232+
* Generates all {@link Configure} relevance predicates that can be generated from the given list of
233+
* deselected presence conditions.
234+
* The returned list of predicates is complete: For every (partial) variant of the variation tree or diff the
235+
* deselected presence conditions come from, a corresponding relevance predicate is within the returned list.
236+
* @param deselectedPCs A list of negations of all presence conditions that occur in a variation tree or diff.
237+
* @return A complete list of {@link Configure} predicates.
238+
*/
160239
private List<Configure> allConfigureRelevances(final List<Node> deselectedPCs) {
161240
/*
162241
* Select a random satisfiable configuration (i.e., a non-false config).
@@ -174,7 +253,15 @@ private List<Configure> allConfigureRelevances(final List<Node> deselectedPCs) {
174253

175254
return all;
176255
}
177-
256+
257+
/**
258+
* Creates a random {@link Configure} relevance predicate from the given list of
259+
* deselected presence conditions.
260+
* This method picks a random satisfiable formula from the given list and returns it as a relevance predicate
261+
* for configuration.
262+
* @return A random, satisfiable {@link Configure} predicate, created from the given presence conditions.
263+
* Null if the given list is empty or if it does not contain a satisfiable formula.
264+
*/
178265
private Configure randomConfigure(final List<Node> deselectedPCs) {
179266
/*
180267
Do we need this?
@@ -209,11 +296,21 @@ private Configure randomConfigure(final List<Node> deselectedPCs) {
209296

210297
return new Configure(winner);
211298
}
212-
299+
300+
/**
301+
* Generates a {@link Trace} relevance predicate for each feature in the given set of feature names.
302+
* @param features A set of feature names to trace.
303+
* @return A {@link Trace} predicate for each feature name in the given set.
304+
*/
213305
private List<Trace> allTraceRelevances(final Set<String> features) {
214306
return features.stream().map(Trace::new).toList();
215307
}
216308

309+
/**
310+
* Creates a random {@link Trace} relevance predicate from the given set of feature names.
311+
* @param features A set of feature names.
312+
* @return A {@link Trace} predicate for a feature name randomly picked from the given set.
313+
*/
217314
private Trace randomTrace(final Set<String> features) {
218315
/*
219316
Pick a random feature for our relevance.
@@ -223,10 +320,20 @@ private Trace randomTrace(final Set<String> features) {
223320
return new Trace(CollectionUtils.getRandomElement(random, features));
224321
}
225322

323+
/**
324+
* Generates a {@link Search} relevance predicate for each artifact in the given set.
325+
* @param artifacts A list of text-based artifacts.
326+
* @return A {@link Search} predicate for each artifact.
327+
*/
226328
private List<Search> allSearchRelevances(final Set<String> artifacts) {
227329
return artifacts.stream().map(Search::new).toList();
228330
}
229331

332+
/**
333+
* Creates a random {@link Search} relevance predicate from the given set of artifacts.
334+
* @param artifacts A set of text-based artifacts (e.g., lines of code).
335+
* @return A {@link Search} predicate for an artifact randomly picked from the given set.
336+
*/
230337
private Search randomSearch(final Set<String> artifacts) {
231338
/*
232339
Pick a random artifact for our relevance.
@@ -236,6 +343,11 @@ private Search randomSearch(final Set<String> artifacts) {
236343
return new Search(CollectionUtils.getRandomElement(random, artifacts));
237344
}
238345

346+
/**
347+
* Writes the results of this analysis to disk as CSV file.
348+
* @param analysis The current state of the analysis.
349+
* @throws IOException When the file cannot be created or written.
350+
*/
239351
@Override
240352
public void endBatch(Analysis analysis) throws IOException {
241353
IO.write(

src/main/java/org/variantsync/diffdetective/experiments/views/result/ViewEvaluation.java

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,24 @@
22

33
import org.variantsync.diffdetective.util.CSV;
44
import org.variantsync.diffdetective.variation.diff.DiffTree;
5+
import org.variantsync.diffdetective.variation.diff.view.DiffView;
56
import org.variantsync.diffdetective.variation.tree.view.relevance.Relevance;
67
import org.variantsync.diffdetective.variation.tree.view.relevance.Configure;
78

89
import static org.variantsync.functjonal.Functjonal.intercalate;
910

11+
/**
12+
* Single data point in our feasibility study.
13+
* An object of this class corresponds to a row in the CSV files we export.
14+
* This row contains all information for benchmarking a single view generation:
15+
* @param commit The commit on which views were generated.
16+
* @param file The file of the patch that was analysed.
17+
* @param relevance The relevance predicate from which the views were generated.
18+
* @param msNaive Milliseconds it took to generate the view with the {@link DiffView#naive(DiffTree, Relevance) naive algorithm}
19+
* @param msOptimized Milliseconds it took to generate the view with the {@link DiffView#optimized(DiffTree, Relevance) optimized algorithm}
20+
* @param diffStatistics Various statistics on the variation diff of the analysed patch.
21+
* @param viewStatistics The same statistics as for the original variation diff but for the produced view.
22+
*/
1023
public record ViewEvaluation(
1124
// Repository repo,
1225
String commit,
@@ -17,7 +30,18 @@ public record ViewEvaluation(
1730
DiffStatistics diffStatistics,
1831
DiffStatistics viewStatistics
1932
) implements CSV {
33+
/**
34+
* Holds various information of a variation diff.
35+
* @param nodeCount The number of nodes contained in the variation diff.
36+
* @param annotationNodeCount The number of annotation nodes in the variation diff.
37+
*/
2038
public record DiffStatistics(int nodeCount, int annotationNodeCount) {
39+
/**
40+
* Gathers statistics of a given variation diff.
41+
* This method is side-effect free and will not alter the given diff.
42+
* @param d A variation diff to extract statistics from.
43+
* @return The extracted statistics.
44+
*/
2145
public static DiffStatistics of(final DiffTree d) {
2246
final int[] nodeCount = {0};
2347
final int[] annotationNodeCount = {0};
@@ -33,6 +57,13 @@ public static DiffStatistics of(final DiffTree d) {
3357
}
3458
}
3559

60+
/**
61+
* Creates the header for a CSV file in which objects of this class
62+
* can be rows.
63+
* @param delimiter The delimiter to use between rows in the CSV file (see {@link CSV#DEFAULT_CSV_DELIMITER}.
64+
* @return A string that should be the first row in a CSV file with objects of this class
65+
* as rows.
66+
*/
3667
public static String makeHeader(String delimiter) {
3768
return intercalate(delimiter,
3869
// "repository",
@@ -65,11 +96,4 @@ public String toCSV(String delimiter) {
6596
viewStatistics.annotationNodeCount
6697
);
6798
}
68-
69-
private String getRelevanceArguments() {
70-
if (relevance instanceof Configure) {
71-
return relevance.parametersToString();
72-
}
73-
return "";
74-
}
7599
}

src/main/java/org/variantsync/diffdetective/util/fide/FixTrueFalse.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
/**
1515
* Class to fix bugs related to {@link True} and {@link False} of FeatureIDE.
16-
* See: https://github.com/FeatureIDE/FeatureIDE/issues/1111
17-
* See: https://github.com/FeatureIDE/FeatureIDE/issues/1333
16+
* See: <a href="https://github.com/FeatureIDE/FeatureIDE/issues/1111">FeatureIDE Issue 1111</a>
17+
* See: <a href="https://github.com/FeatureIDE/FeatureIDE/issues/1333">FeatureIDE Issue 1333</a>
1818
*
1919
* This class contains constants for representing atomic values true and false in formulas
2020
* as well as a conversion method for parsing certain feature names to true and false, respectively.

0 commit comments

Comments
 (0)