diff --git a/README.md b/README.md index 1bc6aa74c..7c40e9e30 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ DiffDetective is an open-source Java library for variability-aware source code differencing and the **analysis of version histories of software product lines**. This means that DiffDetective can **turn a generic differencer into a variability-aware differencer** by means of a pre- or post-processing. DiffDetective is centered around **formally verified** data structures for variability (variation trees) and variability-aware diffs (variation diffs). These data structures are **generic**, and DiffDetective currently implements **C preprocessor support** to parse respective annotations when used to implement variability. The picture below depicts the process of variability-aware differencing. -Variability-Aware Differencing Overview +Variability-Aware Differencing Overview Given two states of a C-preprocessor annotated source code file (left), for example before and after a commit, DiffDetective constructs a variability-aware diff (right) that distinguishes changes to source code from changes to variability annotations. DiffDetective can construct such a variation diff either, by first using a generic differencer, and separating the information (center path), or by first parsing both input versions to an abstract representation, a variation tree (center top and bottom), and constructing a variation diff using a tree differencing algorithm in a second step. @@ -80,6 +80,18 @@ Additionally, there is a screencast available on YouTube, guiding you through th [![DiffDetective Demonstration](docs/yt_thumbnail.png)](https://www.youtube.com/watch?v=q6ight5EDQY) +## Supported Differencing Algorithms + +In principle, any generic differencing algorithm (i.e, any algorithm that may operate on text or trees) can be made variability-aware with DiffDetective, as explained in our demo paper (see below). Some algorithms are integrated directly in the DiffDetective library, while others come as additional Maven projects. + +### Shipped with DiffDetective +- Git Diff as implemented by [JGit](https://github.com/eclipse-jgit/jgit) +- [GumTree](https://github.com/GumTreeDiff/gumtree), and all algorithms and matching engines supported by the GumTree library + +### Extra Modules +- [TrueDiff](https://gitlab.rlp.net/plmz/truediff): Support for TrueDiff comes as [a separate Maven project](https://github.com/VariantSync/TrueDiffDetective). + + ## Publications ### Variability-Aware Differencing with DiffDetective (FSE 2024, ⭐ [Best Demo Paper](https://2024.esec-fse.org/info/awards) ⭐) @@ -167,9 +179,10 @@ Edge-typed variation diffs and the replication package are implemented in a fork DiffDetective was extended and used within bachelor's and master's theses: +- _Unparsing von Datenstrukturen zur Analyse von C-Präprozessor-Variabilität_, Eugen Shulimov, Bachelor's Thesis, 2025, [DOI 10.17619/UNIPB/1-2385](http://doi.org/10.17619/UNIPB/1-2385), (german): Eugen added an unparser for variation trees, essentially inverting the horizontal arrows in our commuting diagram at the top of this README file. The unparser for variation diffs reuses the unparser for variation trees by projecting a variation diff to its two variation trees (before and after the change), unparsing the trees, and then diffing the obtained text files to eventually compute a text-based diff. - _Constructing Variation Diffs Using Tree Diffing Algorithms_, Benjamin Moosherr, Bachelor's Thesis, 2023, [DOI 10.18725/OPARU-50108](https://dx.doi.org/10.18725/OPARU-50108): Benjamin added support for tree-differencing and integrated the GumTree differencer ([Github](https://github.com/GumTreeDiff/gumtree), [Paper](https://doi.org/10.1145/2642937.2642982)). In his thesis, Benjamin also reviewed a range of quality metrics for tree-diffs with focus on their applicability for rating variability-aware diffs. The [org.variantsync.diffdetective.experiments.thesis_bm](src/main/java/org/variantsync/diffdetective/experiments/thesis_bm) package implements the corresponding empirical study and may serve as an example on how to use the tree-differencing. - _Reverse Engineering Feature-Aware Commits From Software Product-Line Repositories_, Lukas Bormann, Bachelor's Thesis, 2023, [10.18725/OPARU-47892](https://dx.doi.org/10.18725/OPARU-47892): Lukas implemented an algorithm for feature-based commit-untangling, which turns variation diff into a series of smaller diffs, each of which contains an edit to a single feature or feature formula. This work was later refined in our publication _Views on Edits to Variational Software_ illustrated above. -- _Inspecting the Evolution of Feature Annotations in Configurable Software_, Lukas Güthing, Master's Thesis, 2023: Lukas implemented different edge-types for associating variability annotations within variation diffs. He published his work later at VaMoS 2024 under the title _Explaining Edits to Variability Annotations in Evolving Software Product Lines_, illustrated above. +- _Inspecting the Evolution of Feature Annotations in Configurable Software_, Lukas Güthing, Master's Thesis, 2023: Lukas implemented different edge-types for associating variability annotations within variation diffs. He published his work later at VaMoS 2024 under the title _Explaining Edits to Variability Annotations in Evolving Software Product Lines_, illustrated above. His work can be found in a [fork][forklg] of DiffDetective. - _Empirical Evaluation of Feature Trace Recording on the Edit History of Marlin_, Sören Viegener, Bachelor's Thesis, 2021, [DOI 10.18725/OPARU-38603](http://dx.doi.org/10.18725/OPARU-38603): In his thesis, Sören started the DiffDetective project and implemented the first version of an algorithm, which parses text-based diffs to C-preprocessor files to variation diffs. He also came up with an initial classification of edits, which we wanted to reuse to evaluate [Feature Trace Recording](https://variantsync.github.io/FeatureTraceRecording/), a method for deriving variability annotations from annotated patches. [documentation]: https://variantsync.github.io/DiffDetective/docs/javadoc diff --git a/default.nix b/default.nix index 9503cc2f2..17640a7d1 100644 --- a/default.nix +++ b/default.nix @@ -26,7 +26,7 @@ }, doCheck ? true, buildGitHubPages ? true, - dependenciesHash ? "sha256-OdagSk6jYCkkw/kPoOJlma9yEK7hMBcNkuxE6qt0ra8=", + dependenciesHash ? "sha256-xQG7IjBROSXfMIe7kvU8fXfKShdqKwVaJR0y97jsZWU=", }: pkgs.stdenvNoCC.mkDerivation rec { pname = "DiffDetective"; diff --git a/docs/datasets/eugen-bachelor-thesis.md b/docs/datasets/eugen-bachelor-thesis.md new file mode 100644 index 000000000..52f415472 --- /dev/null +++ b/docs/datasets/eugen-bachelor-thesis.md @@ -0,0 +1,5 @@ +Project name | Domain | Source code available (\*\*y\*\*es/\*\*n\*\*o)? | Is it a git repository (\*\*y\*\*es/\*\*n\*\*o)? | Repository URL | Clone URL | Estimated number of commits +-------------------|-------------------------|-------------------------------------------------|--------------------------------------------------|--------------------------------------------------------------|----------------------------------------------------|--------------------------------- +berkeley-db-libdb | database system | y | y | https://github.com/berkeleydb/libdb | https://github.com/berkeleydb/libdb.git | 7 +sylpheed | e-mail client | y | y | https://github.com/jan0sch/sylpheed | https://github.com/jan0sch/sylpheed.git | 2,682 +vim | text editor | y | y | https://github.com/vim/vim | https://github.com/vim/vim.git | 17,109 diff --git a/docs/teaser.png b/docs/teaser.png deleted file mode 100644 index 24c43deb2..000000000 Binary files a/docs/teaser.png and /dev/null differ diff --git a/pom.xml b/pom.xml index a598614bd..50c0f52b1 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.variantsync diffdetective - 2.3.0 + 2.4.0 UTF-8 @@ -163,7 +163,7 @@ org.apache.commons commons-lang3 - 3.17.0 + 3.18.0 diff --git a/replication/thesis-es/Dockerfile b/replication/thesis-es/Dockerfile new file mode 100644 index 000000000..4520b8042 --- /dev/null +++ b/replication/thesis-es/Dockerfile @@ -0,0 +1,57 @@ +# syntax=docker/dockerfile:1 + +FROM alpine:3.15 +# PACKAGE STAGE + +# Prepare the compile environment. JDK is automatically installed +RUN apk add maven + +# Create and navigate to a working directory +WORKDIR /home/user + +COPY local-maven-repo ./local-maven-repo + +# Copy the source code +COPY src ./src +# Copy the pom.xml if Maven is used +COPY pom.xml . +# Execute the maven package process +RUN mvn package || exit + +FROM alpine:3.15 + +# Create a user +RUN adduser --disabled-password --home /home/sherlock --gecos '' sherlock + +RUN apk add --no-cache --upgrade bash +RUN apk add --update openjdk17 + +# Change into the home directory +WORKDIR /home/sherlock + +# Copy the compiled JAR file from the first stage into the second stage +# Syntax: COPY --from=STAGE_ID SOURCE_PATH TARGET_PATH +WORKDIR /home/sherlock/holmes +COPY --from=0 /home/user/target/diffdetective-*-jar-with-dependencies.jar ./DiffDetective.jar +WORKDIR /home/sherlock +RUN mkdir results + +# Copy the setup +COPY docs holmes/docs + +# Copy the docker resources +COPY docker/* ./ +COPY replication/thesis-es/docker/* ./ +RUN mkdir DiffDetectiveMining + +# Adjust permissions +RUN chown sherlock:sherlock /home/sherlock -R +RUN chmod +x execute.sh +RUN chmod +x entrypoint.sh +RUN chmod +x fix-perms.sh + +# Set the entrypoint +ENTRYPOINT ["./entrypoint.sh", "./execute.sh"] + +# Set the user +USER sherlock diff --git a/replication/thesis-es/README.md b/replication/thesis-es/README.md new file mode 100644 index 000000000..dbac2923f --- /dev/null +++ b/replication/thesis-es/README.md @@ -0,0 +1,49 @@ +![Maven](https://github.com/VariantSync/DiffDetective/actions/workflows/maven.yml/badge.svg) +[![Documentation](https://img.shields.io/badge/Documentation-Read-purple)][documentation] +[![Install](https://img.shields.io/badge/Install-Instructions-blue)](INSTALL.md) +[![GitHubPages](https://img.shields.io/badge/GitHub%20Pages-online-blue.svg?style=flat)][website] +[![License](https://img.shields.io/badge/License-GNU%20LGPLv3-blue)](../../LICENSE.LGPL3) + +# Unparsing Experiment +This is an experiment for the bachelor thesis by Eugen Shulimov which tests the unparser for variation trees and diffs. + +### Prerequisite +All following commands assume that working directory of your terminal is the `thesis-es` directory. Please switch directories, if this is not the case: +```shell +cd DiffDetective/replication/thesis-es +``` + +### Build the Docker container +Start the docker deamon. +Clone this repository. +Open a terminal and navigate to the root directory of this repository. +To build the Docker container you can run the `build` script corresponding to your operating system. +#### Windows: +`.\build.bat` +#### Linux/Mac (bash): +`./build.sh` + +### Start the experiment +To execute the experiment you can run the `execute`script corresponding to your operating system. + +#### Windows: +`.\execute.bat +#### Linux/Mac (bash): +`./execute.sh + +> If you want to stop the execution, you can call the provided script for stopping the container in a separate terminal. +> When restarted, the execution will continue processing by restarting at the last unfinished repository. +> #### Windows: +> `.\stop-execution.bat` +> #### Linux/Mac (bash): +> `./stop-execution.sh` + +You might see warnings or errors reported from SLF4J like `Failed to load class "org.slf4j.impl.StaticLoggerBinder"` which you can safely ignore. + +### View the results in the [results][resultsdir] directory +All raw results are stored in the [results][resultsdir] directory. + +[documentation]: https://variantsync.github.io/DiffDetective/docs/javadoc/ +[website]: https://variantsync.github.io/DiffDetective/ + +[resultsdir]: results diff --git a/replication/thesis-es/build.bat b/replication/thesis-es/build.bat new file mode 100644 index 000000000..73bc8d9ab --- /dev/null +++ b/replication/thesis-es/build.bat @@ -0,0 +1,19 @@ +@echo off +setlocal + +set "targetSubPath=thesis-es" + +rem Get the current directory +for %%A in ("%CD%") do set "currentDir=%%~nxA" + +rem Check if the current directory ends with the target sub-path + +if "%currentDir:~-9%"=="%targetSubPath%" ( + cd ..\.. + docker build -t diff-detective-unparse -f replication\thesis-es\Dockerfile . + @pause +) else ( + echo error: the script must be run from inside the thesis-es directory, i.e., DiffDetective\replication\%targetSubPath% +) +endlocal + diff --git a/replication/thesis-es/build.sh b/replication/thesis-es/build.sh new file mode 100644 index 000000000..19bb7b741 --- /dev/null +++ b/replication/thesis-es/build.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# We have to switch to the root directory of the project and build the Docker image from there, +# because Docker only allows access to the files in the current file system subtree (i.e., no access to ancestors). +# We have to do this to get access to 'src', 'docker', 'local-maven-repo', etc. +# For resiliency against different working directories during execution of this +# script we calculate the correct path using the special bash variable +# BASH_SOURCE. +cd "$(dirname "${BASH_SOURCE[0]}")/../.." || exit + +docker build -t diff-detective-unparse -f replication/thesis-es/Dockerfile . diff --git a/replication/thesis-es/docker/DOCKER.md b/replication/thesis-es/docker/DOCKER.md new file mode 100644 index 000000000..966ebc0d5 --- /dev/null +++ b/replication/thesis-es/docker/DOCKER.md @@ -0,0 +1,6 @@ +# Docker Files + +This directory contains the files that are required to run the Docker container. + +## Execution +The [`execute.sh`](execute.sh) script can be adjusted to run the program that should be executed by the Docker container. \ No newline at end of file diff --git a/replication/thesis-es/docker/execute.sh b/replication/thesis-es/docker/execute.sh new file mode 100644 index 000000000..a4e2ce4dc --- /dev/null +++ b/replication/thesis-es/docker/execute.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +cd /home/sherlock/holmes || exit + +echo "Running the experiment." +java -cp DiffDetective.jar org.variantsync.diffdetective.experiments.thesis-es.Main + +echo "Collecting results." +cp -r results/* ../results/ +echo "The results are located in the 'results' directory." + diff --git a/replication/thesis-es/execute.bat b/replication/thesis-es/execute.bat new file mode 100644 index 000000000..2467d7379 --- /dev/null +++ b/replication/thesis-es/execute.bat @@ -0,0 +1,15 @@ +@echo off +setlocal + +set "targetSubPath=thesis-es" + +rem Get the current directory +for %%A in ("%CD%") do set "currentDir=%%~nxA" + +rem Check if the current directory ends with the target sub-path +if "%currentDir:~-9%"=="%targetSubPath%" ( +docker run --rm -v "%cd%\results":"/home/sherlock/results" diff-detective-unparse %* +) else ( + echo error: the script must be run from inside the thesis-es directory, i.e., DiffDetective\replication\%targetSubPath% +) +endlocal diff --git a/replication/thesis-es/execute.sh b/replication/thesis-es/execute.sh new file mode 100644 index 000000000..c0b2fba9b --- /dev/null +++ b/replication/thesis-es/execute.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Assure that the script is only called from the folder cotaining this script +cd "$(dirname "${BASH_SOURCE[0]}")" || exit + +if [[ $# -gt 0 ]]; then +echo "Executing $1" +fi +docker run --rm -v "$(pwd)/results":"/home/sherlock/results" diff-detective-unparse "$@" diff --git a/replication/thesis-es/results/.gitignore b/replication/thesis-es/results/.gitignore new file mode 100644 index 000000000..86d0cb272 --- /dev/null +++ b/replication/thesis-es/results/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/replication/thesis-es/stop-execution.bat b/replication/thesis-es/stop-execution.bat new file mode 100644 index 000000000..009494d8f --- /dev/null +++ b/replication/thesis-es/stop-execution.bat @@ -0,0 +1,3 @@ +@echo "Stopping all running simulations. This will take a moment..." +@FOR /f "tokens=*" %%i IN ('docker ps -a -q --filter "ancestor=diff-detective-unparse"') DO docker stop %%i +@echo "...done." \ No newline at end of file diff --git a/replication/thesis-es/stop-execution.sh b/replication/thesis-es/stop-execution.sh new file mode 100644 index 000000000..0ebe6a83a --- /dev/null +++ b/replication/thesis-es/stop-execution.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +echo "Stopping Docker container. This will take a moment..." +docker stop "$(docker ps -a -q --filter "ancestor=diff-detective-unparse")" +echo "...done." diff --git a/src/main/java/org/variantsync/diffdetective/analysis/PreprocessingAnalysis.java b/src/main/java/org/variantsync/diffdetective/analysis/PreprocessingAnalysis.java index 1ea16ece0..75c967adb 100644 --- a/src/main/java/org/variantsync/diffdetective/analysis/PreprocessingAnalysis.java +++ b/src/main/java/org/variantsync/diffdetective/analysis/PreprocessingAnalysis.java @@ -3,24 +3,25 @@ import java.util.Arrays; import java.util.List; -import org.variantsync.diffdetective.variation.diff.transform.VariationDiffTransformer; +import org.variantsync.diffdetective.variation.diff.VariationDiff; +import org.variantsync.diffdetective.variation.diff.transform.Transformer; import org.variantsync.diffdetective.variation.DiffLinesLabel; public class PreprocessingAnalysis implements Analysis.Hooks { - private final List> preprocessors; + private final List>> preprocessors; - public PreprocessingAnalysis(List> preprocessors) { + public PreprocessingAnalysis(List>> preprocessors) { this.preprocessors = preprocessors; } @SafeVarargs - public PreprocessingAnalysis(VariationDiffTransformer... preprocessors) { + public PreprocessingAnalysis(Transformer>... preprocessors) { this.preprocessors = Arrays.asList(preprocessors); } @Override public boolean analyzeVariationDiff(Analysis analysis) { - VariationDiffTransformer.apply(preprocessors, analysis.getCurrentVariationDiff()); + Transformer.apply(preprocessors, analysis.getCurrentVariationDiff()); analysis.getCurrentVariationDiff().assertConsistency(); return true; } diff --git a/src/main/java/org/variantsync/diffdetective/diff/git/GitDiffer.java b/src/main/java/org/variantsync/diffdetective/diff/git/GitDiffer.java index a79f8936a..d1b2523fe 100644 --- a/src/main/java/org/variantsync/diffdetective/diff/git/GitDiffer.java +++ b/src/main/java/org/variantsync/diffdetective/diff/git/GitDiffer.java @@ -21,9 +21,11 @@ import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser; +import org.variantsync.diffdetective.variation.tree.source.GitSource; import java.io.*; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -111,14 +113,12 @@ public static CommitDiffResult createCommitDiff( final CanonicalTreeParser currentTreeParser = new CanonicalTreeParser(); final CanonicalTreeParser prevTreeParser = new CanonicalTreeParser(); try (ObjectReader reader = repository.getGitRepo().getRepository().newObjectReader()) { - try { - currentTreeParser.reset(reader, childCommit.getTree()); - if (parentCommit != null) { - prevTreeParser.reset(reader, parentCommit.getTree()); - } - } catch (IOException e) { - return CommitDiffResult.Failure(DiffError.JGIT_ERROR, e.toString()); + currentTreeParser.reset(reader, childCommit.getTree()); + if (parentCommit != null) { + prevTreeParser.reset(reader, parentCommit.getTree()); } + } catch (IOException e) { + return CommitDiffResult.Failure(DiffError.JGIT_ERROR, e.toString()); } final AbstractTreeIterator parentTreeIterator; @@ -254,6 +254,7 @@ private static CommitDiffResult getPatchDiffs( final VariationDiff variationDiff = VariationDiffParser.createVariationDiff( fullDiff, + new GitSource(repository, childCommit.getId().name(), Path.of(filename)), repository.getParseOptions().variationDiffParseOptions() ); diff --git a/src/main/java/org/variantsync/diffdetective/diff/git/GitPatch.java b/src/main/java/org/variantsync/diffdetective/diff/git/GitPatch.java index 6bdef202e..e0ca5d9b8 100644 --- a/src/main/java/org/variantsync/diffdetective/diff/git/GitPatch.java +++ b/src/main/java/org/variantsync/diffdetective/diff/git/GitPatch.java @@ -1,17 +1,19 @@ package org.variantsync.diffdetective.diff.git; +import java.util.List; + import org.eclipse.jgit.diff.DiffEntry; import org.variantsync.diffdetective.diff.text.TextBasedDiff; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.diff.Time; import org.variantsync.diffdetective.variation.diff.VariationDiff; // For Javadoc -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; /** * Interface for patches from a git repository. * A git patch is a {@link TextBasedDiff} from which {@link VariationDiff}s can be created. * */ -public interface GitPatch extends VariationDiffSource, TextBasedDiff { +public interface GitPatch extends Source, TextBasedDiff { /** * Minimal default implementation of {@link GitPatch} * @param getDiff The diff in text form. @@ -41,6 +43,16 @@ public GitPatch shallowClone() { public String toString() { return oldFileName + "@ " + getParentCommitHash + " (parent) to " + newFileName + " @ " + getCommitHash + " (child)"; } + + @Override + public String getSourceExplanation() { + return "SimpleGitPatch"; + } + + @Override + public List getSourceArguments() { + return List.of(getChangeType(), oldFileName(), newFileName(), getCommitHash(), getParentCommitHash()); + } } /** diff --git a/src/main/java/org/variantsync/diffdetective/diff/git/PatchDiff.java b/src/main/java/org/variantsync/diffdetective/diff/git/PatchDiff.java index f6e03b0c7..d4232509e 100644 --- a/src/main/java/org/variantsync/diffdetective/diff/git/PatchDiff.java +++ b/src/main/java/org/variantsync/diffdetective/diff/git/PatchDiff.java @@ -123,4 +123,9 @@ public String toString() { public GitPatch shallowClone() { return new GitPatch.SimpleGitPatch(getDiff(), getChangeType(), getFileName(Time.BEFORE), getFileName(Time.AFTER), getCommitHash(), getParentCommitHash()); } + + @Override + public String getSourceExplanation() { + return "PatchDiff"; + } } diff --git a/src/main/java/org/variantsync/diffdetective/examplesearch/ExampleFinder.java b/src/main/java/org/variantsync/diffdetective/examplesearch/ExampleFinder.java index ebe8d1a11..38782644b 100644 --- a/src/main/java/org/variantsync/diffdetective/examplesearch/ExampleFinder.java +++ b/src/main/java/org/variantsync/diffdetective/examplesearch/ExampleFinder.java @@ -11,6 +11,7 @@ import org.variantsync.diffdetective.show.Show; import org.variantsync.diffdetective.util.Assert; import org.variantsync.diffdetective.util.IO; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.util.StringUtils; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.diff.Time; @@ -24,7 +25,6 @@ import org.variantsync.diffdetective.variation.diff.serialize.edgeformat.DefaultEdgeLabelFormat; import org.variantsync.diffdetective.variation.diff.serialize.nodeformat.MappingsDiffNodeFormat; import org.variantsync.diffdetective.variation.diff.serialize.treeformat.CommitDiffVariationDiffLabelFormat; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; import java.io.IOException; import java.nio.file.Path; @@ -106,14 +106,10 @@ private boolean checkIfExample(Analysis analysis, String localDiff) { // We do not want a variationDiff for the entire file but only for the local change to have a small example. final VariationDiff localTree; try { - localTree = VariationDiff.fromDiff(localDiff, new VariationDiffParseOptions(annotationParser, true, true)); + localTree = VariationDiff.fromDiff(localDiff, Source.findFirst(variationDiff, GitPatch.class), new VariationDiffParseOptions(annotationParser, true, true)); // Not every local diff can be parsed to a VariationDiff because diffs are unaware of the underlying language (i.e., CPP). // We want only running examples whose diffs describe entire diff trees for easier understanding. - if (isGoodExample.test(localTree)) { - Assert.assertTrue(variationDiff.getSource() instanceof GitPatch); - final GitPatch variationDiffSource = (GitPatch) variationDiff.getSource(); - localTree.setSource(variationDiffSource.shallowClone()); - } else { + if (!isGoodExample.test(localTree)) { return false; } } catch (DiffParseException e) { @@ -149,9 +145,9 @@ public boolean analyzeVariationDiff(Analysis analysis) { } private void exportExample(final Analysis analysis, final String tdiff, final VariationDiff vdiff, Path outputDir) { - Assert.assertTrue(vdiff.getSource() instanceof GitPatch); final Repository repo = analysis.getRepository(); - final GitPatch patch = (GitPatch) vdiff.getSource(); + final GitPatch patch = Source.findFirst(vdiff, GitPatch.class); + Assert.assertNotNull(patch); outputDir = outputDir.resolve(Path.of(repo.getRepositoryName() + "_" + patch.getCommitHash())); final String filename = patch.getFileName(Time.AFTER); @@ -185,8 +181,8 @@ private void exportExample(final Analysis analysis, final String tdiff, final Va } static String getDiff(final VariationDiff tree) { - final VariationDiffSource source = tree.getSource(); - Assert.assertTrue(source instanceof TextBasedDiff); - return ((TextBasedDiff) source).getDiff(); + TextBasedDiff textBasedDiff = Source.findFirst(tree, TextBasedDiff.class); + Assert.assertNotNull(textBasedDiff); + return textBasedDiff.getDiff(); } } diff --git a/src/main/java/org/variantsync/diffdetective/experiments/thesis_bm/ConstructionValidation.java b/src/main/java/org/variantsync/diffdetective/experiments/thesis_bm/ConstructionValidation.java index 75c04e6a3..b90bae61d 100644 --- a/src/main/java/org/variantsync/diffdetective/experiments/thesis_bm/ConstructionValidation.java +++ b/src/main/java/org/variantsync/diffdetective/experiments/thesis_bm/ConstructionValidation.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; +import java.nio.file.Path; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -42,6 +43,7 @@ import org.variantsync.diffdetective.variation.diff.Time; import org.variantsync.diffdetective.variation.diff.filter.VariationDiffFilter; import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser; +import org.variantsync.diffdetective.variation.tree.source.GitSource; import org.variantsync.functjonal.category.InplaceSemigroup; import org.variantsync.functjonal.map.MergeMap; @@ -375,6 +377,7 @@ private void counts(VariationDiff tree, VariationDiffStatistics } private VariationDiff parseVariationTree(Analysis analysis, RevCommit commit) throws IOException, DiffParseException { + String fileName = analysis.getCurrentPatch().getFileName(AFTER); try (BufferedReader afterFile = new BufferedReader( /* @@ -386,10 +389,14 @@ private VariationDiff parseVariationTree(Analysis analysis, RevC GitDiffer.getBeforeFullFile( analysis.getRepository(), commit, - analysis.getCurrentPatch().getFileName(AFTER)), + fileName), 0xfeff)) // BOM, same as GitDiffer.BOM_PATTERN ) { - return VariationDiffParser.createVariationTree(afterFile, analysis.getRepository().getParseOptions().variationDiffParseOptions()); + return VariationDiffParser.createVariationTree( + afterFile, + new GitSource(analysis.getRepository(), commit.getId().name(), Path.of(fileName)), + analysis.getRepository().getParseOptions().variationDiffParseOptions() + ); } } diff --git a/src/main/java/org/variantsync/diffdetective/experiments/thesis_es/Main.java b/src/main/java/org/variantsync/diffdetective/experiments/thesis_es/Main.java new file mode 100644 index 000000000..089b21885 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/experiments/thesis_es/Main.java @@ -0,0 +1,185 @@ +package org.variantsync.diffdetective.experiments.thesis_es; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.stream.Stream; +import org.variantsync.diffdetective.AnalysisRunner; +import org.variantsync.diffdetective.analysis.Analysis; +import org.variantsync.diffdetective.datasets.DatasetDescription; +import org.variantsync.diffdetective.datasets.DefaultDatasets; +import org.variantsync.diffdetective.datasets.PatchDiffParseOptions; +import org.variantsync.diffdetective.datasets.PatchDiffParseOptions.DiffStoragePolicy; +import org.variantsync.diffdetective.datasets.Repository; +import org.variantsync.diffdetective.diff.git.DiffFilter; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; + +public class Main { + + public static void main(String[] args) throws IOException { + startAnalysis(); + evaluationAnalysis(Path.of("docs", "datasets", "eugen-bachelor-thesis.md")); + + } + + private static void startAnalysis() throws IOException { + final AnalysisRunner.Options analysisOptions = new AnalysisRunner.Options( + Paths.get("..", "DiffDetectiveReplicationDatasets"), + Paths.get("results", "thesis_es"), + Paths.get("docs", "datasets", "eugen-bachelor-thesis.md"), + repo -> new PatchDiffParseOptions( + DiffStoragePolicy.REMEMBER_FULL_DIFF, + VariationDiffParseOptions.Default), + repo -> new DiffFilter.Builder().allowMerge(true) + .allowedFileExtensions("c", "cpp").build(), + true, + false); + + AnalysisRunner.run(analysisOptions, extractionRunner()); + } + + protected static BiConsumer extractionRunner() { + return (repo, repoOutputDir) -> { + + final BiFunction AnalysisFactory = (r, out) -> new Analysis("Thesis Eugen Shulimov", + List.of(new UnparseAnalysis()), r, out); + + Analysis.forEachCommit(() -> AnalysisFactory.apply(repo, repoOutputDir)); + + }; + } + + /** + * Verarbeitet die Ergebnisse der Analyse um aus einzelnen + * Angaben eine gesamt Übersicht zu bekommen + * + * @param path Pfad zu der markdown datei, aus der die repositories für die + * Analyse stammen + * @throws IOException + */ + private static void evaluationAnalysis(Path path) throws IOException { + int count = 0; + int[] diffTest = { 0, 0, 0, 0, 0, 0, 0, 0 }; + int[] diffSemEqTest = { 0, 0, 0, 0, }; + int[] treeTest = { 0, 0, 0, 0, 0, 0, 0, 0 }; + final List datasets = DefaultDatasets.loadDatasets(path); + + for (DatasetDescription description : datasets) { + Stream files = Files + .list(Path.of("results", "thesis_es", description.name())) + .filter(filename -> filename.getFileName().toString().endsWith(".thesis_es.csv")); + for (Path tempPath : files.toList()) { + String[] splitFileData = Files.readString(tempPath).split("\n"); + for (int j = 1; j < splitFileData.length; j++) { + String[] splitLineData = splitFileData[j].split(";"); + for (int i = 0; i < splitLineData.length; i++) { + splitLineData[i] = parseNumberStringToIntWithLengthGreaterOne(splitLineData[i]); + } + count = count + 1; + diffTest[0] = diffTest[0] + Integer.parseInt(splitLineData[8]); + diffTest[1] = diffTest[1] + Integer.parseInt(splitLineData[9]); + diffTest[2] = diffTest[2] + Integer.parseInt(splitLineData[10]); + diffTest[3] = diffTest[3] + Integer.parseInt(splitLineData[11]); + diffTest[4] = diffTest[4] + Integer.parseInt(splitLineData[12]); + diffTest[5] = diffTest[5] + Integer.parseInt(splitLineData[13]); + diffTest[6] = diffTest[6] + Integer.parseInt(splitLineData[14]); + diffTest[7] = diffTest[7] + Integer.parseInt(splitLineData[15]); + diffSemEqTest[0] = diffSemEqTest[0] + Integer.parseInt(splitLineData[16]); + diffSemEqTest[1] = diffSemEqTest[1] + Integer.parseInt(splitLineData[17]); + diffSemEqTest[2] = diffSemEqTest[2] + Integer.parseInt(splitLineData[18]); + diffSemEqTest[3] = diffSemEqTest[3] + Integer.parseInt(splitLineData[19]); + treeTest[0] = treeTest[0] + Integer.parseInt(splitLineData[20]); + treeTest[1] = treeTest[1] + Integer.parseInt(splitLineData[21]); + treeTest[2] = treeTest[2] + Integer.parseInt(splitLineData[22]); + treeTest[3] = treeTest[3] + Integer.parseInt(splitLineData[23]); + treeTest[4] = treeTest[4] + Integer.parseInt(splitLineData[24]); + treeTest[5] = treeTest[5] + Integer.parseInt(splitLineData[25]); + treeTest[6] = treeTest[6] + Integer.parseInt(splitLineData[26]); + treeTest[7] = treeTest[7] + Integer.parseInt(splitLineData[27]); + treeTest[0] = treeTest[0] + Integer.parseInt(splitLineData[28]); + treeTest[1] = treeTest[1] + Integer.parseInt(splitLineData[29]); + treeTest[2] = treeTest[2] + Integer.parseInt(splitLineData[30]); + treeTest[3] = treeTest[3] + Integer.parseInt(splitLineData[31]); + treeTest[4] = treeTest[4] + Integer.parseInt(splitLineData[32]); + treeTest[5] = treeTest[5] + Integer.parseInt(splitLineData[33]); + treeTest[6] = treeTest[6] + Integer.parseInt(splitLineData[34]); + treeTest[7] = treeTest[7] + Integer.parseInt(splitLineData[35]); + + } + } + } + List result = new ArrayList<>(); + result.add("Anzahl geprüfter Diffs : " + count + "\n"); + result.add("Anzahl syntaktisch korrekter Diffs mit MultiLine0 und EmptyLine0 : " + diffTest[0] + "\n"); + result.add("Anzahl syntaktisch korrekter Diffs ohne Whitespace mit MultiLine0 und EmptyLine0 : " + diffTest[4] + + "\n"); + result.add("Anzahl semantisch korrekter Diffs mit MultiLine0 und EmptyLine0 : " + diffSemEqTest[0] + "\n"); + result.add("Anzahl von Diffs mit MultiLine0 und EmptyLine0, welche keine Korrektheitskriterium erfühlt haben : " + + (count - diffSemEqTest[0]) + "\n"); + + result.add("Anzahl syntaktisch korrekter Diffs mit MultiLine1 und EmptyLine0 : " + diffTest[1] + "\n"); + result.add("Anzahl syntaktisch korrekter Diffs ohne Whitespace mit MultiLine1 und EmptyLine0 : " + diffTest[5] + + "\n"); + result.add("Anzahl semantisch korrekter Diffs mit MultiLine1 und EmptyLine0 : " + diffSemEqTest[1] + "\n"); + result.add("Anzahl von Diffs mit MultiLine1 und EmptyLine0, welche keine Korrektheitskriterium erfühlt haben : " + + (count - diffSemEqTest[1]) + "\n"); + + result.add("Anzahl syntaktisch korrekter Diffs mit MultiLine0 und EmptyLine1 : " + diffTest[2] + "\n"); + result.add("Anzahl syntaktisch korrekter Diffs ohne Whitespace mit MultiLine0 und EmptyLine1 : " + diffTest[6] + + "\n"); + result.add("Anzahl semantisch korrekter Diffs mit MultiLine0 und EmptyLine1 : " + diffSemEqTest[2] + "\n"); + result.add("Anzahl von Diffs mit MultiLine0 und EmptyLine1, welche keine Korrektheitskriterium erfühlt haben : " + + (count - diffSemEqTest[2]) + "\n"); + + result.add("Anzahl syntaktisch korrekter Diffs mit MultiLine1 und EmptyLine1 : " + diffTest[3] + "\n"); + result.add("Anzahl syntaktisch korrekter Diffs ohne Whitespace mit MultiLine1 und EmptyLine1 : " + diffTest[7] + + "\n"); + result.add("Anzahl semantisch korrekter Diffs mit MultiLine1 und EmptyLine1 : " + diffSemEqTest[3] + "\n"); + result.add("Anzahl von Diffs mit MultiLine1 und EmptyLine1, welche keine Korrektheitskriterium erfühlt haben : " + + (count - diffSemEqTest[3]) + "\n"); + + result.add("-------------------------------------------------------------------------------------------"); + result.add("Anzahl geprüfter Trees : " + count * 2 + "\n"); + result.add("Anzahl syntaktisch korrekter Trees mit MultiLine0 und EmptyLine0 : " + treeTest[0] + "\n"); + result.add("Anzahl syntaktisch korrekter Trees ohne Whitespace mit MultiLine0 und EmptyLine0 : " + treeTest[4] + + "\n"); + result.add("Anzahl von Trees mit MultiLine0 und EmptyLine0, welche keine Korrektheitskriterium erfühlt haben : " + + (2 * count - treeTest[4]) + "\n"); + + result.add("Anzahl syntaktisch korrekter Trees mit MultiLine1 und EmptyLine0 : " + treeTest[1] + "\n"); + result.add("Anzahl syntaktisch korrekter Trees ohne Whitespace mit MultiLine1 und EmptyLine0 : " + treeTest[5] + + "\n"); + result.add("Anzahl von Trees mit MultiLine1 und EmptyLine0, welche keine Korrektheitskriterium erfühlt haben : " + + (2 * count - treeTest[5]) + "\n"); + + result.add("Anzahl syntaktisch korrekter Trees mit MultiLine0 und EmptyLine1 : " + treeTest[2] + "\n"); + result.add("Anzahl syntaktisch korrekter Trees ohne Whitespace mit MultiLine0 und EmptyLine1 : " + treeTest[6] + + "\n"); + result.add("Anzahl von Trees mit MultiLine0 und EmptyLine1, welche keine Korrektheitskriterium erfühlt haben : " + + (2 * count - treeTest[6]) + "\n"); + + result.add("Anzahl syntaktisch korrekter Trees mit MultiLine1 und EmptyLine1 : " + treeTest[3] + "\n"); + result.add("Anzahl syntaktisch korrekter Trees ohne Whitespace mit MultiLine1 und EmptyLine1 : " + treeTest[7] + + "\n"); + result.add("Anzahl von Trees mit MultiLine1 und EmptyLine1, welche keine Korrektheitskriterium erfühlt haben : " + + (2 * count - treeTest[7]) + "\n"); + + Files.write(Path.of("results", "thesis_es", "resultOfAnalysis.txt"), result); + + } + + private static String parseNumberStringToIntWithLengthGreaterOne(String string) { + string = string.trim(); + for (char c : string.toCharArray()) { + if (Character.isDigit(c)) { + return Character.toString(c); + } + } + return ""; + } +} diff --git a/src/main/java/org/variantsync/diffdetective/experiments/thesis_es/UnparseAnalysis.java b/src/main/java/org/variantsync/diffdetective/experiments/thesis_es/UnparseAnalysis.java new file mode 100644 index 000000000..278dc0d20 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/experiments/thesis_es/UnparseAnalysis.java @@ -0,0 +1,324 @@ +package org.variantsync.diffdetective.experiments.thesis_es; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm; +import org.variantsync.diffdetective.analysis.Analysis; +import org.variantsync.diffdetective.diff.git.PatchDiff; +import org.variantsync.diffdetective.util.CSV; +import org.variantsync.diffdetective.util.FileUtils; +import org.variantsync.diffdetective.util.IO; +import org.variantsync.diffdetective.util.Source; +import org.variantsync.diffdetective.util.StringUtils; +import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.VariationUnparser; +import org.variantsync.diffdetective.variation.diff.Time; +import org.variantsync.diffdetective.variation.diff.VariationDiff; +import org.variantsync.diffdetective.variation.diff.construction.JGitDiff; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; +import org.variantsync.diffdetective.variation.tree.VariationTree; + +public class UnparseAnalysis implements Analysis.Hooks { + + public static final String CSV_EXTENSION = ".thesis_es.csv"; + + public static int count = 0; + + private StringBuilder csv; + + // for debugging + private int errorCount = 0; + + @Override + public void initializeResults(Analysis analysis) { + Analysis.Hooks.super.initializeResults(analysis); + + csv = new StringBuilder(); + csv.append(UnparseEvaluation.makeHeader(CSV.DEFAULT_CSV_DELIMITER)).append(StringUtils.LINEBREAK); + + errorCount = 0; + } + + @Override + public boolean analyzeVariationDiff(Analysis analysis) throws Exception { + PatchDiff patch = analysis.getCurrentPatch(); + String textDiff = patch.getDiff(); + try { + BufferedReader in = new BufferedReader(new StringReader(textDiff)); + String line = ""; + StringBuilder tempString = new StringBuilder(); + while ((line = in.readLine()) != null) { + tempString.append(line); + tempString.append("\n"); + } + textDiff = tempString.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + + String codeBefore = VariationUnparser.undiff(patch.getDiff(), Time.BEFORE); + String codeAfter = VariationUnparser.undiff(patch.getDiff(), Time.AFTER); + + boolean[][] diffTestAll = runTestsDiff(textDiff); + boolean[] treeBeforeTest = runTestsTree(codeBefore); + boolean[] treeAfterTest = runTestsTree(codeAfter); + boolean[] dataTests = runDataTest(textDiff, codeBefore, codeAfter); + int error = 1; + // Test das es überhaupt funktioniert + if (!(boolOr(diffTestAll[0]) || boolOr(diffTestAll[1]))) { + error = error * 2; + reportErrorToFile(analysis, "textDiff: \n" + textDiff); + } + if (!boolOr(treeBeforeTest)) { + error = error * 3; + reportErrorToFile(analysis, "treeBefore: \n" + codeBefore); + } + if (!boolOr(treeAfterTest)) { + error = error * 5; + reportErrorToFile(analysis, "treeAfter: \n" + codeAfter); + } + // Testen der implikationen + // für Diff + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine false und IgnoreEmptyLine false + if (diffTestAll[0][0] && !diffTestAll[0][4]) { + reportErrorToFile(analysis, "diffTestAll[0][0] && !diffTestAll[0][4] " + textDiff); + } + // syntaktische Gleicheheit ohne Whitespace folgt semantische Gleichheit + // für CollapseMultyLine false und IgnoreEmptyLine false + if (diffTestAll[0][4] && !diffTestAll[1][0]) { + reportErrorToFile(analysis, "diffTestAll[0][4] && !diffTestAll[1][0] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine true und IgnoreEmptyLine false + if (diffTestAll[0][1] && !diffTestAll[0][5]) { + reportErrorToFile(analysis, "diffTestAll[0][1] && !diffTestAll[0][5] " + textDiff); + } + // syntaktische Gleicheheit ohne Whitespace folgt semantische Gleichheit + // für CollapseMultyLine true und IgnoreEmptyLine false + if (diffTestAll[0][5] && !diffTestAll[1][1]) { + reportErrorToFile(analysis, "diffTestAll[0][5] && !diffTestAll[1][1] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine false und IgnoreEmptyLine true + if (diffTestAll[0][2] && !diffTestAll[0][6]) { + reportErrorToFile(analysis, "diffTestAll[0][2] && !diffTestAll[0][6] " + textDiff); + } + // syntaktische Gleicheheit ohne Whitespace folgt semantische Gleichheit + // für CollapseMultyLine false und IgnoreEmptyLine true + if (diffTestAll[0][6] && !diffTestAll[1][2]) { + reportErrorToFile(analysis, "diffTestAll[0][6] && !diffTestAll[1][2] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine true und IgnoreEmptyLine true + if (diffTestAll[0][3] && !diffTestAll[0][7]) { + reportErrorToFile(analysis, "diffTestAll[0][3] && !diffTestAll[0][7] " + textDiff); + } + // syntaktische Gleicheheit ohne Whitespace folgt semantische Gleichheit + // für CollapseMultyLine true und IgnoreEmptyLine true + if (diffTestAll[0][7] && !diffTestAll[1][3]) { + reportErrorToFile(analysis, "diffTestAll[0][7] && !diffTestAll[1][3] " + textDiff); + } + // für Trees + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine false und IgnoreEmptyLine false + if (treeBeforeTest[0] && !treeBeforeTest[4]) { + reportErrorToFile(analysis, "treeBeforeTest[0] && !treeBeforeTest[4] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine true und IgnoreEmptyLine false + if (treeBeforeTest[1] && !treeBeforeTest[5]) { + reportErrorToFile(analysis, "treeBeforeTest[1] && !treeBeforeTest[5] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine false und IgnoreEmptyLine true + if (treeBeforeTest[2] && !treeBeforeTest[6]) { + reportErrorToFile(analysis, "treeBeforeTest[2] && !treeBeforeTest[6] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine true und IgnoreEmptyLine true + if (treeBeforeTest[3] && !treeBeforeTest[7]) { + reportErrorToFile(analysis, "treeBeforeTest[3] && !treeBeforeTest[7] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine false und IgnoreEmptyLine false + if (treeAfterTest[0] && !treeAfterTest[4]) { + reportErrorToFile(analysis, "treeAfterTest[0] && !treeAfterTest[4] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine true und IgnoreEmptyLine false + if (treeAfterTest[1] && !treeAfterTest[5]) { + reportErrorToFile(analysis, "treeAfterTest[1] && !treeAfterTest[5] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine false und IgnoreEmptyLine true + if (treeAfterTest[2] && !treeAfterTest[6]) { + reportErrorToFile(analysis, "treeAfterTest[2] && !treeAfterTest[6] " + textDiff); + } + // syntaktische Gleicheheit folgt syntaktische ohne Whitespace Gleichheit + // für CollapseMultyLine true und IgnoreEmptyLine true + if (treeAfterTest[3] && !treeAfterTest[7]) { + reportErrorToFile(analysis, "treeAfterTest[3] && !treeAfterTest[7] " + textDiff); + } + + // Speichere ergebniss + final UnparseEvaluation ue = new UnparseEvaluation( + boolToInt(dataTests), + boolToInt(diffTestAll[0]), + boolToInt(diffTestAll[1]), + boolToInt(treeBeforeTest), + boolToInt(treeAfterTest)); + csv.append(ue.toCSV()).append(StringUtils.LINEBREAK); + return Analysis.Hooks.super.analyzeVariationDiff(analysis); + } + + @Override + public void endBatch(Analysis analysis) throws IOException { + IO.write( + FileUtils.addExtension(analysis.getOutputFile(), CSV_EXTENSION), + csv.toString()); + } + + private void reportErrorToFile(Analysis analysis, String errorMessage) throws IOException { + IO.write( + FileUtils.addExtension(analysis.getOutputFile().resolve("error" + errorCount), ".txt"), + errorMessage); + ++errorCount; + } + + public static String removeWhitespace(String string, boolean diff) { + if (string.isEmpty()) { + return ""; + } else { + StringBuilder result = new StringBuilder(); + try { + BufferedReader in = new BufferedReader(new StringReader(string)); + String line = ""; + while ((line = in.readLine()) != null) { + if (!line.replaceAll("\\s+", "").isEmpty()) { + String temp = line.trim(); + if (diff && !(temp.charAt(0) == '+' || temp.charAt(0) == '-')) { + temp = " " + temp; + } + result.append(temp); + result.append("\n"); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return result.toString(); + } + } + + public static String parseUnparseTree(String text, VariationDiffParseOptions option) { + String temp = "b"; + try { + VariationTree tree = VariationTree.fromText(text, Source.Unknown, option); + temp = VariationUnparser.unparseTree(tree); + } catch (Exception e) { + e.printStackTrace(); + } + return temp; + } + + public static String parseUnparseDiff(String textDiff, VariationDiffParseOptions option) { + String temp = "b"; + try { + VariationDiff diff = VariationDiff.fromDiff(textDiff, Source.Unknown, option); + temp = VariationUnparser.unparseDiff(diff); + } catch (Exception e) { + e.printStackTrace(); + } + return temp; + } + + public static VariationDiffParseOptions optionsSetter(int i) { + if (i == 0) { + return new VariationDiffParseOptions(false, false); + } else if (i == 1) { + return new VariationDiffParseOptions(true, false); + } else if (i == 2) { + return new VariationDiffParseOptions(false, true); + } else { + return new VariationDiffParseOptions(true, true); + } + } + + public static boolean equalsText(String text1, String text2, boolean whitespace, boolean diff) { + if (whitespace) { + return text1.equals(text2); + } else { + return removeWhitespace(text1, diff).equals(removeWhitespace(text2, diff)); + } + } + + public static boolean[][] runTestsDiff(String text) { + boolean[][] array = new boolean[2][8]; + for (int i = 0; i < 4; i++) { + String diff = parseUnparseDiff(text, optionsSetter(i)); + array[0][i] = equalsText(text, diff, true, true); + array[0][i + 4] = equalsText(text, diff, false, true); + array[1][i] = (equalsText(VariationUnparser.undiff(text, Time.BEFORE), + VariationUnparser.undiff(diff, Time.BEFORE), true, true) + && equalsText(VariationUnparser.undiff(text, Time.AFTER), + VariationUnparser.undiff(diff, Time.AFTER), true, true)) + || (equalsText(VariationUnparser.undiff(text, Time.BEFORE), + VariationUnparser.undiff(diff, Time.BEFORE), false, true) + && equalsText(VariationUnparser.undiff(text, Time.AFTER), + VariationUnparser.undiff(diff, Time.AFTER), false, true)); + array[1][i + 4] = false; + } + return array; + } + + public static boolean[] runTestsTree(String text) { + boolean[] array = new boolean[8]; + for (int i = 0; i < 4; i++) { + String temp = parseUnparseTree(text, optionsSetter(i)); + array[i] = equalsText(text, temp, true, false); + array[i + 4] = equalsText(text, temp, false, false); + } + return array; + } + + public static boolean[] runDataTest(String textDiff, String treeBefore, String treeAfter) throws IOException { + boolean[] array = new boolean[8]; + array[0] = JGitDiff.textDiff(treeBefore, treeAfter, SupportedAlgorithm.MYERS).equals(textDiff); + array[1] = removeWhitespace(JGitDiff.textDiff(treeBefore, treeAfter, SupportedAlgorithm.MYERS), true) + .equals(removeWhitespace(textDiff, true)); + array[2] = JGitDiff.textDiff(treeBefore, treeAfter, SupportedAlgorithm.HISTOGRAM).equals(textDiff); + array[3] = removeWhitespace(JGitDiff.textDiff(treeBefore, treeAfter, SupportedAlgorithm.HISTOGRAM), true) + .equals(removeWhitespace(textDiff, true)); + array[4] = treeBefore.equals(VariationUnparser.undiff(textDiff, Time.BEFORE)); + array[5] = removeWhitespace(treeBefore, false) + .equals(removeWhitespace(VariationUnparser.undiff(textDiff, Time.BEFORE), false)); + array[6] = treeAfter.equals(VariationUnparser.undiff(textDiff, Time.AFTER)); + array[7] = removeWhitespace(treeAfter, false) + .equals(removeWhitespace(VariationUnparser.undiff(textDiff, Time.AFTER), false)); + return array; + } + + public static int[] boolToInt(boolean[] array) { + int[] temp = new int[array.length]; + for (int i = 0; i < array.length; i++) { + if (array[i]) { + temp[i] = 1; + } else { + temp[i] = 0; + } + } + return temp; + } + + public static boolean boolOr(boolean[] array) { + for (boolean temp : array) { + if (temp) { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/org/variantsync/diffdetective/experiments/thesis_es/UnparseEvaluation.java b/src/main/java/org/variantsync/diffdetective/experiments/thesis_es/UnparseEvaluation.java new file mode 100644 index 000000000..ba0ff3ba5 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/experiments/thesis_es/UnparseEvaluation.java @@ -0,0 +1,95 @@ +package org.variantsync.diffdetective.experiments.thesis_es; + +import static org.variantsync.functjonal.Functjonal.intercalate; + +import org.variantsync.diffdetective.util.CSV; + +public record UnparseEvaluation( + int[] dataTest, + int[] diffTest, + int[] diffSemEqTest, + int[] treeBeforeTest, + int[] treeAfterTest) implements CSV { + + @Override + public String toCSV(String delimiter) { + return intercalate(delimiter, + dataTest[0], + dataTest[1], + dataTest[2], + dataTest[3], + dataTest[4], + dataTest[5], + dataTest[6], + dataTest[7], + diffTest[0], + diffTest[1], + diffTest[2], + diffTest[3], + diffTest[4], + diffTest[5], + diffTest[6], + diffTest[7], + diffSemEqTest[0], + diffSemEqTest[1], + diffSemEqTest[2], + diffSemEqTest[3], + treeBeforeTest[0], + treeBeforeTest[1], + treeBeforeTest[2], + treeBeforeTest[3], + treeBeforeTest[4], + treeBeforeTest[5], + treeBeforeTest[6], + treeBeforeTest[7], + treeAfterTest[0], + treeAfterTest[1], + treeAfterTest[2], + treeAfterTest[3], + treeAfterTest[4], + treeAfterTest[5], + treeAfterTest[6], + treeAfterTest[7]); + } + + public static String makeHeader(String delimiter) { + return intercalate(delimiter, + "diffFromTreesEqTextDiffMye", + "diffFromTreesEqTextDiffMyeWhite", + "diffFromTreesEqTextDiffHis", + "diffFromTreesEqTextDiffHisWhite", + "treeBefEqTreeBefDiff", + "treeBefEqTreeBefDiffWhite", + "treeAftEqTreeAftDiff", + "treeAftEqTreeAftDiffWhite", + "diffEqTestMultiL0EmptyL0", + "diffEqTestMultiL1EmptyL0", + "diffEqTestMultiL0EmptyL1", + "diffEqTestMultiL1EmptyL1", + "diffEqTestMultiL0EmptyL0White", + "diffEqTestMultiL1EmptyL0White", + "diffEqTestMultiL0EmptyL1White", + "diffEqTestMultiL1EmptyL1White", + "diffSemEqTestMultiL0EmptyL0", + "diffSemEqTestMultiL1EmptyL0", + "diffSemEqTestMultiL0EmptyL1", + "diffSemEqTestMultiL1EmptyL1", + "treeBeforeEqTestMultiL0EmptyL0", + "treeBeforeEqTestMultiL1EmptyL0", + "treeBeforeEqTestMultiL0EmptyL1", + "treeBeforeEqTestMultiL1EmptyL1", + "treeBeforeEqTestMultiL0EmptyL0White", + "treeBeforeEqTestMultiL1EmptyL0White", + "treeBeforeEqTestMultiL0EmptyL1White", + "treeBeforeEqTestMultiL1EmptyL1White", + "treeAfterEqTestMultiL0EmptyL0", + "treeAfterEqTestMultiL1EmptyL0", + "treeAfterEqTestMultiL0EmptyL1", + "treeAfterEqTestMultiL1EmptyL1", + "treeAfterEqTestMultiL0EmptyL0White", + "treeAfterEqTestMultiL1EmptyL0White", + "treeAfterEqTestMultiL0EmptyL1White", + "treeAfterEqTestMultiL1EmptyL1White"); + } + +} diff --git a/src/main/java/org/variantsync/diffdetective/experiments/views/result/ViewEvaluation.java b/src/main/java/org/variantsync/diffdetective/experiments/views/result/ViewEvaluation.java index 8211574bb..e1916925d 100644 --- a/src/main/java/org/variantsync/diffdetective/experiments/views/result/ViewEvaluation.java +++ b/src/main/java/org/variantsync/diffdetective/experiments/views/result/ViewEvaluation.java @@ -85,8 +85,8 @@ public String toCSV(String delimiter) { // repo.getRepositoryName(), commit, file, - relevance.getFunctionName(), -// getQueryArguments(), + relevance.getSourceExplanation(), +// relevance.getSourceArguments(), msNaive, msOptimized, diffStatistics.nodeCount, diff --git a/src/main/java/org/variantsync/diffdetective/gumtree/VariationDiffAdapter.java b/src/main/java/org/variantsync/diffdetective/gumtree/VariationDiffAdapter.java index b05d8b6aa..d0fbb8728 100644 --- a/src/main/java/org/variantsync/diffdetective/gumtree/VariationDiffAdapter.java +++ b/src/main/java/org/variantsync/diffdetective/gumtree/VariationDiffAdapter.java @@ -22,6 +22,7 @@ public VariationDiffAdapter(Projection node) { super(node); } + @Override protected VariationTreeAdapter newInstance(VariationNode node) { return new VariationDiffAdapter<>(Cast.unchecked(node)); } diff --git a/src/main/java/org/variantsync/diffdetective/gumtree/VariationTreeAdapter.java b/src/main/java/org/variantsync/diffdetective/gumtree/VariationTreeAdapter.java index cf85482da..a37a5dce6 100644 --- a/src/main/java/org/variantsync/diffdetective/gumtree/VariationTreeAdapter.java +++ b/src/main/java/org/variantsync/diffdetective/gumtree/VariationTreeAdapter.java @@ -2,8 +2,10 @@ import java.util.ArrayList; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map.Entry; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.variantsync.diffdetective.variation.Label; import org.variantsync.diffdetective.variation.tree.VariationNode; @@ -24,15 +26,17 @@ public class VariationTreeAdapter extends AbstractTree { private String cachedLabel; private VariationNode backingNode; + private LinkedHashMap metadata; public VariationTreeAdapter(VariationNode node) { this.backingNode = node; + this.metadata = new LinkedHashMap<>(); - if (backingNode.isConditionalAnnotation()) { - cachedLabel = backingNode.getFormula().toString(); - } else { - cachedLabel = backingNode.getLabel().getLines().stream().collect(Collectors.joining("\n")); - } + cachedLabel = + Stream.concat( + backingNode.getLabel().getLines().stream(), + backingNode.getLabel().getTrailingLines().stream() + ).collect(Collectors.joining("\n")); var children = new ArrayList(node.getChildren().size()); for (var child : node.getChildren()) { @@ -41,7 +45,7 @@ public VariationTreeAdapter(VariationNode node) { setChildren(children); } - protected VariationTreeAdapter newInstance(VariationNode node) { + protected VariationTreeAdapter newInstance(VariationNode node) { return new VariationTreeAdapter<>(node); } @@ -65,12 +69,12 @@ public int getLength() { @Override public Iterator> getMetadata() { - throw new UnsupportedOperationException(); + return metadata.entrySet().iterator(); } @Override - public Object getMetadata(String arg0) { - throw new UnsupportedOperationException(); + public Object getMetadata(String key) { + return metadata.get(key); } /** @@ -97,8 +101,8 @@ public void setLength(int length) { } @Override - public Object setMetadata(String name, Object value) { - throw new UnsupportedOperationException(); + public Object setMetadata(String key, Object value) { + return metadata.put(key, value); } @Override diff --git a/src/main/java/org/variantsync/diffdetective/internal/SimpleRenderer.java b/src/main/java/org/variantsync/diffdetective/internal/SimpleRenderer.java index 7737afedb..2ef7fce47 100644 --- a/src/main/java/org/variantsync/diffdetective/internal/SimpleRenderer.java +++ b/src/main/java/org/variantsync/diffdetective/internal/SimpleRenderer.java @@ -18,7 +18,7 @@ import org.variantsync.diffdetective.variation.diff.render.RenderOptions; import org.variantsync.diffdetective.variation.diff.render.VariationDiffRenderer; import org.variantsync.diffdetective.variation.diff.serialize.nodeformat.MappingsDiffNodeFormat; -import org.variantsync.diffdetective.variation.diff.transform.VariationDiffTransformer; +import org.variantsync.diffdetective.variation.diff.transform.Transformer; import java.io.IOException; import java.nio.file.Files; @@ -162,10 +162,10 @@ public static void main(String[] args) throws IOException { final Repository repository = Repository.fromDirectory(repoPath, repoName); repository.setParseOptions(repository.getParseOptions().withDiffStoragePolicy(PatchDiffParseOptions.DiffStoragePolicy.REMEMBER_STRIPPED_DIFF)); - final List> transform = VariationDiffMiner.Postprocessing(repository); + final List>> transform = VariationDiffMiner.Postprocessing(repository); final PatchDiff patch = VariationDiffParser.parsePatch(repository, file, commit); Assert.assertNotNull(patch != null); - VariationDiffTransformer.apply(transform, patch.getVariationDiff()); + Transformer.apply(transform, patch.getVariationDiff()); renderer.render(patch, Path.of("render", repoName), RENDER_OPTIONS_TO_USE); } diff --git a/src/main/java/org/variantsync/diffdetective/load/GitLoader.java b/src/main/java/org/variantsync/diffdetective/load/GitLoader.java index 5af465f8d..16a98f6b6 100644 --- a/src/main/java/org/variantsync/diffdetective/load/GitLoader.java +++ b/src/main/java/org/variantsync/diffdetective/load/GitLoader.java @@ -1,7 +1,6 @@ package org.variantsync.diffdetective.load; import net.lingala.zip4j.ZipFile; -import net.lingala.zip4j.exception.ZipException; import org.apache.commons.io.FilenameUtils; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; @@ -86,10 +85,9 @@ public static Git fromZip(Path pathToZip) { return fromDirectory(unzippedRepoName); } - try { - ZipFile zipFile = new ZipFile(pathToZip.toFile()); + try (ZipFile zipFile = new ZipFile(pathToZip.toFile())) { zipFile.extractAll(targetDir.toString()); - } catch (ZipException e) { + } catch (IOException e) { Logger.warn("Failed to extract git repo from {} to {}", pathToZip, targetDir); return null; } diff --git a/src/main/java/org/variantsync/diffdetective/mining/RWCompositePatternTreeFormat.java b/src/main/java/org/variantsync/diffdetective/mining/RWCompositePatternTreeFormat.java index 0305528d3..e0a2d551c 100644 --- a/src/main/java/org/variantsync/diffdetective/mining/RWCompositePatternTreeFormat.java +++ b/src/main/java/org/variantsync/diffdetective/mining/RWCompositePatternTreeFormat.java @@ -1,22 +1,25 @@ package org.variantsync.diffdetective.mining; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; +import java.util.List; + +import org.variantsync.diffdetective.util.FileSource; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.diff.serialize.treeformat.VariationDiffLabelFormat; -import org.variantsync.diffdetective.variation.diff.source.PatchFile; public class RWCompositePatternTreeFormat implements VariationDiffLabelFormat { @Override - public VariationDiffSource fromLabel(String label) { + public Source fromLabel(String label) { throw new UnsupportedOperationException("Cannot read"); } @Override - public String toLabel(VariationDiffSource variationDiffSource) { - if (variationDiffSource instanceof PatchFile p) { - final String fileName = p.path().getFileName().toString(); - return fileName.substring(0, fileName.indexOf('.')).replaceAll("_", " "); + public String toLabel(Source variationDiffSource) { + List pathSources = Source.findAll(variationDiffSource, FileSource.class); + if (pathSources.size() != 1) { + throw new IllegalArgumentException("Expected a single path source but got:\n" + Source.fullExplanation(variationDiffSource)); } - throw new IllegalArgumentException("Expected a PatchFile but got " + variationDiffSource); + final String fileName = pathSources.get(0).getPath().getFileName().toString(); + return fileName.substring(0, fileName.indexOf('.')).replaceAll("_", " "); } } diff --git a/src/main/java/org/variantsync/diffdetective/mining/VariationDiffMiner.java b/src/main/java/org/variantsync/diffdetective/mining/VariationDiffMiner.java index 48401bea3..e2ec661be 100644 --- a/src/main/java/org/variantsync/diffdetective/mining/VariationDiffMiner.java +++ b/src/main/java/org/variantsync/diffdetective/mining/VariationDiffMiner.java @@ -13,6 +13,7 @@ import org.variantsync.diffdetective.mining.formats.MiningNodeFormat; import org.variantsync.diffdetective.mining.formats.ReleaseMiningDiffNodeFormat; import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.filter.VariationDiffFilter; import org.variantsync.diffdetective.variation.diff.serialize.GraphFormat; import org.variantsync.diffdetective.variation.diff.serialize.LineGraphExportOptions; @@ -20,7 +21,7 @@ import org.variantsync.diffdetective.variation.diff.serialize.treeformat.CommitDiffVariationDiffLabelFormat; import org.variantsync.diffdetective.variation.diff.transform.CollapseNestedNonEditedAnnotations; import org.variantsync.diffdetective.variation.diff.transform.CutNonEditedSubtrees; -import org.variantsync.diffdetective.variation.diff.transform.VariationDiffTransformer; +import org.variantsync.diffdetective.variation.diff.transform.Transformer; import java.io.IOException; import java.nio.file.Path; @@ -38,8 +39,8 @@ public class VariationDiffMiner { // public static final int PRINT_LARGEST_SUBJECTS = 3; public static final boolean DEBUG_TEST = false; - public static List> Postprocessing(final Repository repository) { - final List> processing = new ArrayList<>(); + public static List>> Postprocessing(final Repository repository) { + final List>> processing = new ArrayList<>(); processing.add(new CutNonEditedSubtrees<>()); processing.add(new CollapseNestedNonEditedAnnotations()); return processing; diff --git a/src/main/java/org/variantsync/diffdetective/mining/postprocessing/Postprocessor.java b/src/main/java/org/variantsync/diffdetective/mining/postprocessing/Postprocessor.java index 8b11d209b..e03ba9a5b 100644 --- a/src/main/java/org/variantsync/diffdetective/mining/postprocessing/Postprocessor.java +++ b/src/main/java/org/variantsync/diffdetective/mining/postprocessing/Postprocessor.java @@ -7,7 +7,7 @@ import org.variantsync.diffdetective.variation.diff.filter.ExplainedFilter; import org.variantsync.diffdetective.variation.diff.filter.TaggedPredicate; import org.variantsync.diffdetective.variation.diff.transform.CutNonEditedSubtrees; -import org.variantsync.diffdetective.variation.diff.transform.VariationDiffTransformer; +import org.variantsync.diffdetective.variation.diff.transform.Transformer; import java.util.List; import java.util.Map; @@ -17,7 +17,7 @@ * Patterns are represented as VariationDiffs and might be filtered or transformed. */ public class Postprocessor { - private final List> transformers; + private final List>> transformers; private final ExplainedFilter> filters; /** @@ -30,7 +30,7 @@ public class Postprocessor { public record Result(List> processedTrees, Map filterCounts) {} private Postprocessor( - final List> transformers, + final List>> transformers, final List>> namedFilters) { this.transformers = transformers; this.filters = new ExplainedFilter>(namedFilters.stream()); @@ -66,7 +66,7 @@ public static Postprocessor Default() { public Result postprocess(final List> frequentSubgraphs) { final List> processedTrees = frequentSubgraphs.stream() .filter(filters) - .peek(tree -> VariationDiffTransformer.apply(transformers, tree)) + .peek(tree -> Transformer.apply(transformers, tree)) .toList(); final Map filterCounts = new ExplainedFilterSummary(filters).snapshot(); diff --git a/src/main/java/org/variantsync/diffdetective/show/Show.java b/src/main/java/org/variantsync/diffdetective/show/Show.java index f6383de47..9077fe338 100644 --- a/src/main/java/org/variantsync/diffdetective/show/Show.java +++ b/src/main/java/org/variantsync/diffdetective/show/Show.java @@ -30,7 +30,7 @@ public static GameEngine diff(final VariationDiff d, final String title) { } public static GameEngine diff(final VariationDiff d) { - return diff(d, d.getSource().toString()); + return diff(d, d.getSource().functionExplanation()); } public static GameEngine tree(final VariationTree t, final String title, List> availableFormats) { @@ -47,7 +47,7 @@ public static GameEngine tree(final VariationTree t, final String title) { } public static GameEngine tree(final VariationTree t) { - return tree(t, t.source().toString()); + return tree(t, t.getSource().functionExplanation()); } public static GameEngine baddiff(final BadVDiff badVDiff, final String title, List> availableFormats) { @@ -80,6 +80,6 @@ public static GameEngine baddiff(final BadVDiff badVDiff, final String title) } public static GameEngine baddiff(final BadVDiff badVDiff) { - return baddiff(badVDiff, badVDiff.diff().source().toString()); + return baddiff(badVDiff, badVDiff.functionExplanation()); } } diff --git a/src/main/java/org/variantsync/diffdetective/show/variation/VariationDiffApp.java b/src/main/java/org/variantsync/diffdetective/show/variation/VariationDiffApp.java index 219e6bda8..3e5e5eb4f 100644 --- a/src/main/java/org/variantsync/diffdetective/show/variation/VariationDiffApp.java +++ b/src/main/java/org/variantsync/diffdetective/show/variation/VariationDiffApp.java @@ -48,7 +48,8 @@ public final static List> DEFAULT_FORMA new LabelOnlyDiffNodeFormat<>(), new EditClassesDiffNodeFormat<>(), new LineNumberFormat<>(), - new FormulasAndLineNumbersNodeFormat<>() + new FormulasAndLineNumbersNodeFormat<>(), + new IndexFormat<>() ); } diff --git a/src/main/java/org/variantsync/diffdetective/util/Assert.java b/src/main/java/org/variantsync/diffdetective/util/Assert.java index bf74c7c93..504d111a0 100644 --- a/src/main/java/org/variantsync/diffdetective/util/Assert.java +++ b/src/main/java/org/variantsync/diffdetective/util/Assert.java @@ -86,7 +86,7 @@ public static void assertFalse(boolean condition, String errorMessage) { } /** Throws {@link AssertionError} with {@code errorMessage} as error message. */ - public static void fail(String errorMessage) { + public static T fail(String errorMessage) { throw new AssertionError(errorMessage); } @@ -105,12 +105,18 @@ public static void assertNull(Object o) { } public static void assertEquals(T expected, T actual) { + assertEquals(expected, actual, null); + } + + public static void assertEquals(T expected, T actual, String message) { + String prefix = message == null ? "" : message + ": "; + if (expected == null) { if (actual != null) { - fail("expected is null but actual is not!"); + fail(prefix + "expected is null but actually it is " + actual); } } else { - assertTrue(expected.equals(actual), expected + " != " + actual); + assertTrue(expected.equals(actual), prefix + expected + " != " + actual); } } } diff --git a/src/main/java/org/variantsync/diffdetective/util/CompositeSource.java b/src/main/java/org/variantsync/diffdetective/util/CompositeSource.java new file mode 100644 index 000000000..aa4e6e3da --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/util/CompositeSource.java @@ -0,0 +1,36 @@ +package org.variantsync.diffdetective.util; + +import java.util.Arrays; +import java.util.List; + +/** + * Represents a {@link Source} without arguments. + */ +public class CompositeSource implements Source { + private final String sourceExplanation; + private final List sources; + + /** + * @param sourceExplanation is returned verbatim by {@link getSourceExplanation} + * @param sources is returned as immutable list by {@link getSources} + */ + public CompositeSource(String sourceExplanation, Source... sources) { + this.sourceExplanation = sourceExplanation; + this.sources = Arrays.asList(sources); + } + + @Override + public String getSourceExplanation() { + return sourceExplanation; + } + + @Override + public List getSources() { + return sources; + } + + @Override + public String toString() { + return Source.shallowExplanation(this); + } +} diff --git a/src/main/java/org/variantsync/diffdetective/util/FileSource.java b/src/main/java/org/variantsync/diffdetective/util/FileSource.java new file mode 100644 index 000000000..84458a0de --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/util/FileSource.java @@ -0,0 +1,19 @@ +package org.variantsync.diffdetective.util; + +import java.nio.file.Path; +import java.util.List; + +/** + * Represents a file input in a {@link Source} hierarchy. + */ +public record FileSource(Path getPath) implements Source { + @Override + public String getSourceExplanation() { + return "File"; + } + + @Override + public List getSourceArguments() { + return List.of(getPath()); + } +} diff --git a/src/main/java/org/variantsync/diffdetective/util/Source.java b/src/main/java/org/variantsync/diffdetective/util/Source.java new file mode 100644 index 000000000..ffc77f308 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/util/Source.java @@ -0,0 +1,297 @@ +package org.variantsync.diffdetective.util; + +import java.nio.file.Path; // For Javadoc +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.variantsync.diffdetective.diff.git.PatchDiff; // For Javadoc +import org.variantsync.diffdetective.variation.diff.ProjectionSource; +import org.variantsync.diffdetective.variation.diff.VariationDiff; // For Javadoc +import org.variantsync.functjonal.Cast; + +/** + * An interface for source traceability. + * For testing and debugging, it can be really useful to know where some value originated from. For + * example, imagine an error during you analysis of a {@link VariationDiff}. Now you want to know + * where the variation diff came from. The solution: DiffDetectice tracks the source and + * transformations of important data structures like {@link VariationDiff#getSource()} and allows + * you to inspect them using this interface. + *

+ * {@link Source} represents a hierarchy of inputs, processing steps, and results (the distinction + * between these types is not directly reflected in the API and only serve as explanation of the + * interface). + *

    + *
  • An input (e.g., {@link FileSource}) is a {@link Source} that has no {@link getSources + * children}. Inputs are the leafs of the {@link Source} hierarchy and contain the {@link + * getSourceExplanation name of the input} (e.g., {@code "file"} or {@code "URL"}) and {@link + * getSourceArguments some arguments} (e.g., the file name or URL). + *
  • A step (e.g., {@link ProjectionSource}) processed {@link getSources one or more sources}, has + * a {@link getSourceExplanation name} and may be configurable by some {@link getSourceArguments + * arguments}. Unconfigurable processing steps (or steps whose configurability should not be + * tracked) are most commonly represented by {@link CompositeSource}. Note that a step might also + * include (interim) results and might thus be considered a result too. + *
  • A result (e.g., {@link VariationDiff}) contains some data and the {@link getSources source of + * that data}. The contained data is not directly accessible by {@link Source this interface} but + * can be obtained by looking up the subclass representing that result with {@link findFirst} or + * {@link findAll}. Results are not necessary to trace the source of some data (and it might thus be + * omitted from the {@link Source} hierarchy) but can help to identify a buggy processing step. + *
+ *

+ * In summary, each {@link Source} in the {@link getSources hierarchy} has a {@link + * getSourceExplanation short explanation} and a number of {@link getSourceArguments arguments}. A + * source may contain additional data (e.g., the diff a variation diff originated from) that is too + * big to be printed by the standard formatting functions ({@link shallowExplanation}, {@link + * shortExplanation}, {@link fullExplanation}) of this interface. To access such data, or the + * arguments of specific subclasses, you can use {@link findFirst} and {@link findAll}. + *

+ * For dealing with generic sources, it is recommended to use the static methods of this interface. + * They provide a more readable interface (e.g., {@code variationDiff.shallowExplanation()} vs. + * {@code Source.shallowExplanation(variationDiff)}) and correctly deal with {@code null} sources + * (treated as {@link Unknown}). + * + * @see CompositeSource + * @see FileSource + */ +public interface Source { + /** + * Returns a short, one line explanation or identifier of this source. + * The result is used by {@link shallowExplanation} and is formatted together with {@link + * getSourceArguments} like {@code "sourceExplanation(argument1, argument2)"}. + */ + String getSourceExplanation(); + + /** + * Returns a list of arguments required to understand this source. + * Each argument in the result list should represent a {@link Object#toString string} without + * newlines and will be formatted together with {@link getSourceExplanation} like {@code + * "sourceExplanation(argument1, argument2)"} by {@link shallowExplanation}. This method is only + * intended to access the arguments for {@link Object#toString printing}. In case access to the + * well-typed object is required, use {@link findFirst} or {@link findAll} and use the accessors + * of the underlying type. + *

+ * For ease of implementing {@code Source}, the return value is a list of {@link Object}s + * instead of a list of {@link String}s to allow code like {@code List.of(arg0, arg1, arg2)} + * instead of {@code List.of(arg0.toString(), arg1.toString(), arg2.toString())}. Users of this + * function should assume nothing from the returned objects except that {@link Object#toString} + * is well behaved. + * + * @return an empty list by default + * @see shallowExplanation + */ + default List getSourceArguments() { + return Collections.emptyList(); + } + + /** + * Returns a list of sources that influenced this source. + * Noteworthy processing steps and incorporation of multiple sources are implemented as a tree + * of sources. This functions returns the children of this source. + *

+ * By default, the first child source is treated specially in {@link getRootSource}. + * + * @return an empty list by default + */ + default List getSources() { + return Collections.emptyList(); + } + + /** + * An explanation of this source disregarding all {@link getSources child sources}. + * The resulting string should not contain any newlines. + * + * @return {@code "sourceExplanation(argument1, argument2, ...)"} by default + * @see getSourceExplanation + * @see getSourceArguments + */ + default String shallowExplanation() { + return getSourceArguments() + .stream() + .map(Object::toString) + .collect(Collectors.joining(", ", getSourceExplanation() + "(", ")")); + } + + /** + * Calls {@link shallowExplanation} on {@code source} but handles {@code null} like {@link + * Unknown}. + */ + static String shallowExplanation(Source source) { + return (source == null ? Unknown : source).shallowExplanation(); + } + + /** + * Returns one representative {@link Source} that identifies the initial data. + * A good root source should help humans to understand at what data they are looking at. Good + * examples is a filename or a commit and repository combination. Note that sometimes this is an + * arbitrary decision (e.g., the state before or after a diff) and might depend on the problem + * that is currently worked on. Hence, there is might not be one correct result in all + * circumstances. + * + * @return the {@link getSources first child} or {@code this} if there are no {@link getSources children} + */ + default Source getRootSource() { + for (var source : getSources()) { + if (source != null) { + return source.getRootSource(); + } + } + + return this; + } + + /** + * Returns a {@link shallowExplanation} of {@link getRootSource the root source} of {@code source}. + */ + static String rootExplanation(Source source) { + return (source == null ? Unknown : source.getRootSource()) + .shallowExplanation(); + } + + /** + * Returns a short one line explanation of {@code source} by pairing {@link shortExplanation} + * with {@link rootExplanation}. + */ + static String shortExplanation(Source source) { + if (source == null) { + return Unknown.shallowExplanation(); + } + + Source root = source.getRootSource(); + if (root == source) { + return source.shallowExplanation(); + } else { + return source.shallowExplanation() + " of " + root.shallowExplanation(); + } + } + + /** + * Explains {@code this} source hierarchy in detail. + * The {@code result} will contain at least one line per {@link Source} in the {@link getSources + * hierarchy} (by default in the {@link shallowExplanation} format). The state of {@code result} + * must be in a new line before and after a call to this method. + * + * @param level the current indentation level (two spaces per level) that needs to be added + * before each line + * @param result the string containing the result of this method + */ + default void fullExplanation(int level, StringBuilder result) { + for (int i = 0; i < level; ++i) { + result.append(" "); + } + result.append(shallowExplanation(this)); + result.append("\n"); + + for (var child : getSources()) { + if (child == null) { + Unknown.fullExplanation(level + 1, result); + } else { + child.fullExplanation(level + 1, result); + } + } + } + + /** + * Calls {@link fullExplanation(int, StringBuilder)} on {@code source} but handles {@code null} + * like {@link Unknown} and returns the resulting string. + */ + static String fullExplanation(Source source) { + if (source == null) { + return fullExplanation(Unknown); + } + + var result = new StringBuilder(); + source.fullExplanation(0, result); + return result.toString(); + } + + /** + * The same as {@link #fullExplanation(Source)} but with a different formatting. + * Where fullExplanation renders this tree of sources as using newlines and indentation, + * functionExplanation renders this tree as one large, nested function call of the form: + * {@link #getSourceExplanation()}({@link #getSourceArguments() args}..., {@link #getSources() nested sources}...). + */ + default String functionExplanation() { + String result = getSourceExplanation() + "("; + + final List args = new ArrayList<>(); + for (Object arg : getSourceArguments()) { + args.add(arg.toString()); + } + for (Source child : getSources()) { + args.add(child.functionExplanation()); + } + + result += args.stream().collect(Collectors.joining(", ")); + + return result + ")"; + } + + /** + * Uses a depth first traversal of the {@link Source} {@link getSources hierarchy} to find and + * return all instances of {@code clazz}. + * This method is intended to provide access to the data contained in the source hierarchy. For + * example, {@code Source.findAll(src, File.class)} finds all source files. Note that arguments + * are not inspected. In case an implementation {@link Source} contains a {@link Path file} as + * {@link getSourceArguments argument} it is not included in the result. + * + * @see findFirst + */ + static List findAll(Source source, Class clazz) { + var result = new ArrayList(); + findAll(result, source, clazz); + return result; + } + + /** + * Implementation of {@link findAll(Source, Class)} using an {@code result} accumulator. + */ + private static void findAll(List result, Source source, Class clazz) { + if (source == null) { + return; + } + + if (source.getClass() == clazz) { + result.add(Cast.unchecked(source)); + } + + for (var child : source.getSources()) { + findAll(result, child, clazz); + } + } + + /** + * Uses a depth first traversal of the {@link Source} {@link getSources hierarchy} to find and + * return the first instances of {@code clazz}. + * This method is intended to provide access to the data contained in the source hierarchy. For + * example, {@code Source.findFirst(src, PatchDiff.class)} finds the first {@link PatchDiff}. + * This allows access to data and arguments like {@link PatchDiff#getDiff} but it does not + * traverse the {@link getSourceArguments} directly. + * + * @see findAll + */ + static T findFirst(Source source, Class clazz) { + if (source == null) { + return null; + } + + if (source.getClass() == clazz) { + return Cast.unchecked(source); + } + + for (var child : source.getSources()) { + var result = findFirst(child, clazz); + if (result != null) { + return result; + } + } + + return null; + } + + /** + * A placeholder for an unknown source without any explanation. + * Should be preferred to a {@code null} {@link Source} to make it easily grepable. + */ + public static Source Unknown = new CompositeSource("Unknown"); +} diff --git a/src/main/java/org/variantsync/diffdetective/util/StringUtils.java b/src/main/java/org/variantsync/diffdetective/util/StringUtils.java index 868ab08f8..8f378dd21 100644 --- a/src/main/java/org/variantsync/diffdetective/util/StringUtils.java +++ b/src/main/java/org/variantsync/diffdetective/util/StringUtils.java @@ -48,4 +48,17 @@ public static String prettyPrintNestedCollections(final Collection collection public static String clamp(int maxlen, String s) { return s.substring(0, Math.min(s.length(), maxlen)); } + + /** + * @return the longest prefix of the given string that contains only of whitespace + */ + public static String getLeadingWhitespace(String s) { + if (s == null) return null; + if (s.isEmpty()) return ""; + int i = 0; + while (i < s.length() && Character.isWhitespace(s.charAt(i))) { + ++i; + } + return s.substring(0, i); + } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/DiffLinesLabel.java b/src/main/java/org/variantsync/diffdetective/variation/DiffLinesLabel.java index 1e1d86d3d..c03efa287 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/DiffLinesLabel.java +++ b/src/main/java/org/variantsync/diffdetective/variation/DiffLinesLabel.java @@ -2,11 +2,14 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; import org.variantsync.diffdetective.diff.text.DiffLineNumber; +import org.variantsync.diffdetective.util.Assert; import org.variantsync.diffdetective.util.StringUtils; +import org.variantsync.diffdetective.variation.diff.Time; import org.variantsync.diffdetective.variation.diff.VariationDiff; // For Javadoc /** @@ -18,6 +21,7 @@ */ public class DiffLinesLabel implements Label { private final List lines; + private List trailingLines; public record Line(String content, DiffLineNumber lineNumber) { public static Line withInvalidLineNumber(String content) { @@ -30,7 +34,15 @@ public DiffLinesLabel() { } public DiffLinesLabel(List lines) { + this(lines, new ArrayList<>()); + } + + public DiffLinesLabel(List lines, List trailingLines) { + Assert.assertNotNull(lines); + Assert.assertNotNull(trailingLines); + this.lines = lines; + this.trailingLines = trailingLines; } public static DiffLinesLabel withInvalidLineNumbers(List lines) { @@ -53,11 +65,85 @@ public List getDiffLines() { return lines; } + public void setDiffTrailingLines(List newLines) { + Assert.assertNotNull(newLines); + trailingLines = newLines; + } + + public List getDiffTrailingLines() { + return trailingLines; + } + @Override public List getLines() { return getDiffLines().stream().map(Line::content).toList(); } + @Override + public List getTrailingLines() { + return getDiffTrailingLines().stream().map(Line::content).toList(); + } + + /** + * Returns a deep copy where the line numbers at {@code time} are set to + * {@link DiffLineNumber#InvalidLineNumber}. + */ + @Override + public DiffLinesLabel withoutTimeDependentState(Time time) { + return new DiffLinesLabel( + mapWithoutTimeDependentState(getDiffLines(), time), + mapWithoutTimeDependentState(getDiffTrailingLines(), time) + ); + } + + private List mapWithoutTimeDependentState(List lines, Time time) { + return lines + .stream() + .map(line -> new Line( + line.content(), + line.lineNumber().withLineNumberAtTime(DiffLineNumber.InvalidLineNumber, time) + )) + .toList(); + } + + /** + * Returns a deep copy where the line numbers at {@code time} are copied from + * {@code otherLabel}. The number of lines and their content must be identical in {@code this} + * and {@code otherLabel}. + * + * @see withoutTimeDependentState + */ + @Override + public DiffLinesLabel withTimeDependentStateFrom(Label otherLabel, Time time) { + DiffLinesLabel other = (DiffLinesLabel) otherLabel; + + return new DiffLinesLabel( + zipWithTimeDependentStateFrom(this.getDiffLines(), other.getDiffLines(), time), + zipWithTimeDependentStateFrom(this.getDiffTrailingLines(), other.getDiffTrailingLines(), time) + ); + } + + private static List zipWithTimeDependentStateFrom(List linesA, List linesB, Time time) { + List result = new ArrayList<>(linesA.size()); + + Iterator itA = linesA.iterator(); + Iterator itB = linesA.iterator(); + while (itA.hasNext() && itB.hasNext()) { + Line lineA = itA.next(); + Line lineB = itB.next(); + + Assert.assertEquals(lineA.content(), lineB.content(), "Mismatching line contents in a call to `withTimeDependentStateFrom` detected"); + result.add(new Line( + lineA.content(), + lineB.lineNumber().withLineNumberAtTime(lineB.lineNumber().atTime(time), time) + )); + } + + Assert.assertFalse(itA.hasNext() || itB.hasNext(), "Mismatching line counts in a call to `withTimeDependentStateFrom` detected"); + + return result; + } + @Override public String toString() { return lines @@ -68,6 +154,15 @@ public String toString() { @Override public DiffLinesLabel clone() { - return new DiffLinesLabel(new ArrayList<>(lines)); + return new DiffLinesLabel(new ArrayList<>(lines), new ArrayList<>(trailingLines)); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DiffLinesLabel that = (DiffLinesLabel) o; + return lines.equals(that.lines) && + trailingLines.equals(that.trailingLines); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/Label.java b/src/main/java/org/variantsync/diffdetective/variation/Label.java index 1c83c27f3..d15d83006 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/Label.java +++ b/src/main/java/org/variantsync/diffdetective/variation/Label.java @@ -2,6 +2,8 @@ import java.util.List; +import org.variantsync.diffdetective.util.Assert; +import org.variantsync.diffdetective.variation.diff.Time; import org.variantsync.diffdetective.variation.diff.VariationDiff; // For Javadoc import org.variantsync.diffdetective.variation.tree.VariationTree; // For Javadoc @@ -9,6 +11,55 @@ * Base interface for labels of {@link VariationTree}s and {@link VariationDiff}s. */ public interface Label { + /** + * Returns the lines which need to be printed before the children of a node. + * Most lines associated with a node should be included in this list, for example, {@code #if}s are stored here. + */ List getLines(); + /** + * Returns the lines which need to be printed after the children of a node. + * For example, {@code #endif}s are stored as trailing lines. + */ + List getTrailingLines(); + + /** + * Returns a deep copy where the state that is only valid at {@code time} is set to its default + * value. Note that not all implementations need to have time dependent state. + * + * @see withTimeDependentStateFrom + */ + default Label withoutTimeDependentState(Time time) { + return this.clone(); + } + + /** + * Returns a deep copy where the state that is only valid at {@code time} is copied from + * {@code other}. All time independent state must be equal in {@code this} and {@code other}. + * Note that not all implementations need to have time dependent state. + * + * @see withoutTimeDependentState + */ + default Label withTimeDependentStateFrom(Label other, Time time) { + Assert.assertEquals(this, other); + return this.clone(); + } + + /** + * Creates a deep copy of this label. + */ Label clone(); + + /** + * Tests whether two labels are observably equal. + * Observably equal means that the two labels + * cannot be distinguished by using methods from this interface. + * The given labels might indeed be of different classes or might + * be considered unequal regarding {@link Object#equals(Object)}. + */ + static boolean observablyEqual(Label a, Label b) { + if (a == null) return false; + if (a == b) return true; + return a.getLines().equals(b.getLines()) + && a.getTrailingLines().equals(b.getTrailingLines()); + } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/LinesLabel.java b/src/main/java/org/variantsync/diffdetective/variation/LinesLabel.java index 937d09712..c0b560212 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/LinesLabel.java +++ b/src/main/java/org/variantsync/diffdetective/variation/LinesLabel.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.stream.Collectors; +import org.variantsync.diffdetective.util.Assert; import org.variantsync.diffdetective.util.StringUtils; /** @@ -12,23 +13,38 @@ */ public class LinesLabel implements Label { private final List lines; + private final List trailingLines; public LinesLabel() { - this(new ArrayList<>()); + this(new ArrayList<>(), new ArrayList<>()); } public LinesLabel(List lines) { + this(lines, new ArrayList<>()); + } + + public LinesLabel(List lines, List trailingLines) { + Assert.assertNotNull(lines); + Assert.assertNotNull(trailingLines); + this.lines = lines; + this.trailingLines = trailingLines; } public static LinesLabel ofCodeBlock(String codeBlock) { return new LinesLabel(Arrays.asList(StringUtils.LINEBREAK_REGEX.split(codeBlock, -1))); } + @Override public List getLines() { return lines; } + @Override + public List getTrailingLines() { + return trailingLines; + } + @Override public String toString() { return lines @@ -38,6 +54,15 @@ public String toString() { @Override public LinesLabel clone() { - return new LinesLabel(new ArrayList<>(lines)); + return new LinesLabel(new ArrayList<>(lines), new ArrayList<>(trailingLines)); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LinesLabel that = (LinesLabel) o; + return lines.equals(that.lines) && + trailingLines.equals(that.trailingLines); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/VariationLabel.java b/src/main/java/org/variantsync/diffdetective/variation/VariationLabel.java index 7373a04d2..341bae124 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/VariationLabel.java +++ b/src/main/java/org/variantsync/diffdetective/variation/VariationLabel.java @@ -2,6 +2,7 @@ import java.util.List; +import org.variantsync.diffdetective.util.Assert; import org.variantsync.diffdetective.variation.tree.HasNodeType; import org.variantsync.diffdetective.variation.tree.VariationTree; // For Javadoc import org.variantsync.functjonal.Cast; @@ -23,6 +24,9 @@ public class VariationLabel implements Label, HasNodeType { private L innerLabel; public VariationLabel(NodeType type, L innerLabel) { + Assert.assertNotNull(type); + Assert.assertNotNull(innerLabel); + this.type = type; this.innerLabel = innerLabel; } @@ -40,6 +44,11 @@ public List getLines() { return innerLabel.getLines(); } + @Override + public List getTrailingLines() { + return innerLabel.getTrailingLines(); + } + @Override public NodeType getNodeType() { return type; @@ -49,4 +58,18 @@ public NodeType getNodeType() { public VariationLabel clone() { return new VariationLabel(type, Cast.unchecked(innerLabel.clone())); } + + @Override + public String toString() { + return innerLabel.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + VariationLabel that = (VariationLabel) o; + return type.equals(that.type) && + innerLabel.equals(that.innerLabel); + } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/VariationUnparser.java b/src/main/java/org/variantsync/diffdetective/variation/VariationUnparser.java new file mode 100644 index 000000000..68d42e208 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/variation/VariationUnparser.java @@ -0,0 +1,57 @@ +package org.variantsync.diffdetective.variation; + +import java.io.IOException; +import java.util.stream.Collectors; + +import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm; +import org.variantsync.diffdetective.variation.diff.DiffType; +import org.variantsync.diffdetective.variation.diff.Time; +import org.variantsync.diffdetective.variation.diff.VariationDiff; +import org.variantsync.diffdetective.variation.diff.construction.JGitDiff; +import org.variantsync.diffdetective.variation.tree.VariationTree; + +public class VariationUnparser { + /** + * Unparse {@link VariationTree}s into a {@link String}. + * + * @param tree that is unparsed + * @return the unparsed variation tree + * @param the type of labels of the tree + */ + public static String unparseTree(VariationTree tree) { + return tree.unparse(); + } + + /** + * Unparse {@link VariationDiff}s into a {@link String}. + * + * @param diff that is unparsed + * @return the unparsed variation diff + * @param the type of labels of the tree + * @throws IOException + */ + public static String unparseDiff(VariationDiff diff) throws IOException { + String tree1 = unparseTree(diff.project(Time.BEFORE)); + String tree2 = unparseTree(diff.project(Time.AFTER)); + return JGitDiff.textDiff(tree1, tree2, SupportedAlgorithm.MYERS); + } + + /** + * Extract the state of the diffed text before or after {@code diff}. + * + * @param diff the diff from which the state is extracted + * @param time that the returned state represents + * @return the state before or after the diff + */ + public static String undiff(String diff, Time time) { + char excludedDiffSymbol = DiffType.thatExistsOnlyAt(time.other()).symbol; + + String result = diff + .lines() + .filter(line -> line.isEmpty() || line.charAt(0) != excludedDiffSymbol) + .map(line -> line.isEmpty() ? "" : line.substring(1)) + .collect(Collectors.joining("\n")); + + return result.isEmpty() ? "" : result + "\n"; + } +} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/DiffGraph.java b/src/main/java/org/variantsync/diffdetective/variation/diff/DiffGraph.java index df1d7e6e6..24da64f76 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/DiffGraph.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/DiffGraph.java @@ -1,7 +1,7 @@ package org.variantsync.diffdetective.variation.diff; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.DiffLinesLabel; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; import java.util.Collection; @@ -20,10 +20,10 @@ public final class DiffGraph { private DiffGraph() {} /** - * Invokes {@link DiffGraph#fromNodes(Collection, VariationDiffSource)} )} with an unknown VariationDiffSource. + * Invokes {@link DiffGraph#fromNodes(Collection, Source)} )} with an unknown source. */ public static VariationDiff fromNodes(final Collection> nodes) { - return fromNodes(nodes, VariationDiffSource.Unknown); + return fromNodes(nodes, Source.Unknown); } /** @@ -33,7 +33,7 @@ public static VariationDiff fromNodes(final Collection fromNodes(final Collection> nodes, final VariationDiffSource source) { + public static VariationDiff fromNodes(final Collection> nodes, final Source source) { final DiffNode newRoot = DiffNode.createRoot(DiffLinesLabel.ofCodeBlock(DIFFGRAPH_LABEL)); nodes.stream() .filter(DiffNode::isRoot) diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/DiffNode.java b/src/main/java/org/variantsync/diffdetective/variation/diff/DiffNode.java index 4244fadfe..47088e292 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/DiffNode.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/DiffNode.java @@ -13,7 +13,6 @@ import org.variantsync.diffdetective.variation.tree.VariationNode; import org.variantsync.functjonal.Cast; -import java.lang.reflect.Array; import java.util.*; import java.util.function.Function; import java.util.stream.Stream; @@ -52,31 +51,51 @@ public class DiffNode implements HasNodeType { private Node featureMapping; /** - * The parents {@link DiffNode} before and after the edit. - * This array has to be indexed by {@code Time.ordinal()} - * - * Invariant: Iff {@code getParent(time) != null} then - * {@code getParent(time).getChildOrder(time).contains(this)}. + * Bundles all the state that may be different before and after an edit. + * @see at */ - private DiffNode[] parents = Cast.unchecked(Array.newInstance(DiffNode.class, 2)); + private static class TimeDependentState { + /** + * The parents {@link DiffNode} before and after the edit. + * This array has to be indexed by {@code Time.ordinal()} + * + * Invariant: Iff {@code getParent(time) != null} then + * {@code getParent(time).getChildOrder(time).contains(this)}. + */ + public DiffNode parent; + + /** + * The children before and after the edit. + * This array has to be indexed by {@code Time.ordinal()} + * + * Invariant: Iff {@code getChildOrder(time).contains(child)} then + * {@code child.getParent(time) == this}. + */ + public List> children; + + /** + * Cache for before and after projections. + * It stores the projection node at each time so that only one instance of {@link Projection} + * per {@link Time} is ever created. This array has to be indexed by {@code Time.ordinal()} + * + *

This field is required to allow identity tests of {@link Projection}s with {@code ==}. + */ + public Projection projection; + + public TimeDependentState() { + parent = null; + children = null; + children = new ArrayList<>(); + projection = null; + } + } - /** - * The children before and after the edit. - * This array has to be indexed by {@code Time.ordinal()} - * - * Invariant: Iff {@code getChildOrder(time).contains(child)} then - * {@code child.getParent(time) == this}. - */ - private final List>[] children = Cast.unchecked(Array.newInstance(List.class, 2)); + private final TimeDependentState stateBefore = new TimeDependentState(); + private final TimeDependentState stateAfter = new TimeDependentState(); - /** - * Cache for before and after projections. - * It stores the projection node at each time so that only one instance of {@link Projection} - * per {@link Time} is ever created. This array has to be indexed by {@code Time.ordinal()} - * - *

This field is required to allow identity tests of {@link Projection}s with {@code ==}. - */ - private Projection[] projections = Cast.unchecked(Array.newInstance(Projection.class, 2)); + private TimeDependentState at(Time time) { + return time.match(stateBefore, stateAfter); + } /** * Creates a DiffNode with the given parameters. @@ -90,11 +109,22 @@ public class DiffNode implements HasNodeType { public DiffNode(DiffType diffType, NodeType nodeType, DiffLineNumber fromLines, DiffLineNumber toLines, Node featureMapping, L label) { - children[BEFORE.ordinal()] = new ArrayList<>(); - children[AFTER.ordinal()] = new ArrayList<>(); + this(diffType, fromLines, toLines, featureMapping, new VariationLabel<>(nodeType, label)); + } + /** + * Creates a DiffNode with the given parameters. + * @param diffType The type of change made to this node. + * @param fromLines The starting line number of the corresponding text. + * @param toLines The ending line number of the corresponding text. + * @param featureMapping The formula stored in this node. Should be null for artifact nodes. + * @param label The label and type of this node. + */ + public DiffNode(DiffType diffType, + DiffLineNumber fromLines, DiffLineNumber toLines, + Node featureMapping, VariationLabel label) { this.diffType = diffType; - this.label = new VariationLabel<>(nodeType, label); + this.label = label; this.from = fromLines; this.to = toLines; this.featureMapping = featureMapping; @@ -253,7 +283,7 @@ public void drop(Time time) { * Returns -1 if the given node is not a child of this node. */ public int indexOfChild(final DiffNode child, Time time) { - return children[time.ordinal()].indexOf(child); + return at(time).children.indexOf(child); } /** @@ -264,8 +294,8 @@ public void insertChild(final DiffNode child, int index, Time time) { Assert.assertFalse(isChild(child, time), () -> "Given child " + child + " already has a " + time + " parent (" + child.getParent(time) + ")!"); - children[time.ordinal()].add(index, child); - child.parents[time.ordinal()] = this; + at(time).children.add(index, child); + child.at(time).parent = this; } /** @@ -277,8 +307,8 @@ public void addChild(final DiffNode child, Time time) { Assert.assertFalse(isChild(child, time), () -> "Given child " + child + " already has a " + time + " parent (" + child.getParent(time) + ")!"); - children[time.ordinal()].add(child); - child.parents[time.ordinal()] = this; + at(time).children.add(child); + child.at(time).parent = this; } /** @@ -301,8 +331,8 @@ public void addChildren(final Collection> children, Time time) { public void removeChild(final DiffNode child, Time time) { Assert.assertTrue(isChild(child, time)); - child.parents[time.ordinal()] = null; - children[time.ordinal()].remove(child); + child.at(time).parent = null; + at(time).children.remove(child); } /** @@ -327,30 +357,130 @@ public void removeChildren(final Collection> childrenToRemove) { * @return All removed children. */ public List> removeChildren(Time time) { - for (var child : children[time.ordinal()]) { - child.parents[time.ordinal()] = null; + for (var child : at(time).children) { + child.at(time).parent = null; } - final List> orphans = children[time.ordinal()]; - children[time.ordinal()] = new ArrayList<>(); + final List> orphans = at(time).children; + at(time).children = new ArrayList<>(); return orphans; } /** - * Removes all children from the given node and adds them as children to this node at the respective times. - * The order of children is not stable because first all before children are transferred and then all after children. + * Removes all children from the given node and adds them as children to this node at the given time. + * The given node will have no children afterwards at the given time. + * @param other The node whose children should be stolen for the given time. + */ + public void stealChildrenOf(Time time, final DiffNode other) { + addChildren(other.removeChildren(time), time); + } + + /** + * Removes all children from the given node and adds them as children to this node (at all times). * The given node will have no children afterwards. * @param other The node whose children should be stolen. */ public void stealChildrenOf(final DiffNode other) { - Time.forAll(time -> addChildren(other.removeChildren(time), time)); + Time.forAll(time -> stealChildrenOf(time, other)); + } + + /** + * Splits an {@link isNon unmodified} node into a removed and an added node. + * Only one new node is created. Depending on {@code time}, {@code this} is changed into + * {@link DiffType#ADD} for {@link Time#BEFORE} or {@link DiffType#REM} for {@link Time#AFTER}. + * + * @param time decides which node is created + * @return the new node that exists at time {@code time}. + */ + public DiffNode split(Time time) { + Assert.assertTrue(isNon()); + + DiffType otherDiffType = DiffType.thatExistsOnlyAt(time); + var other = new DiffNode( + otherDiffType, + getFromLine().as(otherDiffType), + getToLine().as(otherDiffType), + getFormula(), + Cast.unchecked(label.withoutTimeDependentState(time.other())) + ); + + this.diffType = otherDiffType.inverse(); + this.from = this.from.as(this.diffType); + this.to = this.to.as(this.diffType); + this.setLabel(Cast.unchecked(this.getLabel().withoutTimeDependentState(time))); + + other.addChildren(this.removeChildren(time), time); + getParent(time).replaceChild(this, other, time); + + // Preserve the projection by changing its `backingNode` to `other`. + if (this.at(time).projection != null) { + other.at(time).projection = this.at(time).projection; + this.at(time).projection = null; + other.at(time).projection.backingNode = other; + } + + return other; + } + + /** + * Merges {@code other} into this node. + * {@code other} is removed from the graph and this node inherits all of its edges. This + * node and {@code other} need to be compatible (exist at different times and have the + * same {@link getNodeType node type} and compatible {@link getLabel labels}). + *

+ * Both {@code this} and {@code other} must not be {@link isRoot the root}. + * + * @param other the node which is removed from the graph + */ + public void join(DiffNode other) { + Time time = switch (diffType) { + case ADD -> BEFORE; + case REM -> AFTER; + case NON -> Assert.fail("Attempt to join a node that already exists at both times."); + }; + Assert.assertEquals(other.diffType, DiffType.thatExistsOnlyAt(time)); + Assert.assertEquals(getNodeType(), other.getNodeType()); + Assert.assertFalse(isRoot()); + Assert.assertFalse(other.isRoot()); + + diffType = DiffType.NON; + setLabel(Cast.unchecked(getLabel().withTimeDependentStateFrom(other.getLabel(), time))); + + setFromLine(getFromLine().withLineNumberAtTime(other.getFromLine().atTime(AFTER), AFTER)); + setToLine(getToLine().withLineNumberAtTime(other.getToLine().atTime(AFTER), AFTER)); + + this.stealChildrenOf(other); + other.getParent(time).replaceChild(other, this, time); + } + + /** + * Replaces a child of this node with another node. + *

+ * If {@code oldChild} is not a child of this node, nothing happens. + * + * @param oldChild the child that is removed + * @param newChild the child that is inserted + * @param time at which the child relation is changed + */ + public void replaceChild(DiffNode oldChild, DiffNode newChild, Time time) { + Assert.assertNull(newChild.getParent(time)); + Assert.assertTrue(newChild.getDiffType().existsAtTime(time)); + + for (ListIterator> it = at(time).children.listIterator(); it.hasNext(); ) { + if (it.next() == oldChild) { + it.set(newChild); + newChild.at(time).parent = oldChild.at(time).parent; + oldChild.at(time).parent = null; + break; + } + } } /** * Returns the parent of this node before or after the edit. */ public DiffNode getParent(Time time) { - return parents[time.ordinal()]; + return at(time).parent; } /** @@ -430,7 +560,7 @@ public void setFormula(Node featureMapping) { * Returns the order of the children at {@code time}. */ public List> getChildOrder(Time time) { - return Collections.unmodifiableList(children[time.ordinal()]); + return Collections.unmodifiableList(at(time).children); } /** @@ -440,8 +570,8 @@ public List> getChildOrder(Time time) { */ public Stream> getAllChildrenStream() { return Stream.concat( - children[BEFORE.ordinal()].stream(), - children[AFTER.ordinal()].stream().filter(child -> child.getParent(BEFORE) != this) + at(BEFORE).children.stream(), + at(AFTER).children.stream().filter(child -> child.getParent(BEFORE) != this) ); }; @@ -505,7 +635,7 @@ public boolean isChild(DiffNode child, Time time) { * Returns true iff this node has no children. */ public boolean isLeaf() { - return children[BEFORE.ordinal()].isEmpty() && children[AFTER.ordinal()].isEmpty(); + return at(BEFORE).children.isEmpty() && at(AFTER).children.isEmpty(); } /** @@ -612,10 +742,14 @@ public static DiffNode fromID(int id, String label) { * Checks that the VariationDiff is in a valid state. * In particular, this method checks that all edges are well-formed (e.g., edges can be inconsistent because edges are double-linked). * This method also checks that a node with exactly one parent was edited, and that a node with exactly two parents was not edited. + * To check all children recursively, use {@link VariationDiff#assertConsistency}. * @see Assert#assertTrue * @throws AssertionError when an inconsistency is detected. */ public void assertConsistency() { + // check that the projections are valid (i.e., node type specific consistency checks) + diffType.forAllTimesOfExistence(time -> this.projection(time).assertConsistency()); + // check consistency of children lists and edges for (final DiffNode c : getAllChildren()) { Assert.assertTrue(isChild(c), () -> "Child " + c + " of " + this + " is neither a before nor an after child!"); @@ -639,6 +773,10 @@ public void assertConsistency() { if (pb != null && pa == null) { Assert.assertTrue(isRem()); } + // the root was not edited + if (pb == null && pa == null) { + Assert.assertTrue(isNon()); + } // a node with exactly two parents was not edited if (pb != null && pa != null) { Assert.assertTrue(isNon()); @@ -649,22 +787,6 @@ public void assertConsistency() { Assert.assertTrue(pb.isNon()); } } - - // Else and Elif nodes have an If or Elif as parent. - if (this.isElse() || this.isElif()) { - Time.forAll(time -> { - if (getParent(time) != null) { - Assert.assertTrue(getParent(time).isIf() || getParent(time).isElif(), time + " parent " + getParent(time) + " of " + this + " is neither IF nor ELIF!"); - } - }); - } - - // Only if and elif nodes have a formula - if (this.isIf() || this.isElif()) { - Assert.assertTrue(this.getFormula() != null, "If or elif without feature mapping!"); - } else { - Assert.assertTrue(this.getFormula() == null, "Node with type " + getNodeType() + " has a non null feature mapping"); - } } /** @@ -677,11 +799,11 @@ public void assertConsistency() { public Projection projection(Time time) { Assert.assertTrue(getDiffType().existsAtTime(time)); - if (projections[time.ordinal()] == null) { - projections[time.ordinal()] = new Projection<>(this, time); + if (at(time).projection == null) { + at(time).projection = new Projection<>(this, time); } - return projections[time.ordinal()]; + return at(time).projection; } /** @@ -719,7 +841,7 @@ public static , L1 extends Label, L2 extends Labe for (var variationChildNode : variationNode.getChildren()) { var diffChildNode = unchanged(convert, variationChildNode); - Time.forAll(time -> diffNode.addChild(diffChildNode, time)); + diffChildNode.getDiffType().forAllTimesOfExistence(time -> diffNode.addChild(diffChildNode, time)); } return diffNode; @@ -750,7 +872,6 @@ public DiffNode deepCopy(HashMap, DiffNode> oldToNew) { public DiffNode shallowCopy() { return new DiffNode( getDiffType(), - getNodeType(), getFromLine(), getToLine(), getFormula(), @@ -758,6 +879,65 @@ public DiffNode shallowCopy() { ); } + /** + * Turns this node into a node with {@link DiffType} {@link DiffType#NON}. + * To retain consistency of the variation diff, this node will also ensure that this + * node will have a parent at all times. + * To this end, the parent of this node will also be made unchanged if necessary, potentially + * making some or all ancestors of this node unchanged recursively. + * This method has no effect when this node is already unchanged. + */ + public void makeUnchanged() { + if (isNon()) return; + + this.diffType = DiffType.NON; + + final DiffNode bp = at(Time.BEFORE).parent; + final DiffNode ap = at(Time.AFTER).parent; + + // If we have a parent before the change and after the change, making this node unchanged is fine. + // Otherwise, if at least one parent is null, we have to set the other parent and make our parent unchanged as well. + if (bp == null || ap == null) { + // There is only one parent, which we store in this field. + final DiffNode p = bp == null ? ap : bp; + final Time timeOfExistingEdge = bp == null ? AFTER : BEFORE; + final Time timeOfNewEdge = timeOfExistingEdge.other(); + + Assert.assertTrue(p != null); + + // If the parent is not unchanged, we have to make it unchanged so that it can be our + // parent at all times. + if (!p.isNon()) { + p.makeUnchanged(); + } + + // Now make p our parent at all times, not just at a single time. + // To this end, we essentially have to "patch" this node into our parent scope at timeOfNewEdge. + // Technically, this means that we have to add this node to the children list of p at a specific index. + // We run into the alignment problem here if there is an insertion (or multiple insertions) right next to a deleted node we make unchanged or vice versa. + // Hence, the index at which to patch our node is not unique. + // There are multiple heuristics or strategies we could use to determine the index: + // - constant index: always use index 0 for example + // - line numbers: use the index right before the node with a higher line number at timeOfNewEdge + // This solution requires knowledge on line numbers which are not always present (e.g., in diffs generated in code). + // - context-based patching: Try to locate the node where its neighbors at timeOfNewEdge are most similar to the neighbors at timeOfExistingEdge + // This requires some knowledge on the labels to match contexts. + // We lightweight context-based patching here by trying to insert the node directly right of its closest unchanged left neighbor. + int patchIndex = 0; // the index at which to insert this node at timeOfNewEdge + final List> siblingsAndMe = p.getChildOrder(timeOfExistingEdge); + // We start walking from our closest left neighbor towards the leftmost sibling (at index 0) and try to find the first unchanged sibling. + for (int i = p.indexOfChild(this, timeOfExistingEdge) - 1; i >= 0; i--) { + final DiffNode candidate = siblingsAndMe.get(i); + if (candidate.isNon()) { // i.e., exists at timeOfNewEdge as well + // Insert ourselves as the new right neighbor of the candidate node + patchIndex = p.indexOfChild(candidate, timeOfNewEdge) + 1; + break; + } + } + p.insertChild(this, patchIndex, timeOfNewEdge); + } + } + /** * Transforms a {@code VariationNode} into a {@code DiffNode} by diffing {@code variationNode} * to itself. Recursively translates all children. @@ -787,7 +967,7 @@ private static boolean isSameAs(DiffNode a, DiffNode b, a.getNodeType().equals(b.getNodeType()) && a.getFromLine().equals(b.getFromLine()) && a.getToLine().equals(b.getToLine()) && - (a.getFormula() == null ? b.getFormula() == null : a.getFormula().equals(b.getFormula())) && + Objects.equals(a.getFormula(), b.getFormula()) && a.getLabel().equals(b.getLabel()) )) { return false; @@ -804,6 +984,42 @@ private static boolean isSameAs(DiffNode a, DiffNode b, return aIt.hasNext() == bIt.hasNext(); } + /** + * Returns true if this subtree is exactly equal to {@code other} except for line numbers and other metadata in labels. + * This equality is a weaker equality than {@link DiffNode#isSameAs(DiffNode)} (i.e., whenever isSameAs returns true, so does + * isSameAsIgnoringLineNumbers). + * Labels of DiffNodes are compared via {@link Label#observablyEqual(Label, Label)}. + * This check uses equality checks instead of identity. + */ + public boolean isSameAsIgnoringLineNumbers(DiffNode other) { + return isSameAsIgnoringLineNumbers(this, other, new HashSet<>()); + } + + private static boolean isSameAsIgnoringLineNumbers(DiffNode a, DiffNode b, Set> visited) { + if (!visited.add(a)) { + return true; + } + + if (!( + a.getDiffType().equals(b.getDiffType()) && + a.getNodeType().equals(b.getNodeType()) && + Objects.equals(a.getFormula(), b.getFormula()) && + Label.observablyEqual(a.getLabel(), b.getLabel()) + )) { + return false; + } + + Iterator> aIt = a.getAllChildren().iterator(); + Iterator> bIt = b.getAllChildren().iterator(); + while (aIt.hasNext() && bIt.hasNext()) { + if (!isSameAsIgnoringLineNumbers(aIt.next(), bIt.next(), visited)) { + return false; + } + } + + return aIt.hasNext() == bIt.hasNext(); + } + @Override public String toString() { String s; diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/DiffType.java b/src/main/java/org/variantsync/diffdetective/variation/diff/DiffType.java index 4adc558a5..233ffae89 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/DiffType.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/DiffType.java @@ -1,11 +1,10 @@ package org.variantsync.diffdetective.variation.diff; import org.apache.commons.lang3.function.FailableConsumer; -import org.tinylog.Logger; +import org.apache.commons.lang3.function.FailableRunnable; import java.util.Optional; import java.util.Set; -import java.util.function.Consumer; /** * Type of change made to an artifact (e.g., a line of text in a text-based diff). @@ -13,13 +12,13 @@ * These values correspond to the domain of the Delta function from our paper. */ public enum DiffType { - ADD("+"), - REM("-"), - NON(" "); + ADD('+'), + REM('-'), + NON(' '); - public final String symbol; + public final char symbol; - DiffType(String symbol) { + DiffType(char symbol) { this.symbol = symbol; } @@ -70,8 +69,9 @@ public static Optional thatExistsOnlyAtAll(final Set

+ * Note that this field is package private because {@link DiffNode} needs to change it, + * for example in {@link DiffNode#split}, + * to preserve the identity of this instance and prevent it from becoming invalid. + * Only {@link DiffNode} is intended to have access to this field. + */ + DiffNode backingNode; private Time time; /** @@ -121,4 +130,9 @@ public Node getFormula() { public int getID() { return getBackingNode().getID(); } + + @Override + public String toString() { + return String.format("Projection(%s, %s)", time, getBackingNode()); + } }; diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/ProjectionSource.java b/src/main/java/org/variantsync/diffdetective/variation/diff/ProjectionSource.java index 7f277b69c..5f6225af1 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/ProjectionSource.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/ProjectionSource.java @@ -1,7 +1,23 @@ package org.variantsync.diffdetective.variation.diff; +import java.util.List; + +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.Label; -import org.variantsync.diffdetective.variation.tree.source.VariationTreeSource; -public record ProjectionSource(VariationDiff origin, Time time) implements VariationTreeSource { +public record ProjectionSource(VariationDiff origin, Time time) implements Source { + @Override + public String getSourceExplanation() { + return "Projection"; + } + + @Override + public List getSources() { + return List.of(origin); + } + + @Override + public List getSourceArguments() { + return List.of(time); + } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareDiffer.java b/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareDiffer.java new file mode 100644 index 000000000..11e5a60fa --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareDiffer.java @@ -0,0 +1,56 @@ +package org.variantsync.diffdetective.variation.diff; + +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.nio.file.Path; + +import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.util.FileSource; +import org.variantsync.diffdetective.util.Source; +import org.variantsync.diffdetective.variation.Label; +import org.variantsync.diffdetective.variation.tree.VariationTree; // For Javadoc + +/** + * A generic interface for creating variation diffs from two states represented as text. + * This interface represents a differ that can walk any of the paths present in our visual abstract + * (see below) and thus the states before and after the edit are represented as text. For each of + * the two paths, parsing a text diff and diffing variation trees, there is a specialized version of + * this interface, {@link VariabilityAwareTextDiffer} and {@link VariabilityAwareTreeDiffer} + * respectively. In particular, {@link VariabilityAwareTreeDiffer} represents the input states as + * {@link VariationTree}s. + * + * Variability-Aware Differencing Overview. Same as in the README.md. + * + * @see VariabilityAwareDiffers + */ +@FunctionalInterface +public interface VariabilityAwareDiffer { + /** + * Create a variation diff by diffing the content of two {@link Reader}s. + * For {@link VariationDiff#getSource() traceability}, both {@link Reader}s are paired with a {@link Source}. + */ + VariationDiff diff(Reader before, Reader after, Source beforeSource, Source afterSource) throws IOException, DiffParseException; + + /** + * Create a variation diff by diffing the content of two {@link String}s. + * For {@link VariationDiff#getSource() traceability}, both {@link String}s are paired with a {@link Source}. + */ + default VariationDiff diff(String before, String after, Source beforeSource, Source afterSource) throws IOException, DiffParseException { + return diff(new StringReader(before), new StringReader(after), beforeSource, afterSource); + } + + /** + * Create a variation diff by diffing the content of two {@link Path}s. + * @see diff(Reader, Reader, Source, Source) + */ + default VariationDiff diff(Path before, Path after) throws IOException, DiffParseException { + try ( + Reader beforeStream = new FileReader(before.toFile()); + Reader afterStream = new FileReader(after.toFile()) + ) { + return diff(beforeStream, afterStream, new FileSource(before), new FileSource(after)); + } + } +} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareDiffers.java b/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareDiffers.java new file mode 100644 index 000000000..ce790d696 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareDiffers.java @@ -0,0 +1,135 @@ +package org.variantsync.diffdetective.variation.diff; + +import java.io.IOException; +import java.io.Reader; + +import org.apache.commons.io.IOUtils; +import org.eclipse.jgit.diff.DiffAlgorithm; +import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.util.CompositeSource; +import org.variantsync.diffdetective.util.Source; +import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.diff.construction.GumTreeDiff; +import org.variantsync.diffdetective.variation.diff.construction.JGitDiff; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser; // For Javadoc +import org.variantsync.diffdetective.variation.tree.VariationTree; + +import com.github.gumtreediff.matchers.Matcher; +import com.github.gumtreediff.matchers.Matchers; + +/** + * A collection of differs that create variation diffs. + * @see VariabilityAwareDiffer + * @see VariationDiff + */ +public class VariabilityAwareDiffers { + /** + * Returns a differ that {@link VariationDiffParser#createVariationDiff parses} a + * {@link VariationDiff} after {@link JGitDiff#textDiff diffing} with + * {@link DiffAlgorithm.SupportedAlgorithm one of JGit's differ}. + * + * @param lineDiffAlgorithm the Git diffing algorithm to use + * @param parseOptions options for parsing the {@link VariationDiff} + * @return the diffed {@link VariationDiff} + */ + public static VariabilityAwareTextDiffer JGit(DiffAlgorithm.SupportedAlgorithm lineDiffAlgorithm, VariationDiffParseOptions parseOptions) { + return new VariabilityAwareTextDiffer() { + @Override + public String diffLines(Reader before, Reader after) throws IOException { + return JGitDiff.textDiff(IOUtils.toString(before), IOUtils.toString(after), lineDiffAlgorithm); + } + + @Override + public String diffLines(String before, String after) throws IOException { + return JGitDiff.textDiff(before, after, lineDiffAlgorithm); + } + + @Override + public VariationDiffParseOptions getParseOptions() { + return parseOptions; + } + }; + } + + /** + * Calls {@link JGit(DiffAlgorithm.SupportedAlgorithm, VariationDiffParseOptions)} with + * {@link DiffAlgorithm.SupportedAlgorithm#MYERS} and {@link VariationDiffParseOptions#Default}. + */ + public static VariabilityAwareTextDiffer JGitMyers() { + return JGit(DiffAlgorithm.SupportedAlgorithm.MYERS, VariationDiffParseOptions.Default); + } + + /** + * Returns a differ that {@link VariationTree#fromFile parses} two variation trees and then + * {@link GumTreeDiff#diffUsingMatching diffs} these variation trees. + * + * @param parseOptions options for parsing the {@link VariationTree}s + * @param matcher the matcher used for diffing the {@link VariationTree}s + * @return the diffed {@link VariationDiff} + */ + public static VariabilityAwareTreeDiffer GumTree(VariationDiffParseOptions parseOptions, Matcher matcher) { + return new VariabilityAwareTreeDiffer() { + @Override + public VariationDiff diffTrees(VariationTree before, VariationTree after) { + return GumTreeDiff.diffUsingMatching(before, after, matcher); + } + + @Override + public VariationDiffParseOptions getParseOptions() { + return parseOptions; + } + }; + } + + /** + * Calls {@link GumTree(VariationDiffParseOptions, Matcher)} with {@link + * VariationDiffParseOptions#Default} and {@link Matchers#getInstance {@code + * Matchers.getInstance().getMatcher()}}. + */ + public static VariabilityAwareTreeDiffer GumTree() { + return GumTree(VariationDiffParseOptions.Default, Matchers.getInstance().getMatcher()); + } + + /** + * Returns a differ that first parses a {@link VariationDiff} like {@link JGit} and then + * {@link GumTreeDiff#improveMatching improves} the represented matching. + * + * @param lineDiffAlgorithm the Git diffing algorithm to use + * @param parseOptions options for parsing the {@link VariationDiff} + * @param matcher the matcher used for diffing the variation trees + * @return the diffed {@link VariationDiff} + */ + public static VariabilityAwareTextDiffer JGitGumTreeHybrid(DiffAlgorithm.SupportedAlgorithm lineDiffAlgorithm, VariationDiffParseOptions parseOptions, Matcher matcher) { + return new VariabilityAwareTextDiffer() { + @Override + public String diffLines(Reader before, Reader after) throws IOException { + return JGitDiff.textDiff(IOUtils.toString(before), IOUtils.toString(after), lineDiffAlgorithm); + } + + @Override + public VariationDiffParseOptions getParseOptions() { + return parseOptions; + } + + @Override + public VariationDiff diff(Reader before, Reader after, Source beforeSource, Source afterSource) throws IOException, DiffParseException { + VariationDiff vd = VariabilityAwareTextDiffer.super.diff(before, after, beforeSource, afterSource); + return new VariationDiff<>( + GumTreeDiff.improveMatching(vd.getRoot(), matcher), + new CompositeSource("GumTreeDiff.improveMatching", vd.getSource()) + ); + }; + }; + } + + /** + * Calls {@link JGitGumTreeHybrid(DiffAlgorithm.SupportedAlgorithm, VariationDiffParseOptions, + * Matcher)} with {@link DiffAlgorithm.SupportedAlgorithm#MYERS}, {@link + * VariationDiffParseOptions#Default}, and {@link Matchers#getInstance {@code + * Matchers.getInstance().getMatcher()}}. + */ + public static VariabilityAwareTextDiffer JGitMyersGumTreeHybrid() { + return JGitGumTreeHybrid(DiffAlgorithm.SupportedAlgorithm.MYERS, VariationDiffParseOptions.Default, Matchers.getInstance().getMatcher()); + } +} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareTextDiffer.java b/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareTextDiffer.java new file mode 100644 index 000000000..0fb6042c9 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareTextDiffer.java @@ -0,0 +1,62 @@ +package org.variantsync.diffdetective.variation.diff; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.util.CompositeSource; +import org.variantsync.diffdetective.util.Source; +import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser; + +/** + * A {@link VariabilityAwareDiffer} that first creates a line diff and + * {@link VariationDiffParser#createVariationDiff parses} this line diff into a + * {@link VariationDiff}. + */ +@FunctionalInterface +public interface VariabilityAwareTextDiffer extends VariabilityAwareDiffer { + /** + * Returns a line diff of {@code before} and {@code after} in the unified diff format. + */ + String diffLines(Reader before, Reader after) throws IOException; + + /** + * Returns a line diff of {@code before} and {@code after} in the unified diff format. + */ + default String diffLines(String before, String after) throws IOException { + return diffLines(new StringReader(before), new StringReader(after)); + } + + /** + * Returns the options used for {@link parseDiff parsing} the {@link VariationDiff} in {@link parseDiff}. + */ + default VariationDiffParseOptions getParseOptions() { + return VariationDiffParseOptions.Default; + } + + /** + * Parses the {@link diffLines line diff} into a {@link VariationDiff} using the options + * from {@link getParseOptions}. + */ + default VariationDiff parseDiff(String diff, Source diffSource) throws DiffParseException { + return VariationDiffParser.createVariationDiff( + diff, + new CompositeSource("VariationDiffParser.createVariationDiff", diffSource), + getParseOptions() + ); + } + + /** + * Composes {@link diffLines} and {@link parseDiff} to create a {@link VariationDiff}. + */ + @Override + default VariationDiff diff(Reader before, Reader after, Source beforeSource, Source afterSource) throws IOException, DiffParseException { + return parseDiff( + diffLines(before, after), + new CompositeSource("line diff", beforeSource, afterSource) + ); + } +} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareTreeDiffer.java b/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareTreeDiffer.java new file mode 100644 index 000000000..ec7aa0a6c --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/VariabilityAwareTreeDiffer.java @@ -0,0 +1,50 @@ +package org.variantsync.diffdetective.variation.diff; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; + +import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.util.Source; +import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.Label; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; +import org.variantsync.diffdetective.variation.tree.VariationTree; + +/** + * A {@link VariabilityAwareDiffer} that first {@link VariationTree#fromFile parses} {@link VariationTree}s and + * diffs these trees. + */ +@FunctionalInterface +public interface VariabilityAwareTreeDiffer extends VariabilityAwareDiffer { + /** + * Creates a {@link VariationDiff} by diffing two variation trees. + */ + VariationDiff diffTrees(VariationTree before, VariationTree after); + + /** + * Returns the options used for parsing the {@link VariationTree}s in {@link parseTree}. + */ + default VariationDiffParseOptions getParseOptions() { + return VariationDiffParseOptions.Default; + } + + /** + * {@link VariationTree#fromFile Parses} {@code input} into a {@link VariationTree} using + * the options from {@code getParseOptions}. + */ + default VariationTree parseTree(Reader input, Source source) throws IOException, DiffParseException { + return VariationTree.fromFile(new BufferedReader(input), source, getParseOptions()); + } + + /** + * Composes {@link parseTree} and {@link diffTrees} to create a {@link VariationDiff}. + */ + @Override + default VariationDiff diff(Reader before, Reader after, Source beforeSource, Source afterSource) throws IOException, DiffParseException { + return diffTrees( + parseTree(before, beforeSource), + parseTree(after, afterSource) + ); + } +} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/VariationDiff.java b/src/main/java/org/variantsync/diffdetective/variation/diff/VariationDiff.java index 4a865e1f4..1a288996b 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/VariationDiff.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/VariationDiff.java @@ -12,18 +12,18 @@ import org.variantsync.diffdetective.diff.result.DiffError; import org.variantsync.diffdetective.diff.result.DiffParseException; import org.variantsync.diffdetective.util.Assert; +import org.variantsync.diffdetective.util.FileSource; +import org.variantsync.diffdetective.util.fide.FixTrueFalse; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.Label; import org.variantsync.diffdetective.variation.diff.construction.GumTreeDiff; import org.variantsync.diffdetective.variation.diff.construction.JGitDiff; import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser; -import org.variantsync.diffdetective.variation.diff.source.PatchFile; -import org.variantsync.diffdetective.variation.diff.source.PatchString; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; import org.variantsync.diffdetective.variation.diff.traverse.VariationDiffTraversal; import org.variantsync.diffdetective.variation.diff.traverse.VariationDiffVisitor; import org.variantsync.diffdetective.variation.tree.VariationTree; +import org.variantsync.diffdetective.util.Source; import org.variantsync.functjonal.Cast; import org.variantsync.functjonal.Result; @@ -34,6 +34,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; @@ -48,23 +49,23 @@ /** * Implementation of variation tree diffs from our ESEC/FSE'22 paper. * An instance of this class represents a variation tree diff. It stores the root of the graph as a {@link DiffNode}. - * It optionally holds a {@link VariationDiffSource} that describes how the variation tree diff was obtained. + * It optionally holds a {@link Source} that describes how the variation tree diff was obtained. * The graph structure is implemented by the {@link DiffNode} class. * * @param The type of label stored in this tree. * * @author Paul Bittner, Sören Viegener */ -public class VariationDiff { +public class VariationDiff implements Source { private final DiffNode root; - private VariationDiffSource source; + private Source source; /** * Creates a VariationDiff that only consists of the single given root node. * @param root The root of this tree. */ public VariationDiff(DiffNode root) { - this(root, VariationDiffSource.Unknown); + this(root, Source.Unknown); } /** @@ -73,7 +74,7 @@ public VariationDiff(DiffNode root) { * @param root The root of this tree. * @param source The data from which the VariationDiff was created. */ - public VariationDiff(DiffNode root, VariationDiffSource source) { + public VariationDiff(DiffNode root, Source source) { this.root = root; this.source = source; } @@ -89,9 +90,7 @@ public VariationDiff(DiffNode root, VariationDiffSource source) { */ public static VariationDiff fromFile(final Path p, VariationDiffParseOptions parseOptions) throws IOException, DiffParseException { try (BufferedReader file = Files.newBufferedReader(p)) { - final VariationDiff tree = VariationDiffParser.createVariationDiff(file, parseOptions); - tree.setSource(new PatchFile(p)); - return tree; + return VariationDiffParser.createVariationDiff(file, new FileSource(p), parseOptions); } } @@ -101,13 +100,13 @@ public static VariationDiff fromFile(final Path p, VariationDiff * So just lines preceded by "+", "-", or " " are expected. * @param diff The diff as text. Lines should be separated by a newline character. Each line should be preceded by either "+", "-", or " ". * @param parseOptions {@link VariationDiffParseOptions} for the parsing process. + * @param source the {@link Source} of {@code diff} * @return A result either containing the parsed VariationDiff or an error message in case of failure. * @throws DiffParseException if {@code diff} couldn't be parsed */ - public static VariationDiff fromDiff(final String diff, final VariationDiffParseOptions parseOptions) throws DiffParseException { - final VariationDiff d; + public static VariationDiff fromDiff(final String diff, final Source source, final VariationDiffParseOptions parseOptions) throws DiffParseException { try { - d = VariationDiffParser.createVariationDiff(diff, parseOptions); + return VariationDiffParser.createVariationDiff(diff, source, parseOptions); } catch (DiffParseException e) { Logger.error(""" Could not parse diff: @@ -117,8 +116,6 @@ public static VariationDiff fromDiff(final String diff, final Va diff); throw e; } - d.setSource(new PatchString(diff)); - return d; } /** @@ -162,7 +159,7 @@ public static Result, List> fromPatch(f /** * Create a VariationDiff from two given text files. - * @see #fromLines(String, String, DiffAlgorithm.SupportedAlgorithm, VariationDiffParseOptions) + * @see #fromLines(String, String, Source, Source, DiffAlgorithm.SupportedAlgorithm, VariationDiffParseOptions) */ public static VariationDiff fromFiles( final Path beforeFile, @@ -174,22 +171,24 @@ public static VariationDiff fromFiles( try (BufferedReader b = Files.newBufferedReader(beforeFile); BufferedReader a = Files.newBufferedReader(afterFile) ) { - return fromLines(IOUtils.toString(b), IOUtils.toString(a), algorithm, options); + return fromLines(IOUtils.toString(b), IOUtils.toString(a), new FileSource(beforeFile), new FileSource(afterFile), algorithm, options); } } /** * Creates a variation diff from to line-based text inputs. * This method just forwards to: - * @see JGitDiff#diff(String, String, DiffAlgorithm.SupportedAlgorithm, VariationDiffParseOptions) + * @see JGitDiff#diff(String, String, Source, Source, DiffAlgorithm.SupportedAlgorithm, VariationDiffParseOptions) */ public static VariationDiff fromLines( String before, String after, + Source beforeSource, + Source afterSource, DiffAlgorithm.SupportedAlgorithm algorithm, VariationDiffParseOptions options) throws IOException, DiffParseException { - return JGitDiff.diff(before, after, algorithm, options); + return JGitDiff.diff(before, after, beforeSource, afterSource, algorithm, options); } /** @@ -207,7 +206,7 @@ public static VariationDiff fromTrees(VariationTree befo * The returned value is a deep copy of the variation tree within this diff * at the given time. * If you instead wish to only have a view on the tree at the given diff - * have a look at {@link DiffNode#projection(Time)} for this trees {@link #getRoot() root}. + * have a look at {@link DiffNode#projection(Time)} for this tree's {@link #getRoot() root}. * @param t The time for which to project the variation tree. */ public VariationTree project(Time t) { @@ -374,22 +373,50 @@ public int count(final Predicate> nodesToCount) { return count.get(); } + /** + * Returns all variable names occurring in annotations (i.e., formulas of mapping nodes) in this variation diff. + * This method is deterministic: It will return the feature names always in the same order, assuming the variation diff is not changed inbetween. + * @return A set of every occuring feature name. + */ + public LinkedHashSet computeAllFeatureNames() { + LinkedHashSet features = new LinkedHashSet<>(); + forAll(node -> { + if (node.isConditionalAnnotation()) { + features.addAll(node.getFormula().getUniqueContainedFeatures()); + } + }); + // Since FeatureIDE falsely reports constants "True" and "False" as feature names, we have to remove them from the resulting set. + features.removeIf(FixTrueFalse::isTrueLiteral); + features.removeIf(FixTrueFalse::isFalseLiteral); + return features; + } + /** * Sets the source of this VariationDiff. - * @see VariationDiffSource + * @see Source */ - public void setSource(final VariationDiffSource source) { + public void setSource(final Source source) { this.source = source; } /** * Returns the source of this VariationDiff (i.e., the data this VariationDiff was created from). - * @see VariationDiffSource + * @see Source */ - public VariationDiffSource getSource() { + public Source getSource() { return source; } + @Override + public List getSources() { + return List.of(source); + } + + @Override + public String getSourceExplanation() { + return "VariationDiff"; + } + /** * Returns the number of nodes in this VariationDiff. */ @@ -515,13 +542,23 @@ public ConsistencyResult isConsistent() { return ConsistencyResult.Success(); } + /** + * @see DiffNode#isSameAs + */ public boolean isSameAs(VariationDiff b) { return getRoot().isSameAs(b.getRoot()); } + /** + * @see DiffNode#isSameAsIgnoringLineNumbers + */ + public boolean isSameAsIgnoringLineNumbers(VariationDiff b) { + return getRoot().isSameAsIgnoringLineNumbers(b.getRoot()); + } + @Override public String toString() { - return "VariationDiff of " + source; + return functionExplanation(); } public VariationDiff deepCopy() { diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/bad/BadVDiff.java b/src/main/java/org/variantsync/diffdetective/variation/diff/bad/BadVDiff.java index 25496273d..18279e635 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/bad/BadVDiff.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/bad/BadVDiff.java @@ -2,13 +2,14 @@ import org.variantsync.diffdetective.diff.text.DiffLineNumberRange; import org.variantsync.diffdetective.util.Assert; +import org.variantsync.diffdetective.util.CompositeSource; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.util.StringUtils; import org.variantsync.diffdetective.variation.Label; import org.variantsync.diffdetective.variation.diff.DiffNode; import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.DiffType; import org.variantsync.diffdetective.variation.diff.Time; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; import org.variantsync.diffdetective.variation.tree.VariationTree; import org.variantsync.diffdetective.variation.tree.VariationTreeNode; import org.variantsync.functjonal.Cast; @@ -68,7 +69,7 @@ public record BadVDiff( Map, VariationTreeNode> matching, Map, DiffType> coloring, Map, DiffLineNumberRange> lines -) +) implements Source { /** * Memoization of the VariationTreeNodes a DiffNode was @@ -198,8 +199,18 @@ public static BadVDiff fromGood(VariationDiff d) { record EdgeToConstruct( VariationTreeNode child, DiffNode parent, - Time t - ) {} + Time t, + int index + ) { + public EdgeToConstruct( + VariationTreeNode child, + DiffNode parent, + Time t, + DiffNode originalChild + ) { + this(child, parent, t, parent.indexOfChild(originalChild, t)); + } + } final FromGoodNodeTranslation nodeTranslation = new FromGoodNodeTranslation<>(); @@ -259,7 +270,7 @@ record EdgeToConstruct( nodeTranslation.put(diffNode, time, self); - edgesToConstruct.add(new EdgeToConstruct<>(self, diffNode.getParent(time), time)); + edgesToConstruct.add(new EdgeToConstruct<>(self, diffNode.getParent(time), time, diffNode)); // further metadata to copy lines.put(self, dRange); @@ -283,22 +294,23 @@ record EdgeToConstruct( */ if (pbefore != null) { edgesToConstruct.add(new EdgeToConstruct<>( - self, pbefore, BEFORE + self, pbefore, BEFORE, diffNode )); } else if (pafter != null) { edgesToConstruct.add(new EdgeToConstruct<>( - self, pafter, AFTER + self, pafter, AFTER, diffNode )); } } }); + edgesToConstruct.sort(Comparator.comparingInt(EdgeToConstruct::index)); for (final EdgeToConstruct e : edgesToConstruct) { nodeTranslation.get(e.parent, e.t).addChild(e.child); } return new BadVDiff<>( - new VariationTree<>(root, new BadVDiffFromVariationDiffSource(d.getSource())), + new VariationTree<>(root, new CompositeSource("BadVDiff.fromGood", d.getSource())), matching, coloring, lines @@ -324,14 +336,24 @@ public VariationDiff toGood() { record EdgeToConstruct( DiffNode child, VariationTreeNode parent, - Time time - ) {} + Time time, + int index + ) { + public EdgeToConstruct( + DiffNode child, + VariationTreeNode parent, + Time time, + VariationTreeNode originalChild + ) { + this(child, parent, time, parent.indexOfChild(originalChild)); + } + } final List> edgesToConstruct = new ArrayList<>(); final Map, DiffNode> nodeTranslation = new HashMap<>(); - final DiffNode root = toGood(diff.root()); - nodeTranslation.put(diff.root(), root); + final DiffNode root = toGood(diff.getRoot()); + nodeTranslation.put(diff.getRoot(), root); diff.forAllPreorder(vtnode -> { // If a node was already translated (because it was merged), it does not have to be translated anymore. @@ -351,7 +373,7 @@ record EdgeToConstruct( nodeTranslation.put(vtnode, vGood); coloring.get(vtnode).forAllTimesOfExistence( - t -> edgesToConstruct.add(new EdgeToConstruct<>(vGood, parent, t)) + t -> edgesToConstruct.add(new EdgeToConstruct<>(vGood, parent, t, vtnode)) ); } else { // v was cloned. @@ -369,24 +391,20 @@ record EdgeToConstruct( // invoke the callback for a single time: // BEFORE for REM and AFTER for ADD. vColor.forAllTimesOfExistence( - t -> edgesToConstruct.add(new EdgeToConstruct<>(vGood, parent, t)) + t -> edgesToConstruct.add(new EdgeToConstruct<>(vGood, parent, t, vtnode)) ); badBuddyColor.forAllTimesOfExistence( - t -> edgesToConstruct.add(new EdgeToConstruct<>(vGood, badBuddy.getParent(), t)) + t -> edgesToConstruct.add(new EdgeToConstruct<>(vGood, badBuddy.getParent(), t, badBuddy)) ); } }); + edgesToConstruct.sort(Comparator.comparingInt(EdgeToConstruct::index)); for (final EdgeToConstruct e : edgesToConstruct) { nodeTranslation.get(e.parent()).addChild(e.child(), e.time()); } - VariationDiffSource source = VariationDiffSource.Unknown; - if (diff.source() instanceof BadVDiffFromVariationDiffSource s) { - source = s.initialVariationDiff(); - } - - return new VariationDiff<>(root, source); + return new VariationDiff<>(root, new CompositeSource("BadVDiff.toGood", diff.getSource())); } public BadVDiff deepCopy() { @@ -434,7 +452,17 @@ private void prettyPrint(final String indent, StringBuilder b, VariationTreeNode public String prettyPrint() { final StringBuilder b = new StringBuilder(); - prettyPrint("", b, diff.root()); + prettyPrint("", b, diff.getRoot()); return b.toString(); } + + @Override + public String getSourceExplanation() { + return "BadVDiff"; + } + + @Override + public List getSources() { + return List.of(diff); + } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/bad/BadVDiffFromVariationDiffSource.java b/src/main/java/org/variantsync/diffdetective/variation/diff/bad/BadVDiffFromVariationDiffSource.java deleted file mode 100644 index ceb69d515..000000000 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/bad/BadVDiffFromVariationDiffSource.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.variantsync.diffdetective.variation.diff.bad; - -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; -import org.variantsync.diffdetective.variation.tree.source.VariationTreeSource; - -public record BadVDiffFromVariationDiffSource(VariationDiffSource initialVariationDiff) implements VariationTreeSource { - @Override - public String toString() { - return initialVariationDiff.toString(); - } -} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/construction/GumTreeDiff.java b/src/main/java/org/variantsync/diffdetective/variation/diff/construction/GumTreeDiff.java index ecc6377d6..fbf190b62 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/construction/GumTreeDiff.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/construction/GumTreeDiff.java @@ -9,10 +9,11 @@ import org.variantsync.diffdetective.gumtree.VariationDiffAdapter; import org.variantsync.diffdetective.gumtree.VariationTreeAdapter; import org.variantsync.diffdetective.util.Assert; +import org.variantsync.diffdetective.util.CompositeSource; import org.variantsync.diffdetective.variation.Label; import org.variantsync.diffdetective.variation.diff.DiffNode; +import org.variantsync.diffdetective.variation.diff.Time; import org.variantsync.diffdetective.variation.diff.VariationDiff; -import org.variantsync.diffdetective.variation.diff.source.VariationTreeDiffSource; import org.variantsync.diffdetective.variation.diff.traverse.VariationDiffTraversal; import org.variantsync.diffdetective.variation.tree.VariationNode; import org.variantsync.diffdetective.variation.tree.VariationTree; @@ -22,8 +23,6 @@ import java.util.Map; import static org.variantsync.diffdetective.variation.diff.DiffType.ADD; -import static org.variantsync.diffdetective.variation.diff.DiffType.NON; -import static org.variantsync.diffdetective.variation.diff.DiffType.REM; import static org.variantsync.diffdetective.variation.diff.Time.AFTER; import static org.variantsync.diffdetective.variation.diff.Time.BEFORE; @@ -35,13 +34,21 @@ public class GumTreeDiff { * @see diffUsingMatching(VariationNode, VariationNode, Matcher) */ public static VariationDiff diffUsingMatching(VariationTree before, VariationTree after) { + return diffUsingMatching(before, after, Matchers.getInstance().getMatcher()); + } + + /** + * Create a {@link VariationDiff} by matching nodes between {@code before} and {@code after} + * with {@code matcher}. + */ + public static VariationDiff diffUsingMatching(VariationTree before, VariationTree after, Matcher matcher) { DiffNode root = diffUsingMatching( - before.root(), - after.root(), - Matchers.getInstance().getMatcher() + before.getRoot(), + after.getRoot(), + matcher ); - return new VariationDiff<>(root, new VariationTreeDiffSource(before.source(), after.source())); + return new VariationDiff<>(root, new CompositeSource("diffUsingMatching", before, after)); } /** @@ -85,7 +92,10 @@ public static , L extends Label> DiffNode diffU var dst = new VariationTreeAdapter(after); MappingStore matching = matcher.match(src, dst); - Assert.assertTrue(matching.has(src, dst)); + + // The following algorithm assumes that the root nodes are matched so we ensure that this is + // the case here by establishing that mapping if necessary. + ensureMapping(matching, src, dst); removeUnmapped(matching, src); for (var child : dst.getChildren()) { @@ -114,8 +124,7 @@ private static void removeUnmapped(MappingStore mappings, Vari Tree dst = mappings.getDstForSrc(node); if (dst == null || !dst.getLabel().equals(node.getLabel())) { var diffNode = Cast.>unchecked(node).getDiffNode(); - diffNode.diffType = REM; - diffNode.drop(AFTER); + diffNode.split(AFTER).drop(); } } } @@ -147,7 +156,7 @@ private static void addUnmapped(MappingStore mappings, DiffNod new DiffLineNumber(DiffLineNumber.InvalidLineNumber, from, from), new DiffLineNumber(DiffLineNumber.InvalidLineNumber, to, to), variationNode.getFormula(), - Cast.unchecked(variationNode.getLabel().clone()) + Cast.unchecked(variationNode.getLabel().withoutTimeDependentState(BEFORE)) ); } else { diffNode = Cast.>unchecked(src).getDiffNode(); @@ -155,6 +164,10 @@ private static void addUnmapped(MappingStore mappings, DiffNod // Always drop and reinsert it because it could have moved. diffNode.drop(AFTER); } + + diffNode.setFromLine(diffNode.getFromLine().withLineNumberAtTime(afterNode.getVariationNode().getLineRange().fromInclusive(), AFTER)); + diffNode.setToLine(diffNode.getToLine().withLineNumberAtTime(afterNode.getVariationNode().getLineRange().toExclusive(), AFTER)); + diffNode.setLabel(Cast.unchecked(diffNode.getLabel().withTimeDependentStateFrom(afterNode.getVariationNode().getLabel(), Time.AFTER))); } parent.addChild(diffNode, AFTER); @@ -182,14 +195,17 @@ public static DiffNode improveMatching(DiffNode tree, Ma MappingStore matching = new MappingStore(src, dst); extractMatching(src, dst, matching); matcher.match(src, dst, matching); - Assert.assertTrue(matching.has(src, dst)); + + // The following algorithm assumes that the root nodes are matched so we ensure that this is + // the case here by establishing that mapping if necessary. + ensureMapping(matching, src, dst); for (var srcNode : src.preOrder()) { var dstNode = matching.getDstForSrc(srcNode); var beforeNode = Cast.>unchecked(srcNode).getDiffNode(); if (dstNode == null || !srcNode.getLabel().equals(dstNode.getLabel())) { if (beforeNode.isNon()) { - splitNode(beforeNode); + beforeNode.split(AFTER); } Assert.assertTrue(beforeNode.isRem()); @@ -198,13 +214,13 @@ public static DiffNode improveMatching(DiffNode tree, Ma if (beforeNode != afterNode) { if (beforeNode.isNon()) { - splitNode(beforeNode); + beforeNode.split(AFTER); } if (afterNode.isNon()) { - afterNode = splitNode(afterNode); + afterNode.split(BEFORE); } - joinNode(beforeNode, afterNode); + beforeNode.join(afterNode); } Assert.assertTrue(beforeNode.isNon()); @@ -215,61 +231,6 @@ public static DiffNode improveMatching(DiffNode tree, Ma return tree; } - /** - * Removes the implicit matching between the {@code BEFORE} and {@code AFTER} projection of - * {@code beforeNode}. This is achieved by copying {@code beforeNode} and reconnecting all - * necessary edges such that the new node exists only after and {@code beforeNode} only exists - * before the edit. - * - * This method doesn't change the {@code BEFORE} and {@code AFTER} projection of {@code - * beforeNode}. - * - * @param beforeNode the node to be split - * @return a copy of {@code beforeNode} existing only after the edit. - */ - private static DiffNode splitNode(DiffNode beforeNode) { - Assert.assertTrue(beforeNode.isNon()); - - DiffNode afterNode = beforeNode.shallowCopy(); - - afterNode.diffType = ADD; - beforeNode.diffType = REM; - - afterNode.addChildren(beforeNode.removeChildren(AFTER), AFTER); - var afterParent = beforeNode.getParent(AFTER); - afterParent.insertChild(afterNode, afterParent.indexOfChild(beforeNode, AFTER), AFTER); - beforeNode.drop(AFTER); - - beforeNode.assertConsistency(); - afterNode.assertConsistency(); - - return afterNode; - } - - /** - * Merges {@code afterNode} into {@code beforeNode} such that {@code beforeNode.isNon() == - * true}. Essentially, an implicit matching is inserted between {@code beforeNode} and {@code - * afterNode}. - * - * This method doesn't change the {@code BEFORE} and {@code AFTER} projection of {@code - * beforeNode}. - * - * @param beforeNode the node which is will exist {@code BEFORE} and {@code AFTER} the edit - * @param afterNode the node which is discarded - */ - private static void joinNode(DiffNode beforeNode, DiffNode afterNode) { - Assert.assertTrue(beforeNode.isRem()); - Assert.assertTrue(afterNode.isAdd()); - - beforeNode.diffType = NON; - - beforeNode.addChildren(afterNode.removeChildren(AFTER), AFTER); - - var afterParent = afterNode.getParent(AFTER); - afterParent.insertChild(beforeNode, afterParent.indexOfChild(afterNode, AFTER), AFTER); - afterNode.drop(AFTER); - } - /** * Makes the implicit matching of a {@code VariationDiff} explicit. * @@ -299,4 +260,20 @@ private static void extractMatching( } } } + + /** + * Add a mapping between {@code src} and {@code dst}. + * In case {@code src} or {@code dst} are mapped to some other nodes, these mappings are + * removed. + */ + private static void ensureMapping(MappingStore matching, Tree src, Tree dst) { + if (matching.isSrcMapped(src)) { + matching.removeMapping(src, matching.getDstForSrc(src)); + } + if (matching.isDstMapped(dst)) { + matching.removeMapping(dst, matching.getSrcForDst(dst)); + } + + matching.addMapping(src, dst); + } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/construction/JGitDiff.java b/src/main/java/org/variantsync/diffdetective/variation/diff/construction/JGitDiff.java index 6d2920585..abd988811 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/construction/JGitDiff.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/construction/JGitDiff.java @@ -4,6 +4,8 @@ import org.eclipse.jgit.diff.*; import org.variantsync.diffdetective.diff.git.GitDiffer; import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.util.CompositeSource; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.diff.Time; import org.variantsync.diffdetective.variation.diff.VariationDiff; @@ -122,9 +124,11 @@ Using our own formatter without diff headers (paired with a maximum context (?)) * Uses JGit to diff the two files using the specified {@code options}, and afterwards, creates the variation diff. * Creates a variation diff from to line-based text inputs. * First creates a line-based diff with {@link #textDiff(String, String, DiffAlgorithm.SupportedAlgorithm)} - * and then parses that diff with {@link VariationDiff#fromDiff(String, VariationDiffParseOptions)}. + * and then parses that diff with {@link VariationDiff#fromDiff(String, Source, VariationDiffParseOptions)}. * @param linesBefore State of annotated lines before the change. * @param linesAfter State of annotated lines after the change. + * @param sourceBefore the {@link Source} of {@code linesBefore} + * @param sourceAfter the {@link Source} of {@code linesAfter} * @param algorithm Specification of which algorithm to use for diffing with JGit. * @param options various options for parsing * @return A variation diff comprising the changes. @@ -134,9 +138,15 @@ Using our own formatter without diff headers (paired with a maximum context (?)) public static VariationDiff diff( String linesBefore, String linesAfter, + Source sourceBefore, + Source sourceAfter, DiffAlgorithm.SupportedAlgorithm algorithm, VariationDiffParseOptions options ) throws IOException, DiffParseException { - return VariationDiff.fromDiff(textDiff(linesBefore, linesAfter, algorithm), options); + return VariationDiff.fromDiff( + textDiff(linesBefore, linesAfter, algorithm), + new CompositeSource("JGitDiff.textDiff", sourceBefore, sourceAfter), + options + ); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/doc-files/variability-aware-differencing.png b/src/main/java/org/variantsync/diffdetective/variation/diff/doc-files/variability-aware-differencing.png new file mode 100644 index 000000000..eedc3fd69 Binary files /dev/null and b/src/main/java/org/variantsync/diffdetective/variation/diff/doc-files/variability-aware-differencing.png differ diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/parse/VariationDiffParser.java b/src/main/java/org/variantsync/diffdetective/variation/diff/parse/VariationDiffParser.java index 2df9c3bf3..f8b1f2cc2 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/parse/VariationDiffParser.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/parse/VariationDiffParser.java @@ -17,6 +17,7 @@ import org.variantsync.diffdetective.feature.Annotation; import org.variantsync.diffdetective.feature.AnnotationType; import org.variantsync.diffdetective.util.Assert; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.NodeType; import org.variantsync.diffdetective.variation.diff.DiffNode; @@ -79,6 +80,15 @@ public record DiffLine(DiffType diffType, String content) { /* State */ + /* Implementation note: + * We use stacks to keep track of the path from the current node (the top element in the stack) + * to the root (the bottom element in the stack) of the variation diff. This is not strictly + * necessary because as soon as a node is pushed onto the stack, the corresponding edge is also + * inserted. Hence, we could reconstruct the stack by traversing the current graph using + * {@link DiffNode#getParent} and check for the root using {@link DiffNode#isRoot}. + * However, for consistency with the papers that explain this algorithm and for ease of + * implementation, we keep the stack based implementation. + */ /** * A stack containing the current path before the edit from the root of the currently parsed @@ -108,17 +118,18 @@ public record DiffLine(DiffType diffType, String content) { /** - * The same as {@link VariationDiffParser#createVariationDiff(BufferedReader, VariationDiffParseOptions)} + * The same as {@link VariationDiffParser#createVariationDiff(BufferedReader, Source, VariationDiffParseOptions)} * but with the diff given as a single string with line breaks instead of a {@link BufferedReader}. * * @throws DiffParseException if {@code fullDiff} couldn't be parsed */ public static VariationDiff createVariationDiff( final String fullDiff, + final Source source, final VariationDiffParseOptions parseOptions ) throws DiffParseException { try { - return createVariationDiff(new BufferedReader(new StringReader(fullDiff)), parseOptions); + return createVariationDiff(new BufferedReader(new StringReader(fullDiff)), source, parseOptions); } catch (IOException e) { throw new AssertionError("No actual IO should be performed because only a StringReader is used"); } @@ -131,6 +142,7 @@ public static VariationDiff createVariationDiff( * This parsing algorithm is described in detail in Sören Viegener's bachelor's thesis. * * @param fullDiff The full diff of a patch obtained from a buffered reader. + * @param source the {@link Source} of {@code fullDiff} * @param options {@link VariationDiffParseOptions} for the parsing process. * @return A parsed {@link VariationDiff} upon success or an error indicating why parsing failed. * @throws IOException when reading from {@code fullDiff} fails. @@ -138,11 +150,12 @@ public static VariationDiff createVariationDiff( */ public static VariationDiff createVariationDiff( BufferedReader fullDiff, + Source source, final VariationDiffParseOptions options ) throws IOException, DiffParseException { return new VariationDiffParser( options - ).parse(() -> { + ).parse(source, () -> { String line = fullDiff.readLine(); if (line == null) { return null; @@ -153,10 +166,11 @@ public static VariationDiff createVariationDiff( /** * Parses a variation tree from a source file. - * This method is similar to {@link #createVariationDiff(BufferedReader, VariationDiffParseOptions)} + * This method is similar to {@link #createVariationDiff(BufferedReader, Source, VariationDiffParseOptions)} * but acts as if all lines where unmodified. * * @param file The source code file (not a diff) to be parsed. + * @param source the {@link Source} of {@code file} * @param options {@link VariationDiffParseOptions} for the parsing process. * @return A parsed {@link VariationDiff}. * @throws IOException iff {@code file} throws an {@code IOException} @@ -164,11 +178,12 @@ public static VariationDiff createVariationDiff( */ public static VariationDiff createVariationTree( BufferedReader file, + Source source, VariationDiffParseOptions options ) throws IOException, DiffParseException { return new VariationDiffParser( options - ).parse(() -> { + ).parse(source, () -> { String line = file.readLine(); if (line == null) { return null; @@ -189,7 +204,7 @@ public static VariationDiff createVariationTree( /** * Initializes the parse state. * - * @see #createVariationDiff(BufferedReader, VariationDiffParseOptions) + * @see #createVariationDiff(BufferedReader, Source, VariationDiffParseOptions) */ private VariationDiffParser( VariationDiffParseOptions options @@ -200,6 +215,7 @@ private VariationDiffParser( /** * Parses the line diff {@code fullDiff}. * + * @param source the {@link Source} of {@code lines} * @param lines should supply successive lines of the diff to be parsed, or {@code null} if * there are no more lines to be parsed. * @return the parsed {@code VariationDiff} @@ -208,6 +224,7 @@ private VariationDiffParser( * is detected */ private VariationDiff parse( + Source source, FailableSupplier lines ) throws IOException, DiffParseException { DiffNode root = DiffNode.createRoot(new DiffLinesLabel()); @@ -288,12 +305,7 @@ private VariationDiff parse( ); } - // Cleanup state - beforeStack.clear(); - afterStack.clear(); - lastArtifact = null; - - return new VariationDiff<>(root); + return new VariationDiff<>(root, source); } /** @@ -326,8 +338,8 @@ private void parseLine( // Do not create a node for ENDIF, but update the line numbers of the closed if-chain // and remove that if-chain from the relevant stacks. - diffType.forAllTimesOfExistence(beforeStack, afterStack, stack -> - popIfChain(stack, fromLine) + diffType.forAllTimesOfExistence(time -> + popIfChain(time, fromLine, line) ); } else if (options.collapseMultipleCodeLines() && annotation.type() == AnnotationType.None @@ -355,32 +367,49 @@ private void parseLine( } /** - * Pop {@code stack} until an IF node is popped. + * Pop the stack until an IF node is popped. * If there were ELSEs or ELIFs between an IF and an ENDIF, they were placed on the stack and * have to be popped now. The {@link DiffNode#getToLine() end line numbers} are adjusted * - * @param stack the stack which should be popped + * @param time which stack to pop the if chain (i.e., {@link beforeStack} or {@link afterStack}) * @param elseLineNumber the first line of the else which causes this IF to be popped + * @param line the line containing the endif * @throws DiffParseException if {@code stack} doesn't contain an IF node */ private void popIfChain( - Stack> stack, - DiffLineNumber elseLineNumber + Time time, + DiffLineNumber elseLineNumber, + LogicalLine line ) throws DiffParseException { + Stack> stack = time.match(beforeStack, afterStack); + DiffLineNumber previousLineNumber = elseLineNumber; do { DiffNode annotation = stack.peek(); + // Save endif + if (annotation.isIf()) { + var endIf = line.getLines(); + var otherEndIf = annotation.getLabel().getDiffTrailingLines(); + + // Split the node if two different endif lines are associated to one if node. + if (!otherEndIf.isEmpty() && !endIf.equals(otherEndIf)) { + annotation = annotation.split(time); + } + + annotation.getLabel().setDiffTrailingLines(endIf); + } + // Set the line number of now closed annotations to the beginning of the // following annotation. annotation.setToLine(new DiffLineNumber( Math.max(previousLineNumber.inDiff(), annotation.getToLine().inDiff()), - stack == beforeStack - ? previousLineNumber.beforeEdit() - : annotation.getToLine().beforeEdit(), - stack == afterStack - ? previousLineNumber.afterEdit() - : annotation.getToLine().afterEdit() + time.match( + previousLineNumber.beforeEdit(), + annotation.getToLine().beforeEdit()), + time.match( + annotation.getToLine().afterEdit(), + previousLineNumber.afterEdit()) )); previousLineNumber = annotation.getFromLine(); diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/render/VariationDiffRenderer.java b/src/main/java/org/variantsync/diffdetective/variation/diff/render/VariationDiffRenderer.java index 91b03e0b9..a6dacc622 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/render/VariationDiffRenderer.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/render/VariationDiffRenderer.java @@ -8,6 +8,7 @@ import org.variantsync.diffdetective.shell.ShellExecutor; import org.variantsync.diffdetective.util.Assert; import org.variantsync.diffdetective.util.IO; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.util.StringUtils; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.Label; @@ -17,7 +18,6 @@ import org.variantsync.diffdetective.variation.diff.serialize.LineGraphConstants; import org.variantsync.diffdetective.variation.diff.serialize.LineGraphExport; import org.variantsync.diffdetective.variation.diff.serialize.LineGraphExportOptions; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; import java.io.IOException; import java.nio.file.Files; @@ -193,7 +193,7 @@ public boolean renderWithTreeFormat(final VariationDiff boolean render(final VariationDiff tree, final String treeAndFileName, final Path directory, RenderOptions options, LineGraphExportOptions exportOptions, BiFunction treeHeader) { + private boolean render(final VariationDiff tree, final String treeAndFileName, final Path directory, RenderOptions options, LineGraphExportOptions exportOptions, BiFunction treeHeader) { final Path tempFile = directory.resolve(treeAndFileName + ".lg"); try (var destination = IO.newBufferedOutputStream(tempFile)) { diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/Format.java b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/Format.java index 2a7327903..65401c376 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/Format.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/Format.java @@ -1,11 +1,16 @@ package org.variantsync.diffdetective.variation.diff.serialize; +import org.eclipse.jgit.diff.DiffAlgorithm; +import org.eclipse.jgit.diff.EditList; +import org.eclipse.jgit.diff.Sequence; +import org.eclipse.jgit.diff.SequenceComparator; import org.variantsync.diffdetective.variation.Label; import org.variantsync.diffdetective.variation.diff.DiffNode; import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.serialize.edgeformat.EdgeLabelFormat; import org.variantsync.diffdetective.variation.diff.serialize.nodeformat.DiffNodeLabelFormat; +import java.util.List; import java.util.function.Consumer; import static org.variantsync.diffdetective.variation.diff.Time.AFTER; @@ -69,20 +74,55 @@ public void forEachNode(VariationDiff variationDiff, Consumer */ public void forEachEdge(VariationDiff variationDiff, Consumer> callback) { variationDiff.forAll((node) -> { - var beforeParent = node.getParent(BEFORE); - var afterParent = node.getParent(AFTER); - - // Are both parent edges the same? - if (beforeParent != null && afterParent != null && beforeParent == afterParent) { - sortedEdgeWithLabel(node, node.getParent(BEFORE), StyledEdge.ALWAYS, callback); - } else { - if (beforeParent != null) { - sortedEdgeWithLabel(node, node.getParent(BEFORE), StyledEdge.BEFORE, callback); + List> beforeChildren = node.getChildOrder(BEFORE); + List> afterChildren = node.getChildOrder(AFTER); + + class ListSequence extends Sequence { + public final List list; + + public ListSequence(List list) { + this.list = list; + } + + @Override + public int size() { + return list.size(); } - if (afterParent != null) { - sortedEdgeWithLabel(node, node.getParent(AFTER), StyledEdge.AFTER, callback); + } + + class ListSequenceComparator extends SequenceComparator> { + @Override + public boolean equals(ListSequence sequence1, int index1, ListSequence sequence2, int index2) { + return sequence1.list.get(index1) == sequence2.list.get(index2); + } + + @Override + public int hash(ListSequence sequence, int index) { + return System.identityHashCode(sequence.list.get(index)); } } + + final EditList editList = DiffAlgorithm.getAlgorithm(DiffAlgorithm.SupportedAlgorithm.MYERS).diff( + new ListSequenceComparator>(), + new ListSequence<>(beforeChildren), + new ListSequence<>(afterChildren) + ); + + int beforeIndex = 0; + for (var edit : editList) { + for (; beforeIndex < edit.getBeginA(); ++beforeIndex) { + sortedEdgeWithLabel(beforeChildren.get(beforeIndex), node, StyledEdge.ALWAYS, callback); + } + for (; beforeIndex < edit.getEndA(); ++beforeIndex) { + sortedEdgeWithLabel(beforeChildren.get(beforeIndex), node, StyledEdge.BEFORE, callback); + } + for (int afterIndex = edit.getBeginB(); afterIndex < edit.getEndB(); ++afterIndex) { + sortedEdgeWithLabel(afterChildren.get(afterIndex), node, StyledEdge.AFTER, callback); + } + } + for (; beforeIndex < beforeChildren.size(); ++beforeIndex) { + sortedEdgeWithLabel(beforeChildren.get(beforeIndex), node, StyledEdge.ALWAYS, callback); + } }); } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/LineGraphExport.java b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/LineGraphExport.java index d1483b202..fe9b8319a 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/LineGraphExport.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/LineGraphExport.java @@ -10,12 +10,12 @@ import org.variantsync.diffdetective.diff.git.CommitDiff; import org.variantsync.diffdetective.diff.git.PatchDiff; import org.variantsync.diffdetective.metadata.Metadata; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.util.StringUtils; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.Label; import org.variantsync.diffdetective.variation.diff.Time; import org.variantsync.diffdetective.variation.diff.VariationDiff; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; import org.variantsync.functjonal.category.InplaceSemigroup; /** @@ -154,12 +154,12 @@ public static Statistic toLineGraphFormat(final PatchDiff patch, final LineGraph /** * Produces the final linegraph file content. - * Creates a linegraph header from the given VariationDiffSource using the {@link LineGraphExportOptions#treeFormat()} in the given options. + * Creates a linegraph header from the given Source using the {@link LineGraphExportOptions#treeFormat()} in the given options. * Then appends the already created file content for nodes and edges. - * @param source The {@link VariationDiffSource} that describes where the VariationDiff whose content is written to the file originated from. + * @param source The {@link Source} that describes where the VariationDiff whose content is written to the file originated from. * @param options {@link LineGraphExportOptions} used to determine the treeFormat for the header. */ - private static String lineGraphHeader(final VariationDiffSource source, final LineGraphExportOptions options) { + private static String lineGraphHeader(final Source source, final LineGraphExportOptions options) { return options.treeFormat().toLineGraphLine(source) + StringUtils.LINEBREAK; } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/LineGraphImport.java b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/LineGraphImport.java index 86686b6ed..dcb323eb3 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/LineGraphImport.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/LineGraphImport.java @@ -2,10 +2,10 @@ import org.variantsync.diffdetective.util.Assert; import org.variantsync.diffdetective.util.FileUtils; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.diff.DiffGraph; import org.variantsync.diffdetective.variation.diff.DiffNode; import org.variantsync.diffdetective.variation.diff.VariationDiff; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; import org.variantsync.diffdetective.variation.diff.source.LineGraphFileSource; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.NodeType; @@ -22,6 +22,11 @@ /** * Import VariationDiffs from line graph files. + *

+ * This is a very rudimentary implementation of a deserializer that supports a similar format than + * {@link LineGraphExport}. Rudimentary means that it only deserializes the structure of a variation + * diff. Most other properties, including the label, line numbers and formulas, are not (always) + * correctly deserialized. Hence, this is not an inverse of {@link LineGraphExport}. * * @author Kevin Jedelhauser, Paul Maximilian Bittner */ @@ -123,9 +128,9 @@ public static List> fromLineGraph(final BufferedRe * @return {@link VariationDiff} generated from the given, already parsed parameters. */ private static VariationDiff parseVariationDiff(final String lineGraph, final Path inFile, final List> diffNodeList, final LineGraphImportOptions options) { - VariationDiffSource variationDiffSource = options.treeFormat().fromLineGraphLine(lineGraph); + Source variationDiffSource = options.treeFormat().fromLineGraphLine(lineGraph); - if (variationDiffSource == null || VariationDiffSource.Unknown.equals(variationDiffSource)) { + if (variationDiffSource == null || Source.Unknown.equals(variationDiffSource)) { variationDiffSource = new LineGraphFileSource( lineGraph, inFile @@ -133,34 +138,33 @@ private static VariationDiff parseVariationDiff(final String lin } // Handle trees and graphs differently - if (options.graphFormat() == GraphFormat.DIFFGRAPH) { - return DiffGraph.fromNodes(diffNodeList, variationDiffSource); - } else if (options.graphFormat() == GraphFormat.VARIATION_DIFF) { - // If you should interpret the input data as VariationDiffs, always expect a root to be present. Parse all nodes (v) to a list of nodes. Search for the root. Assert that there is exactly one root. - DiffNode root = null; - for (final DiffNode v : diffNodeList) { - if (v.isRoot()) { - // v is root candidate - if (root != null) { - throw new RuntimeException("Not a VariationDiff: Got more than one root! Got \"" + root + "\" and \"" + v + "\"!"); - } - if (v.getNodeType() == NodeType.IF) { - root = v; - } else { - throw new RuntimeException("Not a VariationDiff but a DiffGraph: The node \"" + v + "\" is not labeled as IF but has no parents!"); + return switch (options.graphFormat()) { + case DIFFGRAPH: + yield DiffGraph.fromNodes(diffNodeList, variationDiffSource); + case VARIATION_DIFF: + // If you should interpret the input data as VariationDiffs, always expect a root to be present. Parse all nodes (v) to a list of nodes. Search for the root. Assert that there is exactly one root. + DiffNode root = null; + for (final DiffNode v : diffNodeList) { + if (v.isRoot()) { + // v is root candidate + if (root != null) { + throw new RuntimeException("Not a VariationDiff: Got more than one root! Got \"" + root + "\" and \"" + v + "\"!"); + } + if (v.getNodeType() == NodeType.IF) { + root = v; + } else { + throw new RuntimeException("Not a VariationDiff but a DiffGraph: The node \"" + v + "\" is not labeled as IF but has no parents!"); + } } } - } - if (root == null) { - throw new RuntimeException("Not a VariationDiff but a DiffGraph: No root found!"); - } + if (root == null) { + throw new RuntimeException("Not a VariationDiff but a DiffGraph: No root found!"); + } -// countRootTypes.merge(root.getNodeType(), 1, Integer::sum); + // countRootTypes.merge(root.getNodeType(), 1, Integer::sum); - return new VariationDiff<>(root, variationDiffSource); - } else { - throw new RuntimeException("Unsupported GraphFormat"); - } + yield new VariationDiff<>(root, variationDiffSource); + }; } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/edgeformat/ChildOrderEdgeFormat.java b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/edgeformat/ChildOrderEdgeFormat.java index 2904be75e..886a8c428 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/edgeformat/ChildOrderEdgeFormat.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/edgeformat/ChildOrderEdgeFormat.java @@ -15,7 +15,7 @@ * * This index is encoded into decimal and delimited by a semicolon from the previous value. * - * This format is mainly useful to equivalence of two {@link VariationDiff}s, for example in tests. + * This format is mainly useful to verify the equivalence of two {@link VariationDiff}s, for example in tests. * * @author Benjamin Moosherr */ diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/nodeformat/DiffNodeLabelFormat.java b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/nodeformat/DiffNodeLabelFormat.java index 378497db9..49a26b641 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/nodeformat/DiffNodeLabelFormat.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/nodeformat/DiffNodeLabelFormat.java @@ -7,7 +7,6 @@ import org.variantsync.diffdetective.variation.diff.DiffNode; import org.variantsync.diffdetective.variation.diff.serialize.LineGraphConstants; import org.variantsync.diffdetective.variation.diff.serialize.LinegraphFormat; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; import org.variantsync.functjonal.Pair; /** @@ -49,7 +48,7 @@ default List toMultilineLabel(DiffNode node) { } /** - * Converts a line describing a graph (starting with "t # ") in line graph format into a {@link VariationDiffSource}. + * Converts a line describing a graph (starting with "t # ") in line graph format into a {@link DiffNode}. * * @param lineGraphLine A line from a line graph file starting with "t #" * @return A pair with the first element being the id of the node specified in the given lineGrapLine. diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/nodeformat/IndexFormat.java b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/nodeformat/IndexFormat.java new file mode 100644 index 000000000..e10938a96 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/nodeformat/IndexFormat.java @@ -0,0 +1,27 @@ +package org.variantsync.diffdetective.variation.diff.serialize.nodeformat; + +import java.util.ArrayList; +import java.util.List; + +import org.variantsync.diffdetective.variation.Label; +import org.variantsync.diffdetective.variation.diff.DiffNode; +import org.variantsync.diffdetective.variation.diff.Time; +import org.variantsync.functjonal.Cast; + +/** + * Labels nodes using their index in their parent list at all times. + */ +public class IndexFormat implements DiffNodeLabelFormat { + @Override + public String toLabel(final DiffNode n) { + final DiffNode node = Cast.unchecked(n); + final Time[] allTimes = Time.values(); + final List values = new ArrayList<>(allTimes.length); + for (final Time t : allTimes) { + values.add(node.getDiffType().existsAtTime(t) && !node.isRoot() + ? Integer.toString(node.getParent(t).indexOfChild(node, t)) + : "_"); + } + return "(" + String.join(", ", values) + ")"; + } +} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/CommitDiffVariationDiffLabelFormat.java b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/CommitDiffVariationDiffLabelFormat.java index c4d19637e..dad73a7bc 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/CommitDiffVariationDiffLabelFormat.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/CommitDiffVariationDiffLabelFormat.java @@ -3,10 +3,10 @@ import org.apache.commons.io.FilenameUtils; import org.variantsync.diffdetective.diff.git.CommitDiff; import org.variantsync.diffdetective.diff.git.PatchDiff; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.diff.Time; import org.variantsync.diffdetective.variation.diff.serialize.LineGraphConstants; import org.variantsync.diffdetective.variation.diff.source.CommitDiffVariationDiffSource; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; import java.nio.file.InvalidPathException; import java.nio.file.Path; @@ -19,7 +19,7 @@ */ public class CommitDiffVariationDiffLabelFormat implements VariationDiffLabelFormat { @Override - public VariationDiffSource fromLabel(final String label) { + public Source fromLabel(final String label) { String[] commit = label.split(LineGraphConstants.TREE_NAME_SEPARATOR_REGEX); try { Path filePath = Paths.get(commit[0]); @@ -31,15 +31,19 @@ public VariationDiffSource fromLabel(final String label) { } @Override - public String toLabel(final VariationDiffSource variationDiffSource) { - if (variationDiffSource instanceof CommitDiffVariationDiffSource commitDiffVariationDiffSource) { + public String toLabel(final Source variationDiffSource) { + CommitDiffVariationDiffSource commitDiffVariationDiffSource = Source.findFirst(variationDiffSource, CommitDiffVariationDiffSource.class); + if (commitDiffVariationDiffSource != null) { // write for instances of CommitDiffVariationDiffSources return FilenameUtils.separatorsToUnix(commitDiffVariationDiffSource.getFileName().toString()) + LineGraphConstants.TREE_NAME_SEPARATOR + commitDiffVariationDiffSource.getCommitHash(); - } else if (variationDiffSource instanceof PatchDiff patchDiff) { + } + + PatchDiff patchDiff = Source.findFirst(variationDiffSource, PatchDiff.class); + if (patchDiff != null) { // write for instances of PatchDiffs return FilenameUtils.separatorsToUnix(patchDiff.getFileName(Time.AFTER)) + LineGraphConstants.TREE_NAME_SEPARATOR + patchDiff.getCommitDiff().getCommitHash(); - } else { - throw new UnsupportedOperationException("There is no implementation for this VariationDiffSource type: " + variationDiffSource); } + + throw new UnsupportedOperationException("There is no implementation for this Source type: " + variationDiffSource); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/IndexedTreeFormat.java b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/IndexedTreeFormat.java index 45a44a64d..67f7d351e 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/IndexedTreeFormat.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/IndexedTreeFormat.java @@ -1,10 +1,10 @@ package org.variantsync.diffdetective.variation.diff.serialize.treeformat; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; +import org.variantsync.diffdetective.util.Source; /** * Exports tree by indexing them. - * This format keeps an internal counter that is incremented on each call of {@link #toLabel(VariationDiffSource)}. + * This format keeps an internal counter that is incremented on each call of {@link #toLabel(Source)}. * Thus, every produced label will have the successive index of the previously produced label. */ public class IndexedTreeFormat implements VariationDiffLabelFormat { @@ -25,12 +25,12 @@ public void reset() { } @Override - public VariationDiffSource fromLabel(String label) { - return VariationDiffSource.Unknown; + public Source fromLabel(String label) { + return Source.Unknown; } @Override - public String toLabel(VariationDiffSource variationDiffSource) { + public String toLabel(Source variationDiffSource) { final String result = "" + nextId; ++nextId; return result; diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/VariationDiffLabelFormat.java b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/VariationDiffLabelFormat.java index f9c5d5ebb..ec3c6c56f 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/VariationDiffLabelFormat.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/serialize/treeformat/VariationDiffLabelFormat.java @@ -1,47 +1,47 @@ package org.variantsync.diffdetective.variation.diff.serialize.treeformat; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.diff.serialize.LineGraphConstants; import org.variantsync.diffdetective.variation.diff.serialize.LinegraphFormat; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; /** - * Reads and writes {@link VariationDiffSource} from and to line graph. + * Reads and writes {@link Source} from and to line graph. * @author Paul Bittner, Kevin Jedelhauser */ public interface VariationDiffLabelFormat extends LinegraphFormat { /** - * Converts a label of line graph into a {@link VariationDiffSource}. + * Converts a label of line graph into a {@link Source}. * - * @param label A string containing the label of the {@link VariationDiffSource} - * @return The {@link VariationDiffSource} descibed by this label. + * @param label A string containing the label of the {@link Source} + * @return The {@link Source} described by this label. */ - VariationDiffSource fromLabel(final String label); + Source fromLabel(final String label); /** - * Converts a {@link VariationDiffSource} label of line graph. + * Converts a {@link Source} label of line graph. * - * @param variationDiffSource The {@link VariationDiffSource} to be converted + * @param variationDiffSource The {@link Source} to be converted * @return The corresponding line graph line */ - String toLabel(final VariationDiffSource variationDiffSource); + String toLabel(final Source variationDiffSource); /** - * Converts a line describing a graph (starting with "t # ") in line graph format into a {@link VariationDiffSource}. + * Converts a line describing a graph (starting with "t # ") in line graph format into a {@link Source}. * * @param lineGraphLine A line from a line graph file starting with "t #" - * @return The {@link VariationDiffSource} descibed by the label of this line. + * @return The {@link Source} descibed by the label of this line. */ - default VariationDiffSource fromLineGraphLine(final String lineGraphLine) { + default Source fromLineGraphLine(final String lineGraphLine) { return fromLabel(lineGraphLine.substring((LineGraphConstants.LG_TREE_HEADER + " ").length())); } /** * Prepends the {@link LineGraphConstants#LG_TREE_HEADER tree declaration} to a label and return an entire line graph line. * - * @param variationDiffSource The {@link VariationDiffSource} to be converted - * @return The entire line graph line of a {@link VariationDiffSource}. + * @param variationDiffSource The {@link Source} to be converted + * @return The entire line graph line of a {@link Source}. */ - default String toLineGraphLine(final VariationDiffSource variationDiffSource) { + default String toLineGraphLine(final Source variationDiffSource) { return LineGraphConstants.LG_TREE_HEADER + " " + toLabel(variationDiffSource); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/source/CommitDiffVariationDiffSource.java b/src/main/java/org/variantsync/diffdetective/variation/diff/source/CommitDiffVariationDiffSource.java index 7b12106b7..b41b07397 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/source/CommitDiffVariationDiffSource.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/source/CommitDiffVariationDiffSource.java @@ -1,42 +1,29 @@ package org.variantsync.diffdetective.variation.diff.source; import java.nio.file.Path; +import java.util.List; import org.variantsync.diffdetective.diff.git.CommitDiff; // For Javadoc +import org.variantsync.diffdetective.util.Source; /** * Describes that a VariationDiff was created from a patch in a {@link CommitDiff}. + * @param getFileName Name of the modified file from whose changes the VariationDiff was parsed. + * @param getCommitHash Hash of the commit in which the edit occurred. */ -public class CommitDiffVariationDiffSource implements VariationDiffSource { - private final Path fileName; - private final String commitHash; - - /** - * Create a source that refers to changes to the given file in the given commit. - * @param fileName Name of the modified file from whose changes the VariationDiff was parsed. - * @param commitHash Hash of the commit in which the edit occurred. - */ - public CommitDiffVariationDiffSource(final Path fileName, final String commitHash) { - this.fileName = fileName; - this.commitHash = commitHash; - } - - /** - * Returns the name of the modified file from whose changes the VariationDiff was parsed. - */ - public Path getFileName() { - return fileName; +public record CommitDiffVariationDiffSource(Path getFileName, String getCommitHash) implements Source { + @Override + public String toString() { + return getFileName() + "@" + getCommitHash(); } - /** - * Returns the hash of the commit in which the edit occurred. - */ - public String getCommitHash() { - return commitHash; + @Override + public String getSourceExplanation() { + return "CommitDiff"; } @Override - public String toString() { - return fileName + "@" + commitHash; + public List getSourceArguments() { + return List.of(getFileName(), getCommitHash()); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/source/FromVariationTreeSource.java b/src/main/java/org/variantsync/diffdetective/variation/diff/source/FromVariationTreeSource.java deleted file mode 100644 index 29ee2a23c..000000000 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/source/FromVariationTreeSource.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.variantsync.diffdetective.variation.diff.source; - -import org.variantsync.diffdetective.variation.tree.source.VariationTreeSource; - -public record FromVariationTreeSource(VariationTreeSource inner) implements VariationDiffSource { - @Override - public String toString() { - return inner.toString(); - } -} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/source/LineGraphFileSource.java b/src/main/java/org/variantsync/diffdetective/variation/diff/source/LineGraphFileSource.java index 4b2d73e9d..7b25f2a39 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/source/LineGraphFileSource.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/source/LineGraphFileSource.java @@ -1,6 +1,9 @@ package org.variantsync.diffdetective.variation.diff.source; import java.nio.file.Path; +import java.util.List; + +import org.variantsync.diffdetective.util.Source; /** * A source for VariationDiffs that were parsed from a linegraph file. @@ -10,5 +13,14 @@ public record LineGraphFileSource( String graphHeader, Path file -) implements VariationDiffSource { +) implements Source { + @Override + public String getSourceExplanation() { + return "LineGraphFile"; + } + + @Override + public List getSourceArguments() { + return List.of(graphHeader, file); + } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/source/PatchFile.java b/src/main/java/org/variantsync/diffdetective/variation/diff/source/PatchFile.java deleted file mode 100644 index 060b909c6..000000000 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/source/PatchFile.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.variantsync.diffdetective.variation.diff.source; - -import java.nio.file.Path; - -/** - * A source for VariationDiff's that were created from patch files on disk. - * @param path Path to the patch file that was parsed to a VariationDiff. - */ -public record PatchFile(Path path) implements VariationDiffSource { -} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/source/PatchString.java b/src/main/java/org/variantsync/diffdetective/variation/diff/source/PatchString.java index 610029183..99feb00ca 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/source/PatchString.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/source/PatchString.java @@ -1,14 +1,20 @@ package org.variantsync.diffdetective.variation.diff.source; import org.variantsync.diffdetective.diff.text.TextBasedDiff; +import org.variantsync.diffdetective.util.Source; /** * Source for VariationDiffs that were created from a patch given as a String. * @param getDiff The patch as a String. */ -public record PatchString(String getDiff) implements TextBasedDiff, VariationDiffSource { +public record PatchString(String getDiff) implements TextBasedDiff, Source { + @Override + public String getSourceExplanation() { + return "Patch"; + } + @Override public String toString() { - return "from line-based diff " + getDiff; + return getSourceExplanation() + getDiff; } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/source/VariationDiffSource.java b/src/main/java/org/variantsync/diffdetective/variation/diff/source/VariationDiffSource.java deleted file mode 100644 index 01f5a944c..000000000 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/source/VariationDiffSource.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.variantsync.diffdetective.variation.diff.source; - -/** - * Describes or identifies that data a VariationDiff was created or parsed from. - * This is typically a patch. - */ -public interface VariationDiffSource { - /** - * Constant to use when the source of a VariationDiff is unknown - * or if it was created artificially. - */ - VariationDiffSource Unknown = new VariationDiffSource() { - @Override - public int hashCode() { - return 0; - } - - @Override - public String toString() { - return "Unknown VariationDiffSource"; - } - }; -} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/source/VariationTreeDiffSource.java b/src/main/java/org/variantsync/diffdetective/variation/diff/source/VariationTreeDiffSource.java deleted file mode 100644 index f5235f866..000000000 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/source/VariationTreeDiffSource.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.variantsync.diffdetective.variation.diff.source; - -import org.variantsync.diffdetective.variation.diff.VariationDiff; // For Javadoc -import org.variantsync.diffdetective.variation.tree.VariationTree; // For Javadoc -import org.variantsync.diffdetective.variation.tree.source.VariationTreeSource; - -/** - * Describes that a {@link VariationDiff} was created from two {@link VariationTree}s. - */ -public record VariationTreeDiffSource( - VariationTreeSource before, - VariationTreeSource after -) implements VariationDiffSource { - @Override - public String toString() { - return "from trees [" + before + "] and [" + after + "]"; - } -} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/CollapseNestedNonEditedAnnotations.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/CollapseNestedNonEditedAnnotations.java index 30da444b1..d2c19d2fa 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/CollapseNestedNonEditedAnnotations.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/CollapseNestedNonEditedAnnotations.java @@ -31,12 +31,12 @@ * * @author Paul Bittner */ -public class CollapseNestedNonEditedAnnotations implements VariationDiffTransformer { +public class CollapseNestedNonEditedAnnotations implements Transformer> { private final List>> chainCandidates = new ArrayList<>(); private final List>> chains = new ArrayList<>(); @Override - public List>> getDependencies() { + public List>>> getDependencies() { return List.of(Cast.unchecked(CutNonEditedSubtrees.class)); } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/CutNonEditedSubtrees.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/CutNonEditedSubtrees.java index 5e4bf16a2..cdd7afae7 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/CutNonEditedSubtrees.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/CutNonEditedSubtrees.java @@ -19,7 +19,7 @@ * of our edit classes in our ESEC/FSE'22 paper. * @author Paul Bittner */ -public class CutNonEditedSubtrees implements VariationDiffTransformer, VariationDiffVisitor { +public class CutNonEditedSubtrees implements Transformer>, VariationDiffVisitor { private final boolean keepDummy; /** diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/EliminateEmptyAlternatives.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/EliminateEmptyAlternatives.java new file mode 100644 index 000000000..f03201235 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/EliminateEmptyAlternatives.java @@ -0,0 +1,108 @@ +package org.variantsync.diffdetective.variation.diff.transform; + +import org.prop4j.Node; +import org.prop4j.NodeWriter; +import org.variantsync.diffdetective.util.Assert; +import org.variantsync.diffdetective.util.StringUtils; +import org.variantsync.diffdetective.variation.DiffLinesLabel; +import static org.variantsync.diffdetective.variation.DiffLinesLabel.Line; +import org.variantsync.diffdetective.variation.tree.VariationTree; +import org.variantsync.diffdetective.variation.tree.VariationTreeNode; + +import java.util.List; + +import static org.variantsync.diffdetective.util.fide.FormulaUtils.*; + +/** + * This transformer simplifies annotations such that empty alternatives do not appear in choices. + * This means, that nestings without any siblings such as + * + *
{@code
+ * #if A
+ * #elif B
+ * #elif C
+ * #else
+ *   foo
+ * #endif
+ * }
+ * + * will be simplified to + * + *
{@code
+ * #if !A && !B && !C
+ *   foo
+ * #endif
+ * }
+ * + * Annotations without any children also get eliminated. + * + * @author Paul Bittner + */ +public class EliminateEmptyAlternatives implements Transformer> { + /** + * Creates a copy of the given label but where the formula is set to the given formula. + * This method also updates the text in the DiffLinesLabel accordingly so that the text is + * consistent with the formula. + * This method assumes that the label has at least one line of text, otherwise the given label + * could not have a formula. + */ + private static DiffLinesLabel updatedLabel(DiffLinesLabel l, Node formula) { + final List lines = l.getDiffLines(); + Assert.assertFalse(lines.isEmpty()); + + // Assumption: + // The only case in which there is more than one line of text is, when we parsed a multiline macro. + // + // We hence may safely ignore any subsequent lines from our existing label because these correspond + // only to lines of a multiline macro, which we ought to replace anyway. + final Line head = lines.get(0); + Assert.assertTrue(head.content().contains("if")); + final String indent = StringUtils.getLeadingWhitespace(head.content()); + + final String newText = indent + "#if " + formula.toString(NodeWriter.javaSymbols); + + // We might have replaced multiple lines by a single line here. + // In this case, some line numbers got lost and any variation tree using this updated label somewhere might not + // have consecutive line numbering anymore. We could consider inserting empty lines to retain + // consecutive line numbers but that might be a more artifical change than inconsecutive line numbers. + return new DiffLinesLabel( + List.of(new Line(newText, head.lineNumber())), + l.getDiffTrailingLines() + ); + } + + private static void elim(VariationTreeNode subtree) { + // We simplify only annotations. + if (!subtree.isAnnotation()) return; + + final List> children = subtree.getChildren(); + + // When there are no children, 'subtree' is an empty annotation that can be eliminated. + if (children.isEmpty()) { + subtree.drop(); + } + // When there is exactly one child and that child is an 'else' or 'elif' we can simplify that nesting. + else if (children.size() == 1) { + final VariationTreeNode child = children.getFirst(); + + if ((subtree.isIf() || subtree.isElif()) && (child.isElif() || child.isElse())) { + // determine new feaure mapping + Node newFormula = negate(subtree.getFormula()); + if (child.isElif()) { + newFormula = and(newFormula, child.getFormula()); + } + subtree.setFormula(newFormula); + subtree.setLabel(updatedLabel(subtree.getLabel(), newFormula)); + + // simplify tree + child.drop(); + subtree.stealChildrenOf(child); + } + } + } + + @Override + public void transform(VariationTree tree) { + tree.forAllPostorder(EliminateEmptyAlternatives::elim); + } +} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/FeatureExpressionFilter.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/FeatureExpressionFilter.java index ad84421c2..34729fbe5 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/FeatureExpressionFilter.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/FeatureExpressionFilter.java @@ -13,7 +13,7 @@ * For example, it might remove an IF but keep its ELSE branches which is illegal. */ @Deprecated -public record FeatureExpressionFilter(Predicate> isFeatureAnnotation) implements VariationDiffTransformer { +public record FeatureExpressionFilter(Predicate> isFeatureAnnotation) implements Transformer> { @Override public void transform(VariationDiff variationDiff) { final List> illegalNodes = new ArrayList<>(); diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/LabelWithEditClass.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/LabelWithEditClass.java index 8d3fe1446..c0292345b 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/LabelWithEditClass.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/LabelWithEditClass.java @@ -15,8 +15,8 @@ * All other nodes will be labeled by the {@link NodeType#name name of their node type}. * @author Paul Bittner */ -public class LabelWithEditClass implements VariationDiffTransformer { - private final VariationDiffTransformer relabelNodes; +public class LabelWithEditClass implements Transformer> { + private final Transformer> relabelNodes; /** * Creates a new transformation that will use the given catalog of edit classes @@ -39,7 +39,7 @@ public void transform(VariationDiff variationDiff) { } @Override - public List>> getDependencies() { + public List>>> getDependencies() { return relabelNodes.getDependencies(); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/NaiveMovedArtifactDetection.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/NaiveMovedArtifactDetection.java index fd95d0046..128ccb7db 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/NaiveMovedArtifactDetection.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/NaiveMovedArtifactDetection.java @@ -20,7 +20,7 @@ * but for each line in the nodes individually. * @author Paul Bittner */ -public class NaiveMovedArtifactDetection implements VariationDiffTransformer { +public class NaiveMovedArtifactDetection implements Transformer> { @Override public void transform(final VariationDiff variationDiff) { final List, DiffNode>> twins = findArtifactTwins(variationDiff); diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RelabelNodes.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RelabelNodes.java index 2716e32b8..9fe933efb 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RelabelNodes.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RelabelNodes.java @@ -10,7 +10,7 @@ * Transformer that changes the label of each node using a relable function. * @author Paul Bittner */ -public class RelabelNodes implements VariationDiffTransformer { +public class RelabelNodes implements Transformer> { private final Function, L> getLabel; /** diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RelabelRoot.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RelabelRoot.java index ebf161165..47b0a0417 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RelabelRoot.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RelabelRoot.java @@ -7,7 +7,7 @@ * Transformer that relabels the root of a VariationDiff. * @author Paul Bittner */ -public class RelabelRoot implements VariationDiffTransformer { +public class RelabelRoot implements Transformer> { private final L newLabel; /** diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RevertSomeChanges.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RevertSomeChanges.java new file mode 100644 index 000000000..f6ec51d9e --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/RevertSomeChanges.java @@ -0,0 +1,52 @@ +package org.variantsync.diffdetective.variation.diff.transform; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +import org.variantsync.diffdetective.util.Assert; +import org.variantsync.diffdetective.variation.Label; +import org.variantsync.diffdetective.variation.diff.DiffNode; +import org.variantsync.diffdetective.variation.diff.VariationDiff; + +/** + * This transformer reverts some changes in a variation diff. + * The transformation requires a predicate on {@link DiffNode nodes} to identify the changes which should be undone. + * An inserted node will be removed, so that the insertion does not happen. + * A removed node will be made unchanged so that it will not be deleted. + * When a node is made unchanged, also its parent node will be made unchanged if necessary to retain diff consistency. + * @see DiffNode#makeUnchanged() + * @author Paul Bittner + */ +public class RevertSomeChanges implements Transformer> { + private Predicate> isInteresting; + + public RevertSomeChanges(final Predicate> isInteresting) { + Assert.assertNotNull(isInteresting); + this.isInteresting = isInteresting; + } + + @Override + public void transform(VariationDiff d) { + final List> nodesToEliminate = new ArrayList<>(); + final List> toUnchanged = new ArrayList<>(); + d.forAll((DiffNode node) -> { + if (isInteresting.test(node)) { + if (node.isAdd()) { + nodesToEliminate.add(node); + } else if (node.isRem()) { + toUnchanged.add(node); + } + } + }); + + for (DiffNode zombie : nodesToEliminate) { + // We also drop all children. + zombie.drop(); + } + + for (DiffNode n : toUnchanged) { + n.makeUnchanged(); + } + } +} diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/VariationDiffTransformer.java b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/Transformer.java similarity index 51% rename from src/main/java/org/variantsync/diffdetective/variation/diff/transform/VariationDiffTransformer.java rename to src/main/java/org/variantsync/diffdetective/variation/diff/transform/Transformer.java index e300a3917..ba10a2a12 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/transform/VariationDiffTransformer.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/transform/Transformer.java @@ -1,44 +1,41 @@ package org.variantsync.diffdetective.variation.diff.transform; -import org.variantsync.diffdetective.variation.Label; -import org.variantsync.diffdetective.variation.diff.VariationDiff; - import java.util.ArrayList; import java.util.List; /** - * Interface that represents inplace transformations of VariationDiffs. - * A VariationDiffTransformer is intended to alter a given VariationDiff. - * @author Paul Bittner + * Models an operation that changes an object of type T inplace (i.e., the object is altered). + * To model further assumptions on the given elements T (i.e., assumptions that cannot easily be expressed as a type), + * Transformers may have dependencies to other transformers, which should be applied first. */ -public interface VariationDiffTransformer { +public interface Transformer { /** - * Apply a transformation to the given VariationDiff inplace. - * The given tree will be changed. - * @param variationDiff The VariationDiff to transform. + * Apply a transformation to the given Object inplace. + * The object will be changed. + * @param element The T object to transform. */ - void transform(final VariationDiff variationDiff); + void transform(final T element); /** * Returns a list of dependencies to other transformers. * A transformer should only be run, if another transformation with the respective type was run for each type on the dependencies. * @return List of types of which instances should be run before applying this transformation. */ - default List>> getDependencies() { + default List>> getDependencies() { return new ArrayList<>(0); } /** - * Checks that the dependencies of all given VariationDiffTransformers are satisfied when + * Checks that the dependencies of all given transformers are satisfied when * applying the transformers sequentially. * @param transformers The transformers whose dependencies to check. * @throws RuntimeException when a dependency is not met. */ - static void checkDependencies(final List> transformers) { + static void checkDependencies(final List> transformers) { for (int i = transformers.size() - 1; i >= 0; --i) { - final VariationDiffTransformer currentTransformer = transformers.get(i); - final List>> currentDependencies = currentTransformer.getDependencies(); - for (final Class> dependency : currentDependencies) { + final Transformer currentTransformer = transformers.get(i); + final List>> currentDependencies = currentTransformer.getDependencies(); + for (final Class> dependency : currentDependencies) { boolean dependencyMet = false; for (int j = i - 1; j >= 0; --j) { if (dependency.isInstance(transformers.get(j))) { @@ -47,7 +44,7 @@ static void checkDependencies(final List void checkDependencies(final List void apply(final List> transformers, final VariationDiff tree) { + static void apply(final List> transformers, final T element) { checkDependencies(transformers); - for (final VariationDiffTransformer t : transformers) { - t.transform(tree); + for (final Transformer t : transformers) { + t.transform(element); } } + } diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/view/DiffView.java b/src/main/java/org/variantsync/diffdetective/variation/diff/view/DiffView.java index cbeb3d811..073ef9bb3 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/view/DiffView.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/view/DiffView.java @@ -6,6 +6,7 @@ import org.variantsync.diffdetective.experiments.views.Main; import org.variantsync.diffdetective.util.Assert; import org.variantsync.diffdetective.util.CollectionUtils; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.Label; import org.variantsync.diffdetective.variation.diff.*; @@ -72,12 +73,19 @@ public static BiPredicate> computeWhenNode private static VariationDiff naive(final VariationDiff d, final Relevance rho, final String[] projectionViewText) throws IOException, DiffParseException { final VariationDiff view; try { - view = JGitDiff.diff(projectionViewText[0], projectionViewText[1], DiffAlgorithm.SupportedAlgorithm.MYERS, Main.VARIATION_DIFF_PARSE_OPTIONS); + view = JGitDiff.diff( + projectionViewText[0], + projectionViewText[1], + Source.Unknown, // overridden below + Source.Unknown, // overridden below + DiffAlgorithm.SupportedAlgorithm.MYERS, + Main.VARIATION_DIFF_PARSE_OPTIONS + ); } catch (DiffParseException e) { Logger.error("Could not parse diff obtained with query {} at {}", d.getSource(), rho); throw e; } - view.setSource(new ViewSource<>(d, rho)); + view.setSource(new ViewSource(d, rho, "naive")); return view; } @@ -112,11 +120,9 @@ public static VariationDiff naive(final Variat // TODO: Avoid inversion by building the map in the correct way in the first place. final Map, Projection> invCopyMemory = CollectionUtils.invert(copyMemory, HashMap::new); - TreeView.treeInline(treeView.root(), v -> inView.test(t, invCopyMemory.get(v))); + TreeView.treeInline(treeView.getRoot(), v -> inView.test(t, invCopyMemory.get(v))); - final StringBuilder b = new StringBuilder(); - treeView.root().printSourceCode(b); - projectionViewText[i] = b.toString(); + projectionViewText[i] = treeView.unparse(); } return naive(d, rho, projectionViewText); @@ -155,6 +161,7 @@ public static VariationDiff badgood(final VariationDiff // unify final VariationDiff goodDiff = badDiff.toGood(); + goodDiff.setSource(new ViewSource(d, rho, "badgood")); goodDiff.assertConsistency(); return goodDiff; } @@ -263,7 +270,7 @@ record Edge(DiffNode childCopy, DiffNode parentInD, Time // Step 4: Build return value Assert.assertNotNull(rootCopy[0]); - return new VariationDiff<>(rootCopy[0], new ViewSource<>(d, rho)); + return new VariationDiff<>(rootCopy[0], new ViewSource(d, rho, "optimized")); } /** diff --git a/src/main/java/org/variantsync/diffdetective/variation/diff/view/ViewSource.java b/src/main/java/org/variantsync/diffdetective/variation/diff/view/ViewSource.java index 6e1f0fabf..a5f30278d 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/diff/view/ViewSource.java +++ b/src/main/java/org/variantsync/diffdetective/variation/diff/view/ViewSource.java @@ -1,15 +1,34 @@ package org.variantsync.diffdetective.variation.diff.view; -import org.variantsync.diffdetective.variation.Label; -import org.variantsync.diffdetective.variation.diff.VariationDiff; -import org.variantsync.diffdetective.variation.diff.source.VariationDiffSource; +import java.util.List; + +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.tree.view.relevance.Relevance; /** - * A {@link VariationDiffSource} that remembers that a variation diff represents a view on - * another variation diff. - * @param diff The original variation diff on which the variation diff with this source is a view on. + * A {@link Source} that remembers that a variation tree or diff represents a view on another variation + * tree or diff. + * @param target The original variation tree/diff on which the view was created. * @param relevance The relevance predicate that was used to create the view. */ -public record ViewSource(VariationDiff diff, Relevance relevance) implements VariationDiffSource { +public record ViewSource(Source target, Relevance relevance, String method) implements Source { + @Override + public String getSourceExplanation() { + return "view"; + } + + @Override + public List getSources() { + return List.of(relevance, target); + } + + @Override + public List getSourceArguments() { + return List.of(); + } + + @Override + public String toString() { + return functionExplanation(); + } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/VariationNode.java b/src/main/java/org/variantsync/diffdetective/variation/tree/VariationNode.java index d1622423f..d79bb2c0c 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/VariationNode.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/VariationNode.java @@ -282,8 +282,9 @@ public void drop() { * @see removeAllChildren */ public void stealChildrenOf(final T other) { - addChildren(other.getChildren()); + List children = new ArrayList<>(other.getChildren()); other.removeAllChildren(); + addChildren(children); } /** @@ -419,6 +420,17 @@ public void forAllPreorder(Consumer action) { } } + /** + * Traverses all nodes in this subtree in postorder. + */ + public void forAllPostorder(Consumer action) { + for (var child : getChildren()) { + child.forAllPostorder(action); + } + + action.accept(this.upCast()); + } + public void forMeAndMyAncestors(final Consumer action) { action.accept(this.upCast()); final T p = getParent(); @@ -487,26 +499,28 @@ public VariationTreeNode toVariationTree(final Map - *
  • if-chains are nested correctly, - *
  • the root is an {@link NodeType#IF} with the feature mapping {@code "true"}, - *
  • the feature mapping is {@code null} iff {@code isConditionalAnnotation} is {@code false} - * and - *
  • all edges are well-formed (e.g., edges can be inconsistent because edges are - * double-linked). - * - * - *

    Some invariants are not checked. These include - *

      - *
    • There should be no cycles and - *
    • {@link getID} should be unique in the whole variation tree. - *
    - * - * @see Assert#assertTrue - * @throws AssertionError when an inconsistency is detected. - */ + * Checks that this node satisfies some easy to check invariants. + * In particular, this method checks that + *
      + *
    • if-chains are nested correctly, + *
    • the root is an {@link NodeType#IF} with the feature mapping {@code "true"}, + *
    • the feature mapping is {@code null} iff {@code isConditionalAnnotation} is {@code false} + * and + *
    • all edges are well-formed (e.g., edges can be inconsistent because edges are + * double-linked). + *
    + * + *

    Some invariants are not checked. These include + *

      + *
    • There should be no cycles, + *
    • {@link getID} should be unique in the whole variation tree, and + *
    • children are not checked recursively. + *
    + * Use {@link VariationTree#assertConsistency} to check all children recursively. + * + * @see Assert#assertTrue + * @throws AssertionError when an inconsistency is detected. + */ public void assertConsistency() { // ELSE and ELIF nodes have an IF or ELIF as parent. if (isElse() || isElif()) { @@ -537,6 +551,12 @@ public void assertConsistency() { "The root has to have the feature mapping 'true'"); } + // check that there is at most one ELIF/ELSE + Assert.assertTrue( + getChildren().stream().filter(c -> c.isElif() || c.isElse()).count() <= 1, + "There is more than one ELIF/ELSE node." + ); + // check consistency of children lists and edges for (var child : getChildren()) { Assert.assertTrue( @@ -563,19 +583,19 @@ public void assertConsistency() { * *

    This method assumes that all labels of this subtree represent source code lines. */ - public void printSourceCode(final StringBuilder output) { + public void unparse(final StringBuilder output) { for (final String line : getLabel().getLines()) { output.append(line); output.append(StringUtils.LINEBREAK); } for (final var child : getChildren()) { - child.printSourceCode(output); + child.unparse(output); } // Add #endif after macro - if (isIf() && !isRoot()) { - output.append("#endif"); + for (final String line : getLabel().getTrailingLines()) { + output.append(line); output.append(StringUtils.LINEBREAK); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/VariationTree.java b/src/main/java/org/variantsync/diffdetective/variation/tree/VariationTree.java index 36cdff174..85a5f6401 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/VariationTree.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/VariationTree.java @@ -3,22 +3,26 @@ import org.variantsync.diffdetective.datasets.PatchDiffParseOptions; import org.variantsync.diffdetective.diff.result.DiffParseException; import org.variantsync.diffdetective.util.Assert; +import org.variantsync.diffdetective.util.CompositeSource; +import org.variantsync.diffdetective.util.FileSource; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.Label; +import org.variantsync.diffdetective.variation.NodeType; // For Javadoc import org.variantsync.diffdetective.variation.diff.DiffNode; -import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.Projection; +import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser; -import org.variantsync.diffdetective.variation.diff.source.FromVariationTreeSource; -import org.variantsync.diffdetective.variation.tree.source.LocalFileSource; -import org.variantsync.diffdetective.variation.tree.source.VariationTreeSource; import java.io.BufferedReader; import java.io.IOException; +import java.io.StringReader; +import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; @@ -30,24 +34,22 @@ /** * Representation of a concrete variation tree with source information. * - * @param root the root of the variation tree - * @param source from which source code the variation tree was obtained * @param The type of label stored in this tree. * * @see VariationTreeNode * @author Benjamin Moosherr */ -public record VariationTree( - VariationTreeNode root, - VariationTreeSource source -) { - /** Creates a {@code VariationTree} with the given root and an unknown source. */ +public class VariationTree implements Source { + private final VariationTreeNode root; + private Source source; + + /** Creates a {@code VariationTree} with the given root and an {@link Source#Unknown unknown} source. */ public VariationTree(VariationTreeNode root) { - this(root, VariationTreeSource.Unknown); + this(root, Source.Unknown); } /** Creates a {@code VariationTree} with the given root and source. */ - public VariationTree(VariationTreeNode root, VariationTreeSource source) { + public VariationTree(VariationTreeNode root, Source source) { this.root = root; this.source = source; @@ -63,7 +65,7 @@ public static VariationTree fromFile(final Path path) throws IOE } /** - * Same as {@link #fromFile(BufferedReader, VariationTreeSource, VariationDiffParseOptions)} + * Same as {@link #fromFile(BufferedReader, Source, VariationDiffParseOptions)} * but registers {@code path} as source. */ public static VariationTree fromFile( @@ -73,8 +75,8 @@ public static VariationTree fromFile( try (BufferedReader file = Files.newBufferedReader(path)) { return fromFile( file, - new LocalFileSource(path), - parseOptions + new FileSource(path), + parseOptions ); } } @@ -83,6 +85,7 @@ public static VariationTree fromFile( * Parses a {@code VariationTree} from source code with C preprocessor annotations. * * @param input the source code to be parsed + * @param source from where the variation tree was obtained * @param parseOptions {@link PatchDiffParseOptions} for the parsing process. * @return a new {@code VariationTree} representing {@code input} * @throws IOException if {@code input} throws {@code IOException} @@ -90,24 +93,45 @@ public static VariationTree fromFile( */ public static VariationTree fromFile( final BufferedReader input, - final VariationTreeSource source, + final Source source, final VariationDiffParseOptions parseOptions ) throws IOException, DiffParseException { - VariationTreeNode tree = VariationDiffParser - .createVariationTree(input, parseOptions) - .getRoot() + VariationDiff diff = + VariationDiffParser.createVariationTree(input, source, parseOptions); + + return new VariationTree<>( // Arbitrarily choose the BEFORE projection as both should be equal. - .projection(BEFORE) - .toVariationTree(); + diff.getRoot().projection(BEFORE).toVariationTree(), + diff.getSource()); + } - return new VariationTree<>(tree, source); + /** + * Parses a {@code VariationTree} from source code with C preprocessor annotations. + * + * @param input the source code to be parsed + * @param source from where the variation tree was obtained + * @param parseOptions {@link PatchDiffParseOptions} for the parsing process. + * @return a new {@code VariationTree} representing {@code input} + * @throws DiffParseException if some preprocessor annotations can't be parsed + */ + public static VariationTree fromText( + final String input, + final Source source, + final VariationDiffParseOptions parseOptions + ) throws DiffParseException { + try { + return fromFile(new BufferedReader(new StringReader(input)), source, parseOptions); + } catch (IOException e) { + // Only thrown on programming errors because StringReader doesn't do IO. + throw new UncheckedIOException(e); + } } - public static VariationTree fromProjection(final Projection projection, final VariationTreeSource source) { + public static VariationTree fromProjection(final Projection projection, final Source source) { return fromVariationNode(projection, source); } - public static , L extends Label> VariationTree fromVariationNode(final VariationNode node, final VariationTreeSource source) { + public static , L extends Label> VariationTree fromVariationNode(final VariationNode node, final Source source) { return new VariationTree<>( node.toVariationTree(), source @@ -116,8 +140,8 @@ public static , L extends Label> VariationTree public VariationDiff toVariationDiff(final Function, DiffNode> nodeConverter) { return new VariationDiff<>( - DiffNode.unchanged(nodeConverter, root()), - new FromVariationTreeSource(source()) + DiffNode.unchanged(nodeConverter, root), + new CompositeSource("VariationTree.toVariationDiff", source) ); } @@ -126,7 +150,7 @@ public VariationDiff toCompletelyUnchangedVariationDiff() { } /** - * Invokes the given callback for each node in this Variation Tree in depth-first order. + * Invokes the given callback for each node in this Variation Tree in pre-order. * @param action callback * @return this */ @@ -135,6 +159,16 @@ public VariationTree forAllPreorder(final Consumer> acti return this; } + /** + * Invokes the given callback for each node in this Variation Tree in post-order. + * @param action callback + * @return this + */ + public VariationTree forAllPostorder(final Consumer> action) { + root.forAllPostorder(action); + return this; + } + /** * Checks whether any node in this tree satisfies the given condition. * The condition might not be invoked on every node in case a node is found. @@ -142,7 +176,7 @@ public VariationTree forAllPreorder(final Consumer> acti * @return True iff the given condition returns true for at least one node in this tree. */ public boolean anyMatch(final Predicate> condition) { - return root().anyMatch(condition); + return root.anyMatch(condition); } /** @@ -182,8 +216,55 @@ public VariationTree deepCopy(final Map, VariationTreeNo return new VariationTree<>(root.deepCopy(oldToNew), this.source); } + public String unparse() { + var result = new StringBuilder(); + root.unparse(result); + return result.toString(); + } + + /** + * Checks whether this {@link VariationTree} is consistent. + * Throws an error if this {@link VariationTree} is inconsistent (e.g., if there are multiple + * {@link NodeType#ELSE} nodes). Has no side-effects otherwise. + * + * @see VariationNode#assertConsistency + */ + public void assertConsistency() { + forAllPreorder(VariationTreeNode::assertConsistency); + } + + public VariationTreeNode getRoot() { + return root; + } + + /** + * Sets the source of this VariationTree. + * @see Source + */ + public void setSource(final Source source) { + this.source = source; + } + + /** + * Returns the source of this VariationTree (i.e., the data this VariationTree was created from). + * @see Source + */ + public Source getSource() { + return source; + } + + @Override + public List getSources() { + return List.of(source); + } + + @Override + public String getSourceExplanation() { + return "VariationTree"; + } + @Override public String toString() { - return "variation tree from " + source; + return functionExplanation(); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/VariationTreeNode.java b/src/main/java/org/variantsync/diffdetective/variation/tree/VariationTreeNode.java index 0609a8fd1..50ac1bae0 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/VariationTreeNode.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/VariationTreeNode.java @@ -33,8 +33,8 @@ * *

    This class contains references to all of its children and its parent so all connected nodes of * a variation tree can be reached through each node of the variation tree. Nevertheless, most of - * the time only node itself or its subtree (the reflexive hull of {@link getChildren}) is meant - * when when referencing a {@code VariationTreeNode}. Use {@link VariationTree} to unambiguously + * the time only the node itself or its subtree (the reflexive hull of {@link getChildren}) is referred to + * when referencing a {@code VariationTreeNode}. Use {@link VariationTree} to unambiguously * refer to a whole variation tree. * *

    If possible, algorithms should be using {@link VariationNode} instead of this concrete @@ -226,6 +226,22 @@ public void removeAllChildren() { childOrder.clear(); } + /** + * Sets the formula that is stored in this node. + * The formula should not be not {@code null} for + * {@link NodeType#isConditionalAnnotation mapping nodes with annotations} and should be {@code null} + * otherwise ({@link NodeType#ARTIFACT}, {@link NodeType#ELSE}). + */ + public void setFormula(Node formula) { + if (isConditionalAnnotation()) { + Assert.assertNotNull(formula); + } else { + Assert.assertNull(formula); + } + + this.featureMapping = formula; + } + @Override public Node getFormula() { return featureMapping; diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/source/GitSource.java b/src/main/java/org/variantsync/diffdetective/variation/tree/source/GitSource.java index d79b70eec..9722d4418 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/source/GitSource.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/source/GitSource.java @@ -1,7 +1,10 @@ package org.variantsync.diffdetective.variation.tree.source; -import java.net.URL; import java.nio.file.Path; +import java.util.List; + +import org.variantsync.diffdetective.datasets.Repository; +import org.variantsync.diffdetective.util.Source; /** * A file at a specific commit in a Git repository. @@ -9,19 +12,29 @@ *

    The parameters of this record should be suitably chosen, so that the following commands can be * executed in a shell to obtain the referenced source code: * - * git clone "$repository" repository + * git clone "${repository.getRemoteURI()}" repository * cd repository * git switch -d "$commitHash" * cat "$path" * */ public record GitSource( - URL repository, + Repository repository, String commitHash, Path path -) implements VariationTreeSource { +) implements Source { @Override public String toString() { return path.toString() + " at " + commitHash + " of " + repository; } + + @Override + public String getSourceExplanation() { + return "GitCommit"; + } + + @Override + public List getSourceArguments() { + return List.of(repository, commitHash, path); + } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/source/LocalFileSource.java b/src/main/java/org/variantsync/diffdetective/variation/tree/source/LocalFileSource.java deleted file mode 100644 index c9c60fbb9..000000000 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/source/LocalFileSource.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.variantsync.diffdetective.variation.tree.source; - -import java.nio.file.Path; - -/** - * A reference to a file with path {@code path} in the local file system. - */ -public record LocalFileSource(Path path) implements VariationTreeSource { - @Override - public String toString() { - return "file://" + path.toString(); - } -} diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/source/VariationTreeSource.java b/src/main/java/org/variantsync/diffdetective/variation/tree/source/VariationTreeSource.java deleted file mode 100644 index 448ac1511..000000000 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/source/VariationTreeSource.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.variantsync.diffdetective.variation.tree.source; - -/** - * A reference to the source of the variation tree. - */ -public interface VariationTreeSource { - /** - * The source of the variation tree is unknown. - * Should be avoided if possible. - */ - VariationTreeSource Unknown = new VariationTreeSource() { - @Override - public String toString() { - return "unknown"; - } - }; - - String toString(); -} diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/view/TreeView.java b/src/main/java/org/variantsync/diffdetective/variation/tree/view/TreeView.java index 5d8cb96c7..f88330218 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/view/TreeView.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/view/TreeView.java @@ -5,6 +5,7 @@ import org.variantsync.diffdetective.variation.tree.VariationTree; import org.variantsync.diffdetective.variation.tree.VariationTreeNode; import org.variantsync.diffdetective.variation.tree.view.relevance.Relevance; +import org.variantsync.diffdetective.variation.diff.view.ViewSource; import java.util.ArrayList; import java.util.HashSet; @@ -54,22 +55,23 @@ private TreeView() {} */ public static void treeInline(final VariationTree t, final Relevance r) { final Set> interestingNodes = new HashSet<>(); - r.computeViewNodes(t.root(), interestingNodes::add); - treeInline(t.root(), interestingNodes::contains); + r.computeViewNodes(t.getRoot(), interestingNodes::add); + treeInline(t.getRoot(), interestingNodes::contains); + t.setSource(new ViewSource(t.getSource(), r, "view_tree")); } /** * Creates a view on the given variation tree as described by the given relevance predicate. * This function is side-effect free. - * Thre given variation tree and relevance will not be altered. + * The given variation tree and relevance will not be altered. * This function corresponds to Equation 4 in our SPLC'23 paper - Views on Edits to Variational Software. * @param t The variation tree to generate a view on. * @param r A relevance predicate that determines for each node in the * tree whether it should be contained in the view or should be excluded. * @return A variation tree that represents a view on the given variation tree t. */ - public static VariationTree tree(final VariationTree t, final Relevance r) { - final VariationTree copy = t.deepCopy(); + public static VariationTree tree(final VariationTree t, final Relevance r) { + final VariationTree copy = t.deepCopy(); treeInline(copy, r); return copy; } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Configure.java b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Configure.java index 88449ba4b..247c87859 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Configure.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Configure.java @@ -1,26 +1,32 @@ package org.variantsync.diffdetective.variation.tree.view.relevance; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.Consumer; + import org.prop4j.Node; import org.prop4j.NodeWriter; -import org.variantsync.diffdetective.analysis.logic.SAT; +import org.variantsync.diffdetective.util.Assert; import org.variantsync.diffdetective.util.fide.FixTrueFalse; +import org.variantsync.diffdetective.util.fide.FixTrueFalse.Formula; +import org.variantsync.diffdetective.variation.NodeType; import org.variantsync.diffdetective.variation.tree.VariationNode; - -import java.util.function.Consumer; +import org.variantsync.diffdetective.variation.tree.view.relevance.spec.ConfigureSpec; /** * Relevance predicate that generates (partial) variants from variation trees. * This relevance predicate is the implementation of Equation 5 in our SPLC'23 paper. */ public class Configure implements Relevance { - private final FixTrueFalse.Formula configuration; + private final Formula configuration; /** * Same as {@link Configure#Configure(Node)} but with a formula that is witnessed to * not contain true or false constants not at the root. * Workaround for FeatureIDE bug FeatureIDE Issue 1333. */ - public Configure(final FixTrueFalse.Formula configuration) { + public Configure(final Formula configuration) { this.configuration = configuration; } @@ -35,35 +41,111 @@ public Configure(final Node configuration) { this(FixTrueFalse.EliminateTrueAndFalse(configuration)); } + /** + * Create a configuration from an assignment of variable names to boolean values. + * The given assignment may be complete or partial. + * Internally, a big conjunction of literals is created: + *
    +     *           ⋀ f              ∧          ⋀ ¬ f
    +     *   (f, true) ∈ assignment    (f, false) ∈ assignment
    +     * 
    + * + * As an example, suppose the map contains the following entries: + *
    +     *   A ↦ true
    +     *   B ↦ false
    +     *   C ↦ true
    +     * 
    + * then we construct a formula A ∧ (¬ B) ∧ C. + */ + public Configure(final Map assignment) { + // We use commutativity of ∧ to iterate the map only once instead of twice as shown in the formula above. + final Formula[] fixedFeatures = new Formula[assignment.size()]; + int i = 0; + for (Entry entry : assignment.entrySet()) { + fixedFeatures[i] = Formula.var(entry.getKey()); + if (!entry.getValue()) { + fixedFeatures[i] = Formula.not(fixedFeatures[i]); + } + + ++i; + } + + this.configuration = Formula.and(fixedFeatures); + } + @Override public boolean test(VariationNode v) { - return SAT.isSatisfiable( - FixTrueFalse.Formula.and( - configuration, - FixTrueFalse.EliminateTrueAndFalse(v.getPresenceCondition()) - ) - ); + return ConfigureSpec.test(configuration, v); + } + + private > void computeViewNodes(List vs, Consumer markRelevant) { + for (final TreeNode c : vs) { + computeViewNodes(c, markRelevant); + } } @Override public > void computeViewNodes(TreeNode v, Consumer markRelevant) { - markRelevant.accept(v); + // The implementation of this method must be semantically equivalent to the default implementation Relevance.super.computeViewNodes(v, markRelevant); + // The implementation of this method is supposed to be optimized to avoid redundant SAT calls when possible. + // This requirement is modelled explicitly in terms of the ConfigureSpec class. + + // If the child is an artifact, it has the same presence condition as v does, so it is also included in the view. + // The root must be in any view to ensure consistency. + if (v.isArtifact() || v.isRoot()) { + markRelevant.accept(v); + computeViewNodes(v.getChildren(), markRelevant); + } else { + computeViewNodesOfElifChain(v, markRelevant); + } + } - for (final TreeNode c : v.getChildren()) { - // If the child is an artifact it has the same presence condition as we do, so it is also included in the view. - if (c.isArtifact() || test(c)) { - computeViewNodes(c, markRelevant); + /** + * @return true if the given node was marked relevant + */ + private > boolean computeViewNodesOfElifChain(TreeNode v, Consumer markRelevant) { + Assert.assertTrue(v.isAnnotation()); + + if (test(v)) { + markRelevant.accept(v); + computeViewNodes(v.getChildren(), markRelevant); + return true; + } else { + // If a partial configuration excludes the node v (i.e, test(v) == false), + // then any ELIF or ELSE branches might still be included. + for (final TreeNode c : v.getChildren()) { + NodeType ct = c.getNodeType(); + + // We can skip all children that are not ELSE or ELIF nodes because these are excluded because v is exluded. + // If our node v was deemed irrelevant and it has an ELSE node c, that ELSE node c must be relevant. + if (ct == NodeType.ELSE) { + markRelevant.accept(v); + markRelevant.accept(c); + computeViewNodes(c.getChildren(), markRelevant); + return true; + } + + // An ELIF might hold any formula which we have to test. + // We handle ELIF nodes recursively because ELIFs might be nested. + // If at least one branch of the ELIF chain is included, we must include also v in the view to retain consistency of the tree. + if (ct == NodeType.ELIF && computeViewNodesOfElifChain(c, markRelevant)) { + markRelevant.accept(v); + return true; + } } } + + return false; } @Override - public String parametersToString() { - return configuration.get().toString(NodeWriter.logicalSymbols); + public List getSourceArguments() { + return List.of(configuration.get().toString(NodeWriter.logicalSymbols)); } @Override - public String getFunctionName() { + public String getSourceExplanation() { return "configure"; } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Relevance.java b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Relevance.java index 8bc06b5e6..6815f8cbc 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Relevance.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Relevance.java @@ -1,5 +1,6 @@ package org.variantsync.diffdetective.variation.tree.view.relevance; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.tree.VariationNode; import java.util.function.Consumer; @@ -13,17 +14,7 @@ * Moreover, this interface provides methods to access a predicates metadata for debugging * and (de-)serialization. */ -public interface Relevance extends Predicate> { - /** - * @return The name of this relevance predicate's type. - */ - String getFunctionName(); - - /** - * @return The parameters set for this particular relevance predicate, as a comma-separated string (without braces). - */ - String parametersToString(); - +public interface Relevance extends Predicate>, Source { /** * Delegates to {@link Relevance#computeViewNodesCheckAll(Relevance, VariationNode, Consumer)} with this relevance * as the first parameter. @@ -37,6 +28,7 @@ public interface Relevance extends Predicate> { * In particular, this function checks each node in the given tree v on relevance. * For each node that is deemed relevant by the given relevance predicate rho, that node and all its ancestors are * marked as relevant by invoking the given callback markRelevant. + * The callback may be invoked multiple times on the same node. * This function tests the relevance predicate on all nodes separately and performs no optimizations. * @param rho The relevance predicate to test on all nodes. * @param v The root node the tree to test for relevance. @@ -57,9 +49,9 @@ public interface Relevance extends Predicate> { * Default implementation for {@link Object#toString()} that can be reused by implementing classes. * The produced string will look like a function call. * @param relevance The relevance predicate to turn into a string. - * @return {@link Relevance#getFunctionName()} + "(" + {@link Relevance#parametersToString()} + ")" + * @return {@link #getSourceArguments()} + "(" + {@link #getSourceExplanation()} + ")" */ static String toString(Relevance relevance) { - return relevance.getFunctionName() + "(" + relevance.parametersToString() + ")"; + return relevance.shallowExplanation(); } } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Search.java b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Search.java index 0f557e7c2..14448078a 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Search.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Search.java @@ -1,5 +1,7 @@ package org.variantsync.diffdetective.variation.tree.view.relevance; +import java.util.List; + import org.variantsync.diffdetective.variation.tree.VariationNode; /** @@ -17,12 +19,12 @@ public boolean test(VariationNode v) { } @Override - public String parametersToString() { - return artifact(); + public List getSourceArguments() { + return List.of(artifact()); } @Override - public String getFunctionName() { + public String getSourceExplanation() { return "is"; } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Trace.java b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Trace.java index d559605a4..ed0d33c35 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Trace.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/Trace.java @@ -1,5 +1,7 @@ package org.variantsync.diffdetective.variation.tree.view.relevance; +import java.util.List; + import org.variantsync.diffdetective.variation.tree.VariationNode; /** @@ -15,12 +17,12 @@ public boolean test(VariationNode v) { } @Override - public String parametersToString() { - return featureName(); + public List getSourceArguments() { + return List.of(featureName()); } @Override - public String getFunctionName() { + public String getSourceExplanation() { return "traceall"; } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/TraceSup.java b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/TraceSup.java index d990256c1..bae357331 100644 --- a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/TraceSup.java +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/TraceSup.java @@ -1,5 +1,7 @@ package org.variantsync.diffdetective.variation.tree.view.relevance; +import java.util.List; + import org.prop4j.Node; import org.prop4j.NodeWriter; import org.variantsync.diffdetective.analysis.logic.SAT; @@ -16,12 +18,12 @@ public boolean test(VariationNode variationNode) { } @Override - public String parametersToString() { - return configuration.toString(NodeWriter.logicalSymbols); + public List getSourceArguments() { + return List.of(configuration.toString(NodeWriter.logicalSymbols)); } @Override - public String getFunctionName() { + public String getSourceExplanation() { return "traceyes"; } diff --git a/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/spec/ConfigureSpec.java b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/spec/ConfigureSpec.java new file mode 100644 index 000000000..c05650686 --- /dev/null +++ b/src/main/java/org/variantsync/diffdetective/variation/tree/view/relevance/spec/ConfigureSpec.java @@ -0,0 +1,59 @@ +package org.variantsync.diffdetective.variation.tree.view.relevance.spec; + +import java.util.List; + +import org.prop4j.Node; +import org.prop4j.NodeWriter; +import org.variantsync.diffdetective.analysis.logic.SAT; +import org.variantsync.diffdetective.util.fide.FixTrueFalse; +import org.variantsync.diffdetective.util.fide.FixTrueFalse.Formula; +import org.variantsync.diffdetective.variation.tree.VariationNode; +import org.variantsync.diffdetective.variation.tree.view.relevance.Relevance; + +/** + * This class serves as a specification for {@link org.variantsync.diffdetective.variation.tree.view.relevance.Configure}. + * Both classes must act semantically equivalent as a {@link Relevance} predicate. + * Whereas Configure is an implementation optimized to avoid SAT calls where necessary, the implementation in ConfigureSpec + * is kept simple by design to remain verifiable. + * ConfigureSpec tests a partial configuration against a variation tree or diff by checking each node individually. + * To this end ConfigureSpec uses the default, naive implementations of {@link Relevance} instead of providing + * optimized implementations for tree traversal as Configure does. + * + * This class is not intended for production use and rather is supposed to be used in tests. + * + * @author Paul Bittner + */ +public record ConfigureSpec(Formula config) implements Relevance { + public static boolean test(Formula formula, VariationNode v) { + return SAT.isSatisfiable( + Formula.and( + formula, + FixTrueFalse.EliminateTrueAndFalse(v.getPresenceCondition()) + ) + ); + } + + public ConfigureSpec(final Node configuration) { + this(FixTrueFalse.EliminateTrueAndFalse(configuration)); + } + + @Override + public boolean test(VariationNode t) { + return test(config, t); + } + + @Override + public List getSourceArguments() { + return List.of(config.get().toString(NodeWriter.logicalSymbols)); + } + + @Override + public String getSourceExplanation() { + return "configure_spec"; + } + + @Override + public String toString() { + return Relevance.toString(this); + } +} diff --git a/src/test/java/BadVDiffTest.java b/src/test/java/BadVDiffTest.java index 3e7f4f7a5..34892f21a 100644 --- a/src/test/java/BadVDiffTest.java +++ b/src/test/java/BadVDiffTest.java @@ -1,4 +1,5 @@ import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.tinylog.Logger; @@ -8,6 +9,12 @@ import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.bad.BadVDiff; import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; +import org.variantsync.diffdetective.variation.diff.serialize.GraphFormat; +import org.variantsync.diffdetective.variation.diff.serialize.LineGraphImport; +import org.variantsync.diffdetective.variation.diff.serialize.LineGraphImportOptions; +import org.variantsync.diffdetective.variation.diff.serialize.edgeformat.ChildOrderEdgeFormat; +import org.variantsync.diffdetective.variation.diff.serialize.nodeformat.FullNodeFormat; +import org.variantsync.diffdetective.variation.diff.serialize.treeformat.IndexedTreeFormat; import java.io.IOException; import java.nio.file.Path; @@ -39,4 +46,21 @@ public void toGood_after_fromGood_idempotency(String filename) throws IOExceptio Assertions.assertTrue(initialVDiff.isSameAs(goodDiff)); } + + @Test + public void childOrderIsPreserved() throws IOException { + final Path fileGraphFile = resDir.resolve("childOrder.lg"); + final var importOptions = new LineGraphImportOptions( + GraphFormat.VARIATION_DIFF, + new IndexedTreeFormat(), + new FullNodeFormat(), + new ChildOrderEdgeFormat<>() + ); + + final VariationDiff initialVDiff = LineGraphImport.fromFile(fileGraphFile, importOptions).get(0); + final var badDiff = BadVDiff.fromGood(initialVDiff); + final var goodDiff = badDiff.toGood(); + + Assertions.assertTrue(initialVDiff.isSameAs(goodDiff)); + } } diff --git a/src/test/java/FeatureNamesTest.java b/src/test/java/FeatureNamesTest.java new file mode 100644 index 000000000..afd0943cf --- /dev/null +++ b/src/test/java/FeatureNamesTest.java @@ -0,0 +1,56 @@ +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.LinkedHashSet; +import java.util.List; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.Label; +import org.variantsync.diffdetective.variation.diff.VariationDiff; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; + +/** + * Test for {@link VariationDiff#computeAllFeatureNames()}. + */ +public class FeatureNamesTest { + private final static Path + diffsDir = Constants.RESOURCE_DIR.resolve("diffs"), + pctestDir = Constants.RESOURCE_DIR.resolve("pctest"), + ourDir = Constants.RESOURCE_DIR.resolve("featurenames"), + collapseDir = diffsDir.resolve("collapse"), + moveDir = diffsDir.resolve("move"); + + public record TestCase(String origin, VariationDiff diff, LinkedHashSet features) { + public static TestCase fromFile(Path p, String... features) throws IOException, DiffParseException { + return new TestCase<>( + p.toString(), + VariationDiff.fromFile(p, VariationDiffParseOptions.Default), + new LinkedHashSet(List.of(features)) + ); + } + }; + + private static List> diffFeatureNameTestCases() throws IOException, DiffParseException { + return List.of( + TestCase.fromFile(collapseDir.resolve("elif.txt"), "A", "B", "C", "D", "E"), + TestCase.fromFile(collapseDir.resolve("simple.txt"), "A", "B", "C"), + TestCase.fromFile(moveDir.resolve("simple.txt"), "X", "Y"), + TestCase.fromFile(pctestDir.resolve("a.diff"), "A", "D", "E", "B", "C"), + TestCase.fromFile(pctestDir.resolve("elif.diff"), "A", "B", "C", "D"), + TestCase.fromFile(pctestDir.resolve("else.diff"), "A", "C", "B"), + TestCase.fromFile(ourDir.resolve("empty.diff")), + TestCase.fromFile(ourDir.resolve("a.diff"), "FIRST", "SECOND"), + TestCase.fromFile(ourDir.resolve("b.diff"), "A") + ); + } + + @ParameterizedTest + @MethodSource("diffFeatureNameTestCases") + public void testComputeAllFeatureNames(TestCase testCase) { + assertEquals(testCase.features(), testCase.diff().computeAllFeatureNames(), testCase.origin()); + } +} diff --git a/src/test/java/JPPParserTest.java b/src/test/java/JPPParserTest.java index a2ac2dc8f..b73ec7ff3 100644 --- a/src/test/java/JPPParserTest.java +++ b/src/test/java/JPPParserTest.java @@ -7,6 +7,7 @@ import org.variantsync.diffdetective.feature.Annotation; import org.variantsync.diffdetective.feature.AnnotationType; import org.variantsync.diffdetective.feature.jpp.JPPAnnotationParser; +import org.variantsync.diffdetective.util.FileSource; import org.variantsync.diffdetective.util.IO; import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.diff.VariationDiff; @@ -132,6 +133,7 @@ public void fullDiffTestCase(JPPParserTest.TestCase testCase) throws try (var inputFile = Files.newBufferedReader(testCase.input)) { variationDiff = VariationDiffParser.createVariationDiff( inputFile, + new FileSource(testCase.input), new VariationDiffParseOptions( false, false diff --git a/src/test/java/LineGraphTest.java b/src/test/java/LineGraphTest.java index 2c79e3dbd..c42704ea8 100644 --- a/src/test/java/LineGraphTest.java +++ b/src/test/java/LineGraphTest.java @@ -1,24 +1,32 @@ import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.function.FailableConsumer; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.diff.text.DiffLineNumber; +import org.variantsync.diffdetective.util.IO; import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.diff.DiffNode; +import org.variantsync.diffdetective.variation.diff.DiffType; +import org.variantsync.diffdetective.variation.diff.Time; import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.serialize.*; import org.variantsync.diffdetective.variation.diff.serialize.edgeformat.DefaultEdgeLabelFormat; import org.variantsync.diffdetective.variation.diff.serialize.nodeformat.LabelOnlyDiffNodeFormat; import org.variantsync.diffdetective.variation.diff.serialize.treeformat.CommitDiffVariationDiffLabelFormat; -import org.variantsync.diffdetective.util.IO; - -import static org.junit.jupiter.api.Assertions.fail; +import org.variantsync.diffdetective.variation.diff.source.CommitDiffVariationDiffSource; +import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; import java.util.stream.Stream; +import static org.junit.jupiter.api.Assertions.fail; + /** * For testing the import of a line graph. */ @@ -34,7 +42,9 @@ public class LineGraphTest { ); public static Stream testCases() throws IOException { - return Files.list(Paths.get("src/test/resources/line_graph")); + return Files + .list(Constants.RESOURCE_DIR.resolve("line_graph")) + .filter(file -> file.getFileName().toString().endsWith(".lg")); } /** @@ -49,22 +59,26 @@ public void idempotentReadWrite(Path testFile) throws IOException { } assertConsistencyForAll(variationDiffs); - Path actualPath = testFile.getParent().resolve(testFile.getFileName().toString() + ".actual"); - try (var output = IO.newBufferedOutputStream(actualPath)) { - LineGraphExport.toLineGraphFormat(variationDiffs, EXPORT_OPTIONS, output); - } + assertEqualsFile(testFile, output -> LineGraphExport.toLineGraphFormat(variationDiffs, EXPORT_OPTIONS, output)); + } - try ( - var expectedFile = Files.newBufferedReader(testFile); - var actualFile = Files.newBufferedReader(actualPath); - ) { - if (!IOUtils.contentEqualsIgnoreEOL(expectedFile, actualFile)) { - fail("The file " + testFile + " couldn't be exported or imported without modifications"); - } else { - // Only keep output file on errors - Files.delete(actualPath); - } - } + @Test + public void testChildOrder() throws IOException, DiffParseException { + Path expectedPath = Constants.RESOURCE_DIR.resolve("line_graph").resolve("childOrder.lg"); + + // Note that this variation diff doesn't have a line diff representation because it + // represents a move (it could be parseable using a tree differ). + var root = DiffNode.createRoot(new DiffLinesLabel()); + var A = DiffNode.createArtifact(DiffType.NON, new DiffLineNumber(1, 1, 2), new DiffLineNumber(1, 1, 2), new DiffLinesLabel(List.of(new DiffLinesLabel.Line("A", new DiffLineNumber(1, DiffLineNumber.InvalidLineNumber, 2))))); + var B = DiffNode.createArtifact(DiffType.NON, new DiffLineNumber(2, 2, 1), new DiffLineNumber(2, 2, 1), new DiffLinesLabel(List.of(new DiffLinesLabel.Line("B", new DiffLineNumber(2, DiffLineNumber.InvalidLineNumber, 1))))); + root.addChild(A, Time.BEFORE); + root.addChild(B, Time.BEFORE); + root.addChild(B, Time.AFTER); + root.addChild(A, Time.AFTER); + + final var variationDiff = new VariationDiff(root, new CommitDiffVariationDiffSource(Path.of("fileName"), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); + + assertEqualsFile(expectedPath, output -> LineGraphExport.toLineGraphFormat(List.of(variationDiff), EXPORT_OPTIONS, output)); } /** @@ -78,4 +92,23 @@ private static void assertConsistencyForAll(final List actualOutput) throws IOException { + Path actualPath = expectedPath.getParent().resolve(expectedPath.getFileName().toString() + ".actual"); + try (var output = IO.newBufferedOutputStream(actualPath)) { + actualOutput.accept(output); + } + + try ( + var expectedFile = Files.newBufferedReader(expectedPath); + var actualFile = Files.newBufferedReader(actualPath); + ) { + if (!IOUtils.contentEqualsIgnoreEOL(expectedFile, actualFile)) { + fail("Expected the content of " + expectedPath + " but got the content of " + actualPath); + } else { + // Only keep output file on errors + Files.delete(actualPath); + } + } + } } diff --git a/src/test/java/ShowTest.java b/src/test/java/ShowTest.java new file mode 100644 index 000000000..004a3d1c0 --- /dev/null +++ b/src/test/java/ShowTest.java @@ -0,0 +1,25 @@ +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.diff.VariationDiff; +import org.variantsync.diffdetective.variation.diff.bad.BadVDiff; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; + +import org.variantsync.diffdetective.show.Show; +import org.variantsync.diffdetective.show.engine.GameEngine; + +import java.io.IOException; +import java.nio.file.Path; + +public class ShowTest { + @Disabled("GUI test, needs to be run manually") + @Test + public void toGood_after_fromGood_idempotency() throws IOException, DiffParseException { + final Path testfile = Constants.RESOURCE_DIR.resolve("badvdiff").resolve("1.diff"); + final VariationDiff vdiff = VariationDiff.fromFile(testfile, new VariationDiffParseOptions(false, false)); + final BadVDiff badDiff = BadVDiff.fromGood(vdiff); + + GameEngine.showAndAwaitAll(Show.baddiff(badDiff)); + } +} diff --git a/src/test/java/TreeDiffingTest.java b/src/test/java/TreeDiffingTest.java index c4c0dad7f..24d9130e9 100644 --- a/src/test/java/TreeDiffingTest.java +++ b/src/test/java/TreeDiffingTest.java @@ -1,16 +1,18 @@ import com.github.gumtreediff.matchers.Matcher; import com.github.gumtreediff.matchers.Matchers; import org.apache.commons.io.IOUtils; +import org.eclipse.jgit.diff.DiffAlgorithm; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.variantsync.diffdetective.diff.result.DiffParseException; -import org.variantsync.diffdetective.feature.cpp.CPPAnnotationParser; +import org.variantsync.diffdetective.util.FileSource; import org.variantsync.diffdetective.util.IO; +import org.variantsync.diffdetective.util.Source; import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.diff.DiffNode; import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.construction.GumTreeDiff; import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; -import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser; import org.variantsync.diffdetective.variation.diff.serialize.Format; import org.variantsync.diffdetective.variation.diff.serialize.LineGraphExporter; import org.variantsync.diffdetective.variation.diff.serialize.TikzExporter; @@ -18,7 +20,6 @@ import org.variantsync.diffdetective.variation.diff.serialize.edgeformat.DefaultEdgeLabelFormat; import org.variantsync.diffdetective.variation.diff.serialize.nodeformat.FullNodeFormat; import org.variantsync.diffdetective.variation.tree.VariationTree; -import org.variantsync.diffdetective.variation.tree.source.LocalFileSource; import java.io.IOException; import java.nio.file.Files; @@ -27,13 +28,12 @@ import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.fail; -import static org.variantsync.diffdetective.variation.diff.Time.BEFORE; public class TreeDiffingTest { private final static Path testDir = Constants.RESOURCE_DIR.resolve("tree-diffing"); private static Pattern expectedFileNameRegex = Pattern.compile("([^_]+)_([^_]+)_expected.lg"); - private static record TestCase(String basename, String matcherName, Matcher matcher) { + private static record TestCase(String expectedDir, String basename, String matcherName, Matcher matcher) { public Path beforeEdit() { return testDir.resolve(String.format("%s.before", basename())); } @@ -43,21 +43,21 @@ public Path afterEdit() { } public Path actual() { - return testDir.resolve(String.format("%s_%s_actual.lg", basename(), matcherName())); + return testDir.resolve(expectedDir).resolve(String.format("%s_%s_actual.lg", basename(), matcherName())); } public Path expected() { - return testDir.resolve(String.format("%s_%s_expected.lg", basename(), matcherName())); + return testDir.resolve(expectedDir).resolve(String.format("%s_%s_expected.lg", basename(), matcherName())); } public Path visualisation() { - return testDir.resolve("tex").resolve(String.format("%s_%s.tex", basename(), matcherName())); + return testDir.resolve(expectedDir).resolve("tex").resolve(String.format("%s_%s.tex", basename(), matcherName())); } } - private static Stream testCases() throws IOException { + private static Stream testCases(String expectedDir) throws IOException { return Files - .list(testDir) + .list(testDir.resolve(expectedDir)) .mapMulti(((path, result) -> { String filename = path.getFileName().toString(); var filenameMatcher = expectedFileNameRegex.matcher(filename); @@ -65,6 +65,7 @@ private static Stream testCases() throws IOException { var treeMatcherName = filenameMatcher.group(2); result.accept(new TestCase( + expectedDir, filenameMatcher.group(1), treeMatcherName, Matchers.getInstance().getMatcher(treeMatcherName)) @@ -73,14 +74,40 @@ private static Stream testCases() throws IOException { })); } + private static Stream createMatchingTestCases() throws IOException { + return testCases("createMatching"); + } + + @ParameterizedTest + @MethodSource("createMatchingTestCases") + public void createMatchingTestCase(TestCase testCase) throws IOException, DiffParseException { + VariationTree beforeEdit = VariationTree.fromFile(testCase.beforeEdit()); + VariationTree afterEdit = VariationTree.fromFile(testCase.afterEdit()); + assertExpectedVariationDiffs(testCase, GumTreeDiff.diffUsingMatching(beforeEdit, afterEdit, testCase.matcher())); + } + + private static Stream improveMatchingTestCases() throws IOException { + return testCases("improveMatching"); + } + @ParameterizedTest - @MethodSource("testCases") - public void testCase(TestCase testCase) throws IOException, DiffParseException { - VariationTree beforeEdit = parseVariationTree(testCase.beforeEdit()); - VariationTree afterEdit = parseVariationTree(testCase.afterEdit()); + @MethodSource("improveMatchingTestCases") + public void improveMatchingTestCase(TestCase testCase) throws IOException, DiffParseException { + VariationDiff variationDiff = + VariationDiff.fromFiles( + testCase.beforeEdit(), + testCase.afterEdit(), + DiffAlgorithm.SupportedAlgorithm.MYERS, + VariationDiffParseOptions.Default + ); + + DiffNode improvedDiffNode = GumTreeDiff.improveMatching(variationDiff.getRoot(), testCase.matcher()); + VariationDiff improvedVariationDiff = new VariationDiff<>(improvedDiffNode, Source.Unknown); - VariationDiff variationDiff = GumTreeDiff.diffUsingMatching(beforeEdit, afterEdit); + assertExpectedVariationDiffs(testCase, improvedVariationDiff); + } + private static void assertExpectedVariationDiffs(TestCase testCase, VariationDiff variationDiff) throws IOException { try (var output = IO.newBufferedOutputStream(testCase.actual())) { new LineGraphExporter<>(new Format<>(new FullNodeFormat(), new ChildOrderEdgeFormat<>())) .exportVariationDiff(variationDiff, output); @@ -110,19 +137,4 @@ public void testCase(TestCase testCase) throws IOException, DiffParseException { } } } - - public VariationTree parseVariationTree(Path filename) throws IOException, DiffParseException { - try (var file = Files.newBufferedReader(filename)) { - return new VariationTree<>( - VariationDiffParser.createVariationTree( - file, - new VariationDiffParseOptions( - new CPPAnnotationParser(), - false, - false) - ).getRoot().projection(BEFORE).toVariationTree(), - new LocalFileSource(filename) - ); - } - } } diff --git a/src/test/java/TreeTransformersTest.java b/src/test/java/TreeTransformersTest.java index c9132c445..2854c009b 100644 --- a/src/test/java/TreeTransformersTest.java +++ b/src/test/java/TreeTransformersTest.java @@ -17,7 +17,7 @@ import org.variantsync.diffdetective.variation.diff.serialize.edgeformat.DefaultEdgeLabelFormat; import org.variantsync.diffdetective.variation.diff.serialize.nodeformat.TypeDiffNodeFormat; import org.variantsync.diffdetective.variation.diff.serialize.treeformat.CommitDiffVariationDiffLabelFormat; -import org.variantsync.diffdetective.variation.diff.transform.VariationDiffTransformer; +import org.variantsync.diffdetective.variation.diff.transform.Transformer; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -64,8 +64,8 @@ private void transformAndRender(VariationDiff variationDiff, Str int i = 1; int prevSize = variationDiff.computeSize(); - final List> transformers = VariationDiffMiner.Postprocessing(repository); - for (final VariationDiffTransformer f : transformers) { + final List>> transformers = VariationDiffMiner.Postprocessing(repository); + for (final Transformer> f : transformers) { INFO.accept("Applying transformation " + f + "."); f.transform(variationDiff); @@ -87,7 +87,7 @@ private void transformAndRender(VariationDiff variationDiff, Str @BeforeEach public void init() { // Main.setupLogger(Level.INFO); -// VariationDiffTransformer.checkDependencies(transformers); + // Transformer.checkDependencies(transformers); } @Test diff --git a/src/test/java/VariationDiffParserTest.java b/src/test/java/VariationDiffParserTest.java index 4c1d4e48f..7646842bf 100644 --- a/src/test/java/VariationDiffParserTest.java +++ b/src/test/java/VariationDiffParserTest.java @@ -7,7 +7,6 @@ import org.variantsync.diffdetective.variation.DiffLinesLabel; import org.variantsync.diffdetective.variation.diff.VariationDiff; import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; -import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser; import org.variantsync.diffdetective.variation.diff.serialize.Format; import org.variantsync.diffdetective.variation.diff.serialize.LineGraphExporter; import org.variantsync.diffdetective.variation.diff.serialize.TikzExporter; @@ -60,15 +59,13 @@ public static void testCase(Path testCasePath) throws IOException, DiffParseExce var expectedPath = testCasePath.getParent().resolve(basename + "_expected.lg"); VariationDiff variationDiff; - try (var inputFile = Files.newBufferedReader(testCasePath)) { - variationDiff = VariationDiffParser.createVariationDiff( - inputFile, - new VariationDiffParseOptions( - false, - false - ) - ); - } + variationDiff = VariationDiff.fromFile( + testCasePath, + new VariationDiffParseOptions( + false, + false + ) + ); try (var output = IO.newBufferedOutputStream(actualPath)) { new LineGraphExporter<>(new Format<>(new FullNodeFormat(), new ChildOrderEdgeFormat<>())) diff --git a/src/test/java/VariationUnparserTest.java b/src/test/java/VariationUnparserTest.java new file mode 100644 index 000000000..17755b25a --- /dev/null +++ b/src/test/java/VariationUnparserTest.java @@ -0,0 +1,79 @@ +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.diff.Time; +import org.variantsync.diffdetective.variation.diff.VariationDiff; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; +import org.variantsync.diffdetective.variation.tree.VariationTree; +import org.variantsync.diffdetective.variation.VariationUnparser; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.variantsync.diffdetective.experiments.thesis_es.UnparseAnalysis.removeWhitespace; + +public class VariationUnparserTest { + private final static Path unparserTestCaseDir = Constants.RESOURCE_DIR.resolve("unparser"); + private final static Path parserTestCaseDir = Constants.RESOURCE_DIR.resolve("diffs").resolve("parser"); + private final static String parserTestCaseSuffix = ".diff"; + + public static Stream treeTestCases() throws IOException { + return withParseOptions(Files.list(unparserTestCaseDir.resolve("trees"))); + } + + public static Stream diffTestCases() throws IOException { + return withParseOptions(Stream.concat( + Files.list(unparserTestCaseDir.resolve("diffs")), + Files.list(parserTestCaseDir) + .filter(filename -> filename.getFileName().toString().endsWith(parserTestCaseSuffix)))); + } + + private static Stream withParseOptions(Stream paths) { + // Build a Cartesian product of all paths and parse options. + return + paths.flatMap(path -> Stream.of( + Arguments.of(path, new VariationDiffParseOptions(false, false)), + Arguments.of(path, new VariationDiffParseOptions(false, true)), + Arguments.of(path, new VariationDiffParseOptions(true, false)), + Arguments.of(path, new VariationDiffParseOptions(true, true)))); + } + + @ParameterizedTest + @MethodSource("treeTestCases") + public void testTreeUnparse(Path testCasePath, VariationDiffParseOptions parseOptions) throws IOException, DiffParseException { + assertEqualTree( + Files.readString(testCasePath).replaceAll("\\r\\n", "\n"), + parseUnparseTree(testCasePath, parseOptions)); + } + + @ParameterizedTest + @MethodSource("diffTestCases") + public void testDiffUnparse(Path testCasePath, VariationDiffParseOptions parseOptions) throws IOException, DiffParseException { + assertEqualDiff( + Files.readString(testCasePath).replaceAll("\\r\\n", "\n"), + parseUnparseDiff(testCasePath, parseOptions)); + } + + private static String parseUnparseTree(Path path, VariationDiffParseOptions option) throws IOException, DiffParseException { + VariationTree tree = VariationTree.fromFile(path, option); + return VariationUnparser.unparseTree(tree); + } + + private static String parseUnparseDiff(Path path, VariationDiffParseOptions option) throws IOException, DiffParseException { + VariationDiff diff = VariationDiff.fromFile(path, option); + return VariationUnparser.unparseDiff(diff); + } + + private static void assertEqualDiff(String expected, String actual) { + assertEqualTree(VariationUnparser.undiff(expected, Time.BEFORE), VariationUnparser.undiff(actual, Time.BEFORE)); + assertEqualTree(VariationUnparser.undiff(expected, Time.AFTER), VariationUnparser.undiff(actual, Time.AFTER)); + } + + private static void assertEqualTree(String expected, String actual) { + assertEquals(removeWhitespace(expected, false), removeWhitespace(actual, false)); + } +} diff --git a/src/test/java/ViewTest.java b/src/test/java/ViewTest.java deleted file mode 100644 index 595ce6dd1..000000000 --- a/src/test/java/ViewTest.java +++ /dev/null @@ -1,245 +0,0 @@ -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.prop4j.*; -import org.tinylog.Logger; -import org.variantsync.diffdetective.analysis.logic.UniqueViewsAlgorithm; -import org.variantsync.diffdetective.diff.result.DiffParseException; -import org.variantsync.diffdetective.show.Show; -import org.variantsync.diffdetective.show.engine.GameEngine; -import org.variantsync.diffdetective.util.StringUtils; -import org.variantsync.diffdetective.variation.DiffLinesLabel; -import org.variantsync.diffdetective.variation.diff.Time; -import org.variantsync.diffdetective.variation.diff.VariationDiff; -import org.variantsync.diffdetective.variation.diff.bad.BadVDiff; -import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; -import org.variantsync.diffdetective.variation.diff.transform.CutNonEditedSubtrees; -import org.variantsync.diffdetective.variation.diff.view.DiffView; -import org.variantsync.diffdetective.variation.diff.view.ViewSource; -import org.variantsync.diffdetective.variation.tree.VariationTree; -import org.variantsync.diffdetective.variation.tree.view.TreeView; -import org.variantsync.diffdetective.variation.tree.view.relevance.*; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import static org.variantsync.diffdetective.util.fide.FormulaUtils.*; - -@Disabled -public class ViewTest { - private static final Path resDir = Constants.RESOURCE_DIR.resolve("badvdiff"); - - private static void showViews( - VariationDiff initialVDiff, - Relevance query - ) { - // treeify - final BadVDiff badDiff = BadVDiff.fromGood(initialVDiff); - - // create view - final BadVDiff view = badDiff.deepCopy(); - TreeView.treeInline(view.diff(), query); - - // unify - final VariationDiff goodDiff = view.toGood(); - goodDiff.assertConsistency(); - - GameEngine.showAndAwaitAll( - Show.diff(initialVDiff, "initial edit e"), - Show.baddiff(badDiff, "tree(e)"), - Show.baddiff(view, "view(tree(e), " + query + ")"), - Show.diff(goodDiff, "unify(view(tree(e), " + query + "))") - ); - } - - @ParameterizedTest - @ValueSource(strings = { - "emacsbug1" - }) - void debugTest(String filename) throws IOException, DiffParseException { - final String filenameWithEnding = filename + ".diff"; - final Path testfile = resDir.resolve(filenameWithEnding); - Logger.debug("Testing " + testfile); -// is( /* Check both of the above conditions, for symbols. */) - final VariationDiff D = VariationDiff.fromFile(testfile, VariationDiffParseOptions.Default); - D.assertConsistency(); - - final Relevance debugQuery = new Search(" /* Check both of the above conditions, for symbols. */"); - final var imp = DiffView.computeWhenNodesAreRelevant(D, debugQuery); - Show.diff(DiffView.optimized(D, debugQuery, imp)).showAndAwait(); - Show.diff(DiffView.naive(D, debugQuery, imp)).showAndAwait(); - } - - - @ParameterizedTest - @ValueSource(strings = { - "1", - "diamond", - "deep_insertion" - }) - void test(String filename) throws IOException, DiffParseException { - final String filenameWithEnding = filename + ".diff"; - final Path testfile = resDir.resolve(filenameWithEnding); - Logger.debug("Testing " + testfile); - - // Load diff - final VariationDiff initialVDiff = VariationDiff.fromFile(testfile, VariationDiffParseOptions.Default); - initialVDiff.assertConsistency(); - - List queries = List.of( - new Trace("B"), - new Configure(negate(var("B"))), - new Search("foo") - ); - - for (Relevance q : queries) { - final var viewNodes = DiffView.computeWhenNodesAreRelevant(initialVDiff, q); - - GameEngine.showAndAwaitAll( - Show.diff(initialVDiff, "D = " + filenameWithEnding), - Show.diff(DiffView.naive(initialVDiff, q, viewNodes), "diff_naive(D, " + q + ")"), - Show.diff(DiffView.optimized(initialVDiff, q, viewNodes), "diff_smart(D, " + q + ")") - ); - } - -// showViews(initialVDiff, new VariantQuery(and(var("X")))); -// showViews(initialVDiff, new VariantQuery(and(var("Y")))); -// showViews(initialVDiff, new VariantQuery(and(negate(var("X"))))); -// showViews(initialVDiff, new VariantQuery(and(negate(var("Y"))))); -// showViews(initialVDiff, new FeatureQuery("X")); -// showViews(initialVDiff, new FeatureQuery("Y")); -// showViews(initialVDiff, new ArtifactQuery("y")); - } - - @ParameterizedTest - @ValueSource(strings = { - "runningexampleInDomain", - }) - void inspectRunningExample(String filename) throws IOException, DiffParseException { - final Path testfile = resDir.resolve(filename + ".diff"); - -// final Literal X = var("Mutable"); - final Literal featureRing = var("Ring"); - final Literal featureDoubleLink = var("DoubleLink"); - - final VariationDiff d = VariationDiff.fromFile(testfile, VariationDiffParseOptions.Default); - final VariationTree b = d.project(Time.BEFORE); - final VariationTree a = d.project(Time.AFTER); - - // Queries of Listing 3 and 4 - final Relevance bobsQuery1 = new Configure(and(negate(featureDoubleLink))); - final Relevance charlottesQuery = new Configure(negate(featureRing)); - - // Figure 1 - GameEngine.showAndAwaitAll( - Show.tree(b, "Figure 1: project(D, b)") - ); - - // Figure 2 - GameEngine.showAndAwaitAll( - Show.diff(d, "Figure 2: D") - ); - - // Figure 3 - final Configure configureExample1 = new Configure( - and(featureRing, /* FM = */ negate(and(featureDoubleLink, featureRing))) - ); - GameEngine.showAndAwaitAll( - Show.tree(TreeView.tree(b, configureExample1), "Figure 3: view_{tree}(Figure 1, " + configureExample1 + ")") - ); - - // Figure 4 - final Trace traceYesExample1 = new Trace( - featureDoubleLink.toString() - ); - GameEngine.showAndAwaitAll( - Show.tree(TreeView.tree(b, traceYesExample1), "Figure 4: view_{tree}(Figure 1, " + traceYesExample1 + ")") - ); - - // Figure 5 - GameEngine.showAndAwaitAll( - Show.diff(DiffView.optimized(d, charlottesQuery), "Figure 5: view_{naive}(Figure 2, " + charlottesQuery + ")") - ); - } - - @ParameterizedTest - @ValueSource(strings = { - "1", - "2" -// "runningexample", -//// "const", -//// "diamond", -//// "deep_insertion" - }) - void testAllConfigs(String filename) throws IOException, DiffParseException { - final Path testfile = resDir.resolve(filename + ".diff"); - final VariationDiff d = VariationDiff.fromFile(testfile, VariationDiffParseOptions.Default); - - final List configs = UniqueViewsAlgorithm.getUniquePartialConfigs(d, false); - final List> views = new ArrayList<>(); - - final StringBuilder str = new StringBuilder(); - for (int i = 0; i < configs.size(); ++i) { - final Node config = configs.get(i); - - final Relevance q = new Configure(config); - final VariationDiff view = DiffView.optimized(d, q); - views.add(view); - - str - .append(" ") - .append(org.apache.commons.lang3.StringUtils.leftPad( - Integer.toString(i), - 4) - ) - .append(".) ") - .append(org.apache.commons.lang3.StringUtils.rightPad( - config.toString(NodeWriter.logicalSymbols), - 40) - ) - .append(" --- ") - .append( - view.computeArtifactNodes().stream() - .map(a -> a.getLabel().getLines().stream() - .map(String::trim) - .collect(Collectors.joining(StringUtils.LINEBREAK)) - ) - .collect(Collectors.toList())) - .append(StringUtils.LINEBREAK); - } - - Logger.info("All unique partial configs:" + StringUtils.LINEBREAK + str); - Show.diff(d, "D").show(); -// { -// final Query q = new FeatureQuery("C"); -// Show.diff(DiffView.optimized(d, q), "view(D, " + q.getName() + ")").showAndAwait(); -// } - - for (int i = 0; i < configs.size(); ++i) { - final VariationDiff view = views.get(i); - final Relevance q = ((ViewSource) view.getSource()).relevance(); - Show.diff(view, i + ".) view(D, " + q + ")").showAndAwait(); - } - } - - @ParameterizedTest - @ValueSource(strings = { - "1", - "2", - "runningexample", - "const", - "diamond", - "deep_insertion" - }) - void cutTest(String filename) throws IOException, DiffParseException { - final Path testfile = resDir.resolve(filename + ".diff"); - final VariationDiff d = VariationDiff.fromFile(testfile, VariationDiffParseOptions.Default); - - Show.diff(d, "original").showAndAwait(); - CutNonEditedSubtrees.genericTransform(true, d); - Show.diff(d, "cut").showAndAwait(); - } -} diff --git a/src/test/java/ViewsTest.java b/src/test/java/ViewsTest.java new file mode 100644 index 000000000..ea618f3d1 --- /dev/null +++ b/src/test/java/ViewsTest.java @@ -0,0 +1,145 @@ +import static org.variantsync.diffdetective.util.fide.FormulaUtils.and; +import static org.variantsync.diffdetective.util.fide.FormulaUtils.negate; +import static org.variantsync.diffdetective.util.fide.FormulaUtils.var; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.prop4j.Literal; +import org.prop4j.Node; +import org.variantsync.diffdetective.diff.result.DiffParseException; +import org.variantsync.diffdetective.util.Assert; +import org.variantsync.diffdetective.variation.DiffLinesLabel; +import org.variantsync.diffdetective.variation.diff.DiffNode; +import org.variantsync.diffdetective.variation.diff.VariationDiff; +import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions; +import org.variantsync.diffdetective.variation.diff.view.DiffView; +import org.variantsync.diffdetective.variation.tree.VariationTree; +import org.variantsync.diffdetective.variation.tree.view.TreeView; +import org.variantsync.diffdetective.variation.tree.view.relevance.Configure; +import org.variantsync.diffdetective.variation.tree.view.relevance.Relevance; +import org.variantsync.diffdetective.variation.tree.view.relevance.spec.ConfigureSpec; + +/** + * Tests for views on variation trees and diffs. + */ +public class ViewsTest { + private static final Path + resDir = Constants.RESOURCE_DIR.resolve("diffs").resolve("views"), + treeDir = resDir.resolve("tree"), // directory of test cases for variation trees + diffDir = resDir.resolve("diff") // directory of test cases for variation diffs + ; + + /** + * This record holds the implementation of a relevance predicate and its specification. + * Both predicates will be tested for semantic equivalence. + * The idea is that the first relevance is an optimized implementation, whereas the second + * relevance is an easy-to-understand and easy-to-verify but suboptimal implementation. + **/ + private static record RelevanceSpec(Relevance impl, Relevance spec) {} + + // These classes are test cases for testing consistency between a relevance predicate's implementation and specification + // on trees and diffs respectively. + private static record TreeConsistencyTestCase(VariationTree tree, List relevances) {} + private static record DiffConsistencyTestCase(VariationDiff diff, List relevances) {} + + /** + * Creates a TreeConsistencyTestCase for the Configure relevance. + * @param fileName The name of the file to parse as variation tree. + * @param fs any number of formulas to test view generation with + */ + private static TreeConsistencyTestCase treeConf(String fileName, Node... fs) throws IOException, DiffParseException { + return new TreeConsistencyTestCase( + VariationTree.fromFile(treeDir.resolve(fileName), VariationDiffParseOptions.Default), + Arrays.stream(fs).map(f -> new RelevanceSpec(new Configure(f), new ConfigureSpec(f))).toList() + ); + } + + /** + * Creates a DiffConsistencyTestCase for the Configure relevance. + * @param fileName The name of the file to parse as variation diff. + * @param fs any number of formulas to test view generation with + */ + private static DiffConsistencyTestCase diffConf(String fileName, Node... fs) throws IOException, DiffParseException { + return new DiffConsistencyTestCase( + VariationDiff.fromFile(diffDir.resolve(fileName), VariationDiffParseOptions.Default), + Arrays.stream(fs).map(f -> new RelevanceSpec(new Configure(f), new ConfigureSpec(f))).toList() + ); + } + + private static List treeConsistencyTestCases() throws IOException, DiffParseException { + final Literal A = var("A"), B = var("B"), C = var("C"), D = var("D"), E = var("E"); + return List.of( + treeConf("else.c", A, negate(A), C), + treeConf("elif.c", A, negate(A), B, negate(B)), + treeConf("elif-chain.c", negate(E), and(negate(A), negate(B), negate(C), negate(D))) + ); + } + + public static List diffConsistencyTestCases() throws IOException, DiffParseException { + List testCases = new ArrayList<>(); + + // We reuse all test cases for variation trees for variation diffs. + testCases.addAll(treeConsistencyTestCases().stream().map( + treeTestCase -> new DiffConsistencyTestCase(treeTestCase.tree.toCompletelyUnchangedVariationDiff(), treeTestCase.relevances)).toList() + ); + + // TODO: Create some additional test cases targeted specifically at variation diffs. + // In these test cases, the projections should be different. + + return testCases; + } + + /** + * Tests that a {@link Relevance} predicate is consistent with its specification on all + * supplied test cases. + */ + @ParameterizedTest + @MethodSource("treeConsistencyTestCases") + public void consistencyOnTrees(TreeConsistencyTestCase t) { + for (RelevanceSpec relevance : t.relevances) { + final VariationTree impl = TreeView.tree(t.tree, relevance.impl); + final VariationTree spec = TreeView.tree(t.tree, relevance.spec); + + // To compare the trees, we create a diff. + // If there are no deleted or removed nodes, both trees are equal. + final VariationDiff d = VariationDiff.fromTrees(impl, spec); + Assert.assertTrue(d.allMatch(DiffNode::isNon)); + } + } + + /** + * Tests that + * (1) a {@link Relevance} predicate is consistent with its specification, and + * (2) the optimized generation of views on variation diffs + * ({@link DiffView#optimized(VariationDiff, Relevance)}) is consistent + * with the naive implementation ({@link DiffView#naive(VariationDiff, Relevance)}) + * which rather serves as a specification. + */ + @ParameterizedTest + @MethodSource("diffConsistencyTestCases") + public void consistencyOnDiffs(DiffConsistencyTestCase t) throws IOException, DiffParseException { + for (RelevanceSpec relevance : t.relevances) { + // All of these must be equal. + final VariationDiff naive_impl = DiffView.naive(t.diff, relevance.impl); + final VariationDiff naive_spec = DiffView.naive(t.diff, relevance.spec); + final VariationDiff opt_impl = DiffView.optimized(t.diff, relevance.impl); + final VariationDiff opt_spec = DiffView.optimized(t.diff, relevance.spec); + + // First, we test consistency among relevance implementation and relevance specification. + Assert.assertTrue(naive_impl.isSameAsIgnoringLineNumbers(naive_spec)); + Assert.assertTrue(opt_impl.isSameAsIgnoringLineNumbers(opt_spec)); + + // Second, assuming relevance consistency, we test consistency between optimized and naive view generation. + // We get the last comparison Assert.assertTrue(opt_impl.isSameAsIgnoringLineNumbers(naive_impl)) by transitivity. + Assert.assertTrue(opt_spec.isSameAsIgnoringLineNumbers(naive_spec)); + } + } + + // TODO: Test cases where we check the result of computing a view against a predefined ground truth. +} diff --git a/src/test/resources/badvdiff/childOrder.lg b/src/test/resources/badvdiff/childOrder.lg new file mode 100644 index 000000000..39cb4cdd3 --- /dev/null +++ b/src/test/resources/badvdiff/childOrder.lg @@ -0,0 +1,13 @@ +t # 1 +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 7, new: -1);A;#if A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 6, new: -1);X;#if X +v 403 NON;ARTIFACT;(old: 3, diff: 5, new: 4);(old: 4, diff: 6, new: 5);;foo +v 192 ADD;IF;(old: -1, diff: 2, new: 1);(old: -1, diff: 7, new: 5);B;#if B +v 256 ADD;IF;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);X;#if X +e 136 16 b;0,-1 +e 264 136 b;0,-1 +e 403 264 b;0,-1 +e 192 16 a;-1,0 +e 256 192 a;-1,0 +e 403 192 a;-1,1 diff --git a/src/test/resources/diffs/differ/4a4c1db1b192e221d8e25460d6d1128d1bdd0c0d.lg b/src/test/resources/diffs/differ/4a4c1db1b192e221d8e25460d6d1128d1bdd0c0d.lg index 3cbe7dae9..4bd20ce33 100644 --- a/src/test/resources/diffs/differ/4a4c1db1b192e221d8e25460d6d1128d1bdd0c0d.lg +++ b/src/test/resources/diffs/differ/4a4c1db1b192e221d8e25460d6d1128d1bdd0c0d.lg @@ -5,5 +5,5 @@ v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Another v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;Hallo e 147 16 ba;0,0 e 203 16 b;1,-1 -e 339 16 ba;2,2 e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/diffs/differ/a032346092e47048becb36a7cb183b4739547370.lg b/src/test/resources/diffs/differ/a032346092e47048becb36a7cb183b4739547370.lg index d151296bd..7aa5bf395 100644 --- a/src/test/resources/diffs/differ/a032346092e47048becb36a7cb183b4739547370.lg +++ b/src/test/resources/diffs/differ/a032346092e47048becb36a7cb183b4739547370.lg @@ -29,19 +29,19 @@ e 336 16 ba;3,3 e 403 336 ba;0,0 e 467 336 ba;1,1 e 528 336 ba;2,2 -e 595 528 ba;0,0 -e 657 528 ba;1,1 -e 723 657 ba;0,0 e 851 336 ba;3,3 e 915 336 ba;4,4 e 979 336 ba;5,5 e 1043 336 ba;6,6 e 1104 336 ba;7,7 -e 1299 1104 ba;0,0 -e 1363 1104 ba;1,1 e 1619 336 ba;8,8 e 1680 336 ba;9,9 -e 1811 1680 ba;0,0 e 1939 336 ba;10,10 e 2000 336 ba;11,11 +e 595 528 ba;0,0 +e 657 528 ba;1,1 +e 723 657 ba;0,0 +e 1299 1104 ba;0,0 +e 1363 1104 ba;1,1 +e 1811 1680 ba;0,0 e 2067 2000 ba;0,0 diff --git a/src/test/resources/diffs/jpp/basic_jpp_expected.lg b/src/test/resources/diffs/jpp/basic_jpp_expected.lg index c6f8d5924..7c02b52eb 100644 --- a/src/test/resources/diffs/jpp/basic_jpp_expected.lg +++ b/src/test/resources/diffs/jpp/basic_jpp_expected.lg @@ -20,16 +20,16 @@ e 131 16 a;-1,0 e 195 16 a;-1,1 e 259 16 a;-1,2 e 320 16 a;-1,3 -e 387 320 a;-1,0 -e 451 320 a;-1,1 -e 515 320 a;-1,2 e 643 16 a;-1,4 e 707 16 a;-1,5 e 768 16 a;-1,6 -e 835 768 a;-1,0 -e 899 768 a;-1,1 -e 963 768 a;-1,2 e 1091 16 a;-1,7 e 1155 16 a;-1,8 e 1216 16 a;-1,9 +e 387 320 a;-1,0 +e 451 320 a;-1,1 +e 515 320 a;-1,2 +e 835 768 a;-1,0 +e 899 768 a;-1,1 +e 963 768 a;-1,2 e 1283 1216 a;-1,0 diff --git a/src/test/resources/diffs/parser/02_expected.lg b/src/test/resources/diffs/parser/02_expected.lg index be1bdf11f..21f0820e2 100644 --- a/src/test/resources/diffs/parser/02_expected.lg +++ b/src/test/resources/diffs/parser/02_expected.lg @@ -3,6 +3,6 @@ v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);A;#if A v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);; Code v 323 ADD;ARTIFACT;(old: -1, diff: 4, new: 2);(old: -1, diff: 5, new: 3);; // Hehe e 136 16 b;0,-1 -e 211 136 b;0,-1 e 211 16 a;-1,0 e 323 16 a;-1,1 +e 211 136 b;0,-1 diff --git a/src/test/resources/diffs/parser/03_expected.lg b/src/test/resources/diffs/parser/03_expected.lg index a51c370b1..d9480b61a 100644 --- a/src/test/resources/diffs/parser/03_expected.lg +++ b/src/test/resources/diffs/parser/03_expected.lg @@ -5,8 +5,8 @@ v 595 NON;ARTIFACT;(old: 6, diff: 8, new: 5);(old: 7, diff: 9, new: 6);;Code v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 10, new: 6);A | B | C;#if A \; || B \; || C \; // Foo v 771 ADD;ARTIFACT;(old: -1, diff: 11, new: 7);(old: -1, diff: 12, new: 8);; // Bar e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 771 16 a;-1,1 e 523 136 b;0,-1 e 595 136 b;1,-1 e 595 128 a;-1,0 -e 128 16 a;-1,0 -e 771 16 a;-1,1 diff --git a/src/test/resources/diffs/parser/08_expected.lg b/src/test/resources/diffs/parser/08_expected.lg index 6d28b028d..1d6417339 100644 --- a/src/test/resources/diffs/parser/08_expected.lg +++ b/src/test/resources/diffs/parser/08_expected.lg @@ -3,6 +3,6 @@ v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 4, new: -1);defined(A);#i v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 2);(old: 3, diff: 4, new: 3);;Code v 192 ADD;IF;(old: -1, diff: 2, new: 1);(old: -1, diff: 4, new: 3);defined(B);#ifdef B e 136 16 b;0,-1 +e 192 16 a;-1,0 e 275 136 b;0,-1 e 275 192 a;-1,0 -e 192 16 a;-1,0 diff --git a/src/test/resources/diffs/parser/09_expected.lg b/src/test/resources/diffs/parser/09_expected.lg index 714b02ae3..30efd0c3d 100644 --- a/src/test/resources/diffs/parser/09_expected.lg +++ b/src/test/resources/diffs/parser/09_expected.lg @@ -1,8 +1,11 @@ v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 5, new: 4);defined(A);#ifdef A +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Code 1 v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 3);(old: 5, diff: 5, new: 4);;Code 2 -e 144 16 ba;0,0 -e 211 144 ba;0,0 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +e 136 16 b;0,-1 e 339 16 b;1,-1 -e 339 144 a;-1,1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 211 128 a;-1,0 +e 339 128 a;-1,1 diff --git a/src/test/resources/diffs/parser/10_expected.lg b/src/test/resources/diffs/parser/10_expected.lg index 23e1643c1..5f7236d99 100644 --- a/src/test/resources/diffs/parser/10_expected.lg +++ b/src/test/resources/diffs/parser/10_expected.lg @@ -3,6 +3,6 @@ v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 3, diff: 4, new: -1);defined(A);#i v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 2);(old: 3, diff: 4, new: 3);;Code v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(B);#ifdef B e 200 16 b;0,-1 +e 128 16 a;-1,0 e 275 200 b;0,-1 e 275 128 a;-1,0 -e 128 16 a;-1,0 diff --git a/src/test/resources/diffs/parser/11_expected.lg b/src/test/resources/diffs/parser/11_expected.lg index 886bc794f..4d60ed8d9 100644 --- a/src/test/resources/diffs/parser/11_expected.lg +++ b/src/test/resources/diffs/parser/11_expected.lg @@ -3,6 +3,6 @@ v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 4, new: -1);defined(A);#i v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 2);(old: 3, diff: 4, new: 3);;Code v 192 ADD;IF;(old: -1, diff: 2, new: 1);(old: -1, diff: 5, new: 3);defined(B);#ifdef B e 136 16 b;0,-1 +e 192 16 a;-1,0 e 275 136 b;0,-1 e 275 192 a;-1,0 -e 192 16 a;-1,0 diff --git a/src/test/resources/diffs/parser/16_expected.lg b/src/test/resources/diffs/parser/16_expected.lg index f351f9f7a..c3b64bcf7 100644 --- a/src/test/resources/diffs/parser/16_expected.lg +++ b/src/test/resources/diffs/parser/16_expected.lg @@ -8,14 +8,14 @@ v 595 NON;ARTIFACT;(old: 6, diff: 8, new: 7);(old: 7, diff: 9, new: 8);;d v 256 ADD;IF;(old: -1, diff: 3, new: 2);(old: -1, diff: 5, new: 4);defined(B);#ifdef B v 386 ADD;ELIF;(old: -1, diff: 5, new: 4);(old: -1, diff: 7, new: 6);C;#elif C e 136 16 b;0,-1 -e 211 136 b;0,-1 e 211 16 a;-1,0 +e 256 16 a;-1,1 +e 211 136 b;0,-1 e 339 136 b;1,-1 -e 339 256 a;-1,0 e 467 136 b;2,-1 -e 467 386 a;-1,0 e 529 136 b;3,-1 -e 529 386 a;-1,1 e 595 529 ba;0,0 -e 256 16 a;-1,1 +e 339 256 a;-1,0 e 386 256 a;-1,1 +e 467 386 a;-1,0 +e 529 386 a;-1,1 diff --git a/src/test/resources/diffs/parser/17_expected.lg b/src/test/resources/diffs/parser/17_expected.lg index 0476ef4d0..046f80dad 100644 --- a/src/test/resources/diffs/parser/17_expected.lg +++ b/src/test/resources/diffs/parser/17_expected.lg @@ -3,5 +3,5 @@ v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 2, diff: 3, new: -1);defined(A);#i v 265 REM;ELSE;(old: 2, diff: 3, new: -1);(old: 3, diff: 5, new: -1);;#else v 192 ADD;IF;(old: -1, diff: 2, new: 1);(old: -1, diff: 4, new: 3);defined(B);#ifdef B #\;#else e 136 16 b;0,-1 -e 265 136 b;0,-1 e 192 16 a;-1,0 +e 265 136 b;0,-1 diff --git a/src/test/resources/diffs/parser/wontfix/01.diff b/src/test/resources/diffs/parser/19.diff similarity index 100% rename from src/test/resources/diffs/parser/wontfix/01.diff rename to src/test/resources/diffs/parser/19.diff diff --git a/src/test/resources/diffs/parser/wontfix/01_expected.lg b/src/test/resources/diffs/parser/19_expected.lg similarity index 76% rename from src/test/resources/diffs/parser/wontfix/01_expected.lg rename to src/test/resources/diffs/parser/19_expected.lg index 937d7f4fc..34f271f8d 100644 --- a/src/test/resources/diffs/parser/wontfix/01_expected.lg +++ b/src/test/resources/diffs/parser/19_expected.lg @@ -1,3 +1,3 @@ v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);A;# \; ifdef A -e 144 16 ba;0;0 +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);# \; ifdef A +e 144 16 ba;0,0 diff --git a/src/test/resources/diffs/parser/wontfix/03.diff b/src/test/resources/diffs/parser/20.diff similarity index 100% rename from src/test/resources/diffs/parser/wontfix/03.diff rename to src/test/resources/diffs/parser/20.diff diff --git a/src/test/resources/diffs/parser/20_expected.lg b/src/test/resources/diffs/parser/20_expected.lg new file mode 100644 index 000000000..3f7dac870 --- /dev/null +++ b/src/test/resources/diffs/parser/20_expected.lg @@ -0,0 +1,3 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 4, diff: 4, new: 4);;/* This is a comment, so it's removed before the preprocessor is run; #ifdef A; */ +e 147 16 ba;0,0 diff --git a/src/test/resources/diffs/parser/wontfix/04.diff b/src/test/resources/diffs/parser/21.diff similarity index 100% rename from src/test/resources/diffs/parser/wontfix/04.diff rename to src/test/resources/diffs/parser/21.diff diff --git a/src/test/resources/diffs/parser/wontfix/04_expected.lg b/src/test/resources/diffs/parser/21_expected.lg similarity index 71% rename from src/test/resources/diffs/parser/wontfix/04_expected.lg rename to src/test/resources/diffs/parser/21_expected.lg index 3683a3f2d..53cfe48b7 100644 --- a/src/test/resources/diffs/parser/wontfix/04_expected.lg +++ b/src/test/resources/diffs/parser/21_expected.lg @@ -1,3 +1,3 @@ v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 4, new: 4);A;#ifdef /*; * Comment; */ A -e 144 16 ba;0;0 +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 4, new: 4);defined(A);#ifdef /*; * Comment; */ A +e 144 16 ba;0,0 diff --git a/src/test/resources/diffs/parser/wontfix/03_expected.lg b/src/test/resources/diffs/parser/wontfix/03_expected.lg deleted file mode 100644 index b6eafe2f5..000000000 --- a/src/test/resources/diffs/parser/wontfix/03_expected.lg +++ /dev/null @@ -1,7 +0,0 @@ -v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True -v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;/* This is a comment, so it's removed before the preprocessor is run -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);; #ifdef A -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 4, new: 4);; */ -e 147 16 ba;0;0 -e 211 16 ba;1;1 -e 275 16 ba;2;2 diff --git a/src/test/resources/diffs/parser/wontfix/README.md b/src/test/resources/diffs/parser/wontfix/README.md index 5c016ea6e..8df09a425 100644 --- a/src/test/resources/diffs/parser/wontfix/README.md +++ b/src/test/resources/diffs/parser/wontfix/README.md @@ -1,9 +1,8 @@ # Test cases of WONTFIX behaviour ## Sophisticated comment parsing -The test cases 01 and 02 would require the removal of comments before checking -if a line is a macro. The test cases 03 and 04 would required the detection of -multi-line macros which span multiple lines. +The test case 02 would require the removal of comments before checking +if a line is a macro. All of these cases require more engineering than they are worth because they should be pretty rare in practice. diff --git a/src/test/resources/diffs/views/tree/elif-chain.c b/src/test/resources/diffs/views/tree/elif-chain.c new file mode 100644 index 000000000..d9dd33cec --- /dev/null +++ b/src/test/resources/diffs/views/tree/elif-chain.c @@ -0,0 +1,15 @@ +int x = +#ifdef A + 0 +#elif B + 1 +#elif C + 2 +#elif D + 3 +#elif E + 4 +#else + 5 +#endif + ; diff --git a/src/test/resources/diffs/views/tree/elif.c b/src/test/resources/diffs/views/tree/elif.c new file mode 100644 index 000000000..ced5c84a2 --- /dev/null +++ b/src/test/resources/diffs/views/tree/elif.c @@ -0,0 +1,5 @@ +#ifdef A + foo +#elif B + bar +#endif diff --git a/src/test/resources/diffs/views/tree/else.c b/src/test/resources/diffs/views/tree/else.c new file mode 100644 index 000000000..c6c093c56 --- /dev/null +++ b/src/test/resources/diffs/views/tree/else.c @@ -0,0 +1,5 @@ +#ifdef A + foo +#else + bar +#endif diff --git a/src/test/resources/featurenames/a.diff b/src/test/resources/featurenames/a.diff new file mode 100644 index 000000000..8bffc620c --- /dev/null +++ b/src/test/resources/featurenames/a.diff @@ -0,0 +1,6 @@ + #if FIRST + foo + #if SECOND + bar + #endif + #endif diff --git a/src/test/resources/featurenames/b.diff b/src/test/resources/featurenames/b.diff new file mode 100644 index 000000000..44d1cb836 --- /dev/null +++ b/src/test/resources/featurenames/b.diff @@ -0,0 +1,6 @@ +-#if A + foo + #if A + bar + #endif +-#endif diff --git a/src/test/resources/featurenames/empty.diff b/src/test/resources/featurenames/empty.diff new file mode 100644 index 000000000..eca8e31ec --- /dev/null +++ b/src/test/resources/featurenames/empty.diff @@ -0,0 +1 @@ + foo diff --git a/src/test/resources/line_graph/.gitignore b/src/test/resources/line_graph/.gitignore new file mode 100644 index 000000000..5842cb6df --- /dev/null +++ b/src/test/resources/line_graph/.gitignore @@ -0,0 +1 @@ +*.actual diff --git a/src/test/resources/line_graph/childOrder.lg b/src/test/resources/line_graph/childOrder.lg new file mode 100644 index 000000000..5971add84 --- /dev/null +++ b/src/test/resources/line_graph/childOrder.lg @@ -0,0 +1,9 @@ +t # fileName$$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +v 16 +v 147 A +v 211 B +e 211 16 a +e 147 16 ba +e 211 16 b + + diff --git a/src/test/resources/line_graph/vulkan_structs.hpp$$$fd641ac85c6170c34845db5e345d3bf9cedce8d7.lg b/src/test/resources/line_graph/vulkan_structs.hpp$$$fd641ac85c6170c34845db5e345d3bf9cedce8d7.lg index b4e82d0ac..2f6f89aba 100644 --- a/src/test/resources/line_graph/vulkan_structs.hpp$$$fd641ac85c6170c34845db5e345d3bf9cedce8d7.lg +++ b/src/test/resources/line_graph/vulkan_structs.hpp$$$fd641ac85c6170c34845db5e345d3bf9cedce8d7.lg @@ -1998,2046 +1998,785 @@ v 4723712 ADD_IF_"if -VULKAN_HPP_NO_STRUCT_SETTERS" v 4724992 ADD_IF_"if -VULKAN_HPP_DISABLE_ENHANCED_MODE" e 592 144 ba e 3283 592 b -e 3283 3200 a e 8275 592 b -e 8275 8192 a e 9107 592 b -e 9107 9024 a e 14547 592 b -e 14547 14464 a e 22355 592 b -e 22355 22272 a e 27731 592 b -e 27731 27648 a e 31059 592 b -e 31059 30976 a e 32467 592 b -e 32467 32384 a e 37715 592 b -e 37715 37632 a e 41427 592 b -e 41427 41344 a e 42195 592 b -e 42195 42112 a e 50195 592 b -e 50195 50112 a e 54483 592 b -e 54483 50112 a e 55763 592 b -e 55763 50112 a e 53640 592 b -e 53779 53640 b -e 53779 53696 a e 54920 592 b -e 55059 54920 b -e 55059 54976 a e 60755 592 b -e 60755 60672 a e 66963 592 b -e 66963 66880 a e 74259 592 b -e 74259 74176 a e 83347 592 b -e 83347 83264 a e 93523 592 b -e 93523 93440 a e 99795 592 b -e 99795 99712 a e 104595 592 b -e 104595 104512 a e 112083 592 b -e 112083 112000 a e 114504 592 b -e 114643 114504 b -e 114643 114560 a e 120403 592 b -e 120403 120320 a e 126547 592 b -e 126547 126464 a e 132243 592 b -e 132243 132160 a e 136467 592 b -e 136467 136384 a e 141267 592 b -e 141267 141184 a e 149139 592 b -e 149139 149056 a e 157267 592 b -e 157267 157184 a e 163475 592 b -e 163475 163392 a e 170771 592 b -e 170771 170688 a e 182675 592 b -e 182675 182592 a e 188691 592 b -e 188691 188608 a e 190227 592 b -e 190227 190144 a e 195667 592 b -e 195667 195584 a e 200339 592 b -e 200339 200256 a e 205971 592 b -e 205971 205888 a e 213139 592 b -e 213139 213056 a e 219219 592 b -e 219219 219136 a e 226067 592 b -e 226067 225984 a e 245968 592 ba -e 247955 245968 b -e 247955 247872 a -e 247872 245968 a e 254099 592 b -e 254099 254016 a e 261971 592 b -e 261971 261888 a e 271187 592 b -e 271187 271104 a e 280659 592 b -e 280659 280576 a e 286483 592 b -e 286483 286400 a e 291411 592 b -e 291411 291328 a e 297683 592 b -e 297683 297600 a e 302611 592 b -e 302611 302528 a e 307027 592 b -e 307027 306944 a e 312979 592 b -e 312979 312896 a e 315080 592 b -e 315219 315080 b -e 315219 315136 a e 320659 592 b -e 320659 320576 a e 325139 592 b -e 325139 325056 a e 329043 592 b -e 329043 328960 a e 334995 592 b -e 334995 334912 a e 337416 592 b -e 337555 337416 b -e 337555 337472 a e 343635 592 b -e 343635 343552 a e 344776 592 b -e 344915 344776 b -e 344915 344832 a e 350355 592 b -e 350355 350272 a e 356115 592 b -e 356115 356032 a e 360403 592 b -e 360403 360320 a e 366227 592 b -e 366227 366144 a e 368147 592 b -e 368147 366144 a e 367368 592 b -e 367507 367368 b -e 367507 367424 a e 369032 592 b -e 369171 369032 b -e 369171 369088 a e 374931 592 b -e 374931 374848 a e 381203 592 b -e 381203 381120 a e 386963 592 b -e 386963 386880 a e 392339 592 b -e 392339 392256 a e 397395 592 b -e 397395 397312 a e 401875 592 b -e 401875 401792 a e 408595 592 b -e 408595 408512 a e 409736 592 b -e 409875 409736 b -e 409875 409792 a e 415251 592 b -e 415251 415168 a e 416456 592 b -e 416595 416456 b -e 416595 416512 a e 421267 592 b -e 421267 421184 a e 426195 592 b -e 426195 426112 a e 431251 592 b -e 431251 431168 a e 436755 592 b -e 436755 436672 a e 443987 592 b -e 443987 443904 a e 445192 592 b -e 445331 445192 b -e 445331 445248 a e 452691 592 b -e 452691 452608 a e 454675 592 b -e 454675 452608 a e 456339 592 b -e 456339 452608 a e 458003 592 b -e 458003 452608 a e 459667 592 b -e 459667 452608 a e 453832 592 b -e 453971 453832 b -e 453971 453888 a e 455496 592 b -e 455635 455496 b -e 455635 455552 a e 457160 592 b -e 457299 457160 b -e 457299 457216 a e 458824 592 b -e 458963 458824 b -e 458963 458880 a e 460488 592 b -e 460627 460488 b -e 460627 460544 a e 466579 592 b -e 466579 466496 a e 471955 592 b -e 471955 471872 a e 477907 592 b -e 477907 477824 a e 486611 592 b -e 486611 486528 a e 490131 592 b -e 490131 486528 a e 489288 592 b -e 489427 489288 b -e 489427 489344 a e 495379 592 b -e 495379 495296 a e 500563 592 b -e 500563 500480 a e 508115 592 b -e 508115 508032 a e 510792 592 b -e 510931 510792 b -e 510931 510848 a e 516499 592 b -e 516499 516416 a e 521683 592 b -e 521683 521600 a e 527251 592 b -e 527251 527168 a e 534419 592 b -e 534419 534336 a e 542739 592 b -e 542739 542656 a e 551699 592 b -e 551699 551616 a e 560915 592 b -e 560915 560832 a e 566291 592 b -e 566291 566208 a e 572051 592 b -e 572051 571968 a e 579155 592 b -e 579155 579072 a e 591571 592 b -e 591571 591488 a e 592403 592 b -e 592403 592320 a e 596627 592 b -e 596627 596544 a e 599699 592 b -e 599699 599616 a e 600403 592 b -e 600403 600320 a e 604627 592 b -e 604627 604544 a e 608659 592 b -e 608659 608576 a e 613651 592 b -e 613651 613568 a e 619923 592 b -e 619923 619840 a e 621576 592 b -e 621715 621576 b -e 621715 621632 a e 626963 592 b -e 626963 626880 a e 633811 592 b -e 633811 633728 a e 641747 592 b -e 641747 641664 a e 647827 592 b -e 647827 647744 a e 653779 592 b -e 653779 653696 a e 659923 592 b -e 659923 659840 a e 666963 592 b -e 666963 666880 a e 673491 592 b -e 673491 673408 a e 679315 592 b -e 679315 679232 a e 684883 592 b -e 684883 684800 a e 690899 592 b -e 690899 690816 a e 692563 592 b -e 692563 690816 a e 691720 592 b -e 691859 691720 b -e 691859 691776 a e 693320 592 b -e 693459 693320 b -e 693459 693376 a e 698835 592 b -e 698835 698752 a e 706515 592 b -e 706515 706432 a e 714067 592 b -e 714067 713984 a e 720403 592 b -e 720403 720320 a e 726995 592 b -e 726995 726912 a e 735827 592 b -e 735827 735744 a e 742739 592 b -e 742739 742656 a e 749395 592 b -e 749395 749312 a e 751304 592 b -e 751443 751304 b -e 751443 751360 a e 758227 592 b -e 758227 758144 a e 760648 592 b -e 760787 760648 b -e 760787 760704 a e 766419 592 b -e 766419 766336 a e 772435 592 b -e 772435 772352 a e 780819 592 b -e 780819 780736 a e 789587 592 b -e 789587 789504 a e 792264 592 b -e 792403 792264 b -e 792403 792320 a e 799443 592 b -e 799443 799360 a e 801864 592 b -e 802003 801864 b -e 802003 801920 a e 808147 592 b -e 808147 808064 a e 813715 592 b -e 813715 813632 a e 817808 592 ba -e 819968 817808 a -e 820035 819968 a e 822291 592 b -e 822291 822208 a e 827155 592 b -e 827155 822208 a e 833811 592 b -e 833811 833728 a e 837584 592 ba -e 840467 837584 b -e 840467 840384 a -e 842387 837584 b -e 842387 840384 a -e 841608 837584 b -e 841747 841608 b -e 841747 841664 a -e 843144 837584 b -e 843283 843144 b -e 843283 843200 a -e 840384 837584 a -e 841664 840384 a -e 843200 840384 a e 848915 592 b -e 848915 848832 a e 854867 592 b -e 854867 854784 a e 862611 592 b -e 862611 862528 a e 864968 592 b -e 865107 864968 b -e 865107 865024 a e 870931 592 b -e 870931 870848 a e 877139 592 b -e 877139 877056 a e 883091 592 b -e 883091 883008 a e 892179 592 b -e 892179 892096 a e 895827 592 b -e 895827 892096 a e 897491 592 b -e 897491 892096 a e 894984 592 b -e 895123 894984 b -e 895123 895040 a e 896648 592 b -e 896787 896648 b -e 896787 896704 a e 898312 592 b -e 898451 898312 b -e 898451 898368 a e 905043 592 b -e 905043 904960 a e 913875 592 b -e 913875 913792 a e 916168 592 b -e 916307 916168 b -e 916307 916224 a e 922003 592 b -e 922003 921920 a e 927443 592 b -e 927443 927360 a e 933075 592 b -e 933075 932992 a e 939155 592 b -e 939155 939072 a e 946131 592 b -e 946131 946048 a e 953427 592 b -e 953427 953344 a e 965203 592 b -e 965203 965120 a e 967635 592 b -e 967635 965120 a e 969299 592 b -e 969299 965120 a e 966792 592 b -e 966931 966792 b -e 966931 966848 a e 968456 592 b -e 968595 968456 b -e 968595 968512 a e 970120 592 b -e 970259 970120 b -e 970259 970176 a e 976019 592 b -e 976019 975936 a e 981203 592 b -e 981203 981120 a e 986259 592 b -e 986259 986176 a e 992083 592 b -e 992083 992000 a e 994056 592 b -e 994195 994056 b -e 994195 994112 a e 999827 592 b -e 999827 999744 a e 1006227 592 b -e 1006227 1006144 a e 1007880 592 b -e 1008019 1007880 b -e 1008019 1007936 a e 1014611 592 b -e 1014611 1014528 a e 1016648 592 b -e 1016787 1016648 b -e 1016787 1016704 a e 1022739 592 b -e 1022739 1022656 a e 1023944 592 b -e 1024083 1023944 b -e 1024083 1024000 a e 1030355 592 b -e 1030355 1030272 a e 1032008 592 b -e 1032147 1032008 b -e 1032147 1032064 a e 1042771 592 b -e 1042771 1042688 a e 1044040 592 b -e 1044179 1044040 b -e 1044179 1044096 a e 1054867 592 b -e 1054867 1054784 a e 1064211 592 b -e 1064211 1064128 a e 1066771 592 b -e 1066771 1064128 a e 1065928 592 b -e 1066067 1065928 b -e 1066067 1065984 a e 1075219 592 b -e 1075219 1075136 a e 1077128 592 b -e 1077267 1077128 b -e 1077267 1077184 a e 1089299 592 b -e 1089299 1089216 a e 1124435 592 b -e 1124435 1124352 a e 1126867 592 b -e 1126867 1124352 a e 1128403 592 b -e 1128403 1124352 a e 1130003 592 b -e 1130003 1124352 a e 1126024 592 b -e 1126163 1126024 b -e 1126163 1126080 a e 1127624 592 b -e 1127763 1127624 b -e 1127763 1127680 a e 1129160 592 b -e 1129299 1129160 b -e 1129299 1129216 a e 1136019 592 b -e 1136019 1135936 a e 1142419 592 b -e 1142419 1142336 a e 1147731 592 b -e 1147731 1147648 a e 1152979 592 b -e 1152979 1152896 a e 1158803 592 b -e 1158803 1158720 a e 1164819 592 b -e 1164819 1164736 a e 1166024 592 b -e 1166163 1166024 b -e 1166163 1166080 a e 1173387 592 b e 1177235 592 b -e 1177235 1177152 a e 1179155 592 b -e 1179155 1177152 a e 1178376 592 b -e 1178515 1178376 b -e 1178515 1178432 a e 1185235 592 b -e 1185235 1185152 a e 1186824 592 b -e 1186963 1186824 b -e 1186963 1186880 a e 1193875 592 b -e 1193875 1193792 a e 1195923 592 b -e 1195923 1193792 a e 1197587 592 b -e 1197587 1193792 a e 1195080 592 b -e 1195219 1195080 b -e 1195219 1195136 a e 1196744 592 b -e 1196883 1196744 b -e 1196883 1196800 a e 1198408 592 b -e 1198547 1198408 b -e 1198547 1198464 a e 1204371 592 b -e 1204371 1204288 a e 1209811 592 b -e 1209811 1209728 a e 1215379 592 b -e 1215379 1215296 a e 1223499 592 b e 1226771 592 b -e 1226771 1226688 a e 1232403 592 b -e 1232403 1232320 a e 1237779 592 b -e 1237779 1237696 a e 1242064 592 ba -e 1244179 1242064 b -e 1244179 1244096 a -e 1244096 1242064 a e 1250387 592 b -e 1250387 1250304 a e 1255571 592 b -e 1255571 1255488 a e 1260563 592 b -e 1260563 1260480 a e 1265427 592 b -e 1265427 1265344 a e 1293587 592 b -e 1293587 1293504 a e 1307411 592 b -e 1307411 1307328 a e 1312723 592 b -e 1312723 1312640 a e 1328979 592 b -e 1328979 1328896 a e 1338259 592 b -e 1338259 1338176 a e 1344595 592 b -e 1344595 1344512 a e 1350163 592 b -e 1350163 1350080 a e 1364307 592 b -e 1364307 1364224 a e 1369363 592 b -e 1369363 1369280 a e 1372816 592 ba -e 1374931 1372816 b -e 1374931 1374848 a -e 1374848 1372816 a e 1381139 592 b -e 1381139 1381056 a e 1386451 592 b -e 1386451 1386368 a e 1389904 592 ba -e 1392019 1389904 b -e 1392019 1391936 a -e 1391936 1389904 a e 1396432 592 ba -e 1398419 1396432 b -e 1398419 1398336 a -e 1398336 1396432 a e 1404243 592 b -e 1404243 1404160 a e 1407760 592 ba -e 1409939 1407760 b -e 1409939 1409856 a -e 1409856 1407760 a e 1431376 592 ba -e 1433171 1431376 b -e 1433171 1433088 a -e 1433088 1431376 a e 1451731 592 b -e 1451731 1451648 a e 1457107 592 b -e 1457107 1457024 a e 1462483 592 b -e 1462483 1462400 a e 1472595 592 b -e 1472595 1472512 a e 1477843 592 b -e 1477843 1477760 a e 1481808 592 ba -e 1483923 1481808 b -e 1483923 1483840 a -e 1483840 1481808 a e 1503251 592 b -e 1503251 1503168 a e 1511123 592 b -e 1511123 1511040 a e 1514248 592 b -e 1514387 1514248 b -e 1514387 1514304 a e 1520851 592 b -e 1520851 1520768 a e 1522120 592 b -e 1522259 1522120 b -e 1522259 1522176 a e 1529491 592 b -e 1529491 1529408 a e 1532243 592 b -e 1532243 1529408 a e 1531400 592 b -e 1531539 1531400 b -e 1531539 1531456 a e 1543571 592 b -e 1543571 1543488 a e 1551763 592 b -e 1551763 1551680 a e 1555091 592 b -e 1555091 1551680 a e 1554248 592 b -e 1554387 1554248 b -e 1554387 1554304 a e 1564819 592 b -e 1564819 1564736 a e 1571923 592 b -e 1571923 1571840 a e 1577363 592 b -e 1577363 1577280 a e 1584787 592 b -e 1584787 1584704 a e 1587347 592 b -e 1587347 1584704 a e 1586504 592 b -e 1586643 1586504 b -e 1586643 1586560 a e 1588232 592 b -e 1588371 1588232 b -e 1588371 1588288 a e 1594451 592 b -e 1594451 1594368 a e 1601107 592 b -e 1601107 1601024 a e 1608275 592 b -e 1608275 1608192 a e 1610771 592 b -e 1610771 1608192 a e 1609928 592 b -e 1610067 1609928 b -e 1610067 1609984 a e 1611592 592 b -e 1611731 1611592 b -e 1611731 1611648 a e 1618707 592 b -e 1618707 1618624 a e 1630227 592 b -e 1630227 1630144 a e 1639251 592 b -e 1639251 1639168 a e 1647571 592 b -e 1647571 1647488 a e 1658323 592 b -e 1658323 1658240 a e 1668243 592 b -e 1668243 1668160 a e 1671571 592 b -e 1671571 1668160 a e 1670728 592 b -e 1670867 1670728 b -e 1670867 1670784 a e 1677843 592 b -e 1677843 1677760 a e 1679496 592 b -e 1679635 1679496 b -e 1679635 1679552 a e 1689555 592 b -e 1689555 1689472 a e 1691987 592 b -e 1691987 1689472 a e 1691144 592 b -e 1691283 1691144 b -e 1691283 1691200 a e 1705235 592 b -e 1705235 1705152 a e 1707283 592 b -e 1707283 1705152 a e 1706440 592 b -e 1706579 1706440 b -e 1706579 1706496 a e 1714387 592 b -e 1714387 1714304 a e 1716435 592 b -e 1716435 1714304 a e 1715592 592 b -e 1715731 1715592 b -e 1715731 1715648 a e 1717256 592 b -e 1717395 1717256 b -e 1717395 1717312 a e 1722579 592 b -e 1722579 1722496 a e 1727955 592 b -e 1727955 1727872 a e 1736595 592 b -e 1736595 1736512 a e 1740048 592 ba -e 1741971 1740048 b -e 1741971 1741888 a -e 1741888 1740048 a e 1747667 592 b -e 1747667 1747584 a e 1753491 592 b -e 1753491 1753408 a e 1763027 592 b -e 1763027 1762944 a e 1768787 592 b -e 1768787 1762944 a e 1768008 592 b -e 1768147 1768008 b -e 1768147 1768064 a e 1780115 592 b -e 1780115 1780032 a e 1781832 592 b -e 1781971 1781832 b -e 1781971 1781888 a e 1788307 592 b -e 1788307 1788224 a e 1789576 592 b -e 1789715 1789576 b -e 1789715 1789632 a e 1800083 592 b -e 1800083 1800000 a e 1801288 592 b -e 1801427 1801288 b -e 1801427 1801344 a e 1811923 592 b -e 1811923 1811840 a e 1820499 592 b -e 1820499 1820416 a e 1823952 592 ba -e 1826067 1823952 b -e 1826067 1825984 a -e 1825984 1823952 a e 1832019 592 b -e 1832019 1831936 a e 1837523 592 b -e 1837523 1837440 a e 1844051 592 b -e 1844051 1843968 a e 1851411 592 b -e 1851411 1851328 a e 1856723 592 b -e 1856723 1856640 a e 1862099 592 b -e 1862099 1862016 a e 1867347 592 b -e 1867347 1867264 a e 1877779 592 b -e 1877779 1877696 a e 1885651 592 b -e 1885651 1885568 a e 1891795 592 b -e 1891795 1891712 a e 1895184 592 ba -e 1897299 1895184 b -e 1897299 1897216 a -e 1897216 1895184 a e 1902931 592 b -e 1902931 1902848 a e 1907792 592 ba -e 1910291 1907792 b -e 1910291 1910208 a -e 1910208 1907792 a e 1917651 592 b -e 1917651 1917568 a e 1923603 592 b -e 1923603 1923520 a e 1927632 592 ba -e 1929875 1927632 b -e 1929875 1929792 a -e 1929792 1927632 a e 1934416 592 ba -e 1936467 1934416 b -e 1936467 1936384 a -e 1936384 1934416 a e 1940496 592 ba -e 1942739 1940496 b -e 1942739 1942656 a -e 1942656 1940496 a e 1949075 592 b -e 1949075 1948992 a e 1953936 592 ba -e 1956499 1953936 b -e 1956499 1956416 a -e 1956416 1953936 a e 1962064 592 ba -e 1964627 1962064 b -e 1964627 1964544 a -e 1964544 1962064 a e 1975891 592 b -e 1975891 1975808 a e 1982099 592 b -e 1982099 1975808 a e 1981256 592 b -e 1981395 1981256 b -e 1981395 1981312 a e 1982472 592 b -e 1982611 1982472 b -e 1982611 1982528 a e 1990803 592 b -e 1990803 1990720 a e 1993747 592 b -e 1993747 1990720 a e 1992904 592 b -e 1993043 1992904 b -e 1993043 1992960 a e 1994504 592 b -e 1994643 1994504 b -e 1994643 1994560 a e 2000275 592 b -e 2000275 2000192 a e 2005587 592 b -e 2005587 2005504 a e 2012499 592 b -e 2012499 2012416 a e 2015315 592 b -e 2015315 2012416 a e 2014472 592 b -e 2014611 2014472 b -e 2014611 2014528 a e 2016072 592 b -e 2016211 2016072 b -e 2016211 2016128 a e 2024080 592 ba -e 2026067 2024080 b -e 2026067 2025984 a -e 2025984 2024080 a e 2031955 592 b -e 2031955 2031872 a e 2038099 592 b -e 2038099 2038016 a e 2043859 592 b -e 2043859 2043776 a e 2049491 592 b -e 2049491 2049408 a e 2055187 592 b -e 2055187 2055104 a e 2067984 592 ba -e 2070163 2067984 b -e 2070163 2070080 a -e 2070080 2067984 a e 2075731 592 b -e 2075731 2075648 a e 2085776 592 ba -e 2087891 2085776 b -e 2087891 2087808 a -e 2087808 2085776 a e 2091984 592 ba -e 2094099 2091984 b -e 2094099 2094016 a -e 2094016 2091984 a e 2108051 592 b -e 2108051 2107968 a e 2113363 592 b -e 2113363 2113280 a e 2137360 592 ba -e 2139347 2137360 b -e 2139347 2139264 a -e 2139264 2137360 a e 2145043 592 b -e 2145043 2144960 a e 2149971 592 b -e 2149971 2149888 a e 2159507 592 b -e 2159507 2159424 a e 2160328 592 b -e 2160467 2160328 b -e 2160467 2160384 a e 2166099 592 b -e 2166099 2166016 a e 2167368 592 b -e 2167507 2167368 b -e 2167507 2167424 a e 2177683 592 b -e 2177683 2177600 a e 2185163 592 b e 2190283 592 b e 2191699 592 b -e 2191699 2191616 a e 2192915 592 b -e 2192915 2192832 a e 2198547 592 b -e 2198547 2198464 a e 2204115 592 b -e 2204115 2204032 a e 2210387 592 b -e 2210387 2210304 a e 2215571 592 b -e 2215571 2215488 a e 2219155 592 b -e 2219155 2219072 a e 2220115 592 b -e 2220115 2220032 a e 2225811 592 b -e 2225811 2225728 a e 2230163 592 b -e 2230163 2230080 a e 2237587 592 b -e 2237587 2237504 a e 2243795 592 b -e 2243795 2243712 a e 2250515 592 b -e 2250515 2250432 a e 2256659 592 b -e 2256659 2256576 a e 2271315 592 b -e 2271315 2271232 a e 2283347 592 b -e 2283347 2283264 a e 2290451 592 b -e 2290451 2290368 a e 2297235 592 b -e 2297235 2297152 a e 2302803 592 b -e 2302803 2302720 a e 2308563 592 b -e 2308563 2308480 a e 2314963 592 b -e 2314963 2314880 a e 2328147 592 b -e 2328147 2328064 a e 2339091 592 b -e 2339091 2339008 a e 2344723 592 b -e 2344723 2344640 a e 2350483 592 b -e 2350483 2350400 a e 2361491 592 b -e 2361491 2361408 a e 2367251 592 b -e 2367251 2367168 a e 2380883 592 b -e 2380883 2380800 a e 2409043 592 b -e 2409043 2408960 a e 2421587 592 b -e 2421587 2421504 a e 2427219 592 b -e 2427219 2427136 a e 2448019 592 b -e 2448019 2447936 a e 2453907 592 b -e 2453907 2453824 a e 2460755 592 b -e 2460755 2460672 a e 2466451 592 b -e 2466451 2466368 a e 2472915 592 b -e 2472915 2472832 a e 2478611 592 b -e 2478611 2478528 a e 2494611 592 b -e 2494611 2494528 a e 2499987 592 b -e 2499987 2499904 a e 2514579 592 b -e 2514579 2514496 a e 2525971 592 b -e 2525971 2525888 a e 2538067 592 b -e 2538067 2537984 a e 2544019 592 b -e 2544019 2543936 a e 2551123 592 b -e 2551123 2551040 a e 2558099 592 b -e 2558099 2558016 a e 2564115 592 b -e 2564115 2564032 a e 2584915 592 b -e 2584915 2584832 a e 2595347 592 b -e 2595347 2595264 a e 2607443 592 b -e 2607443 2607360 a e 2609608 592 b -e 2609747 2609608 b -e 2609747 2609664 a e 2615763 592 b -e 2615763 2615680 a e 2623187 592 b -e 2623187 2623104 a e 2628883 592 b -e 2628883 2628800 a e 2634515 592 b -e 2634515 2634432 a e 2640147 592 b -e 2640147 2640064 a e 2645779 592 b -e 2645779 2645696 a e 2651603 592 b -e 2651603 2651520 a e 2699987 592 b -e 2699987 2699904 a e 2722771 592 b -e 2722771 2722688 a e 2737107 592 b -e 2737107 2737024 a e 2750611 592 b -e 2750611 2750528 a e 2760531 592 b -e 2760531 2760448 a e 2776851 592 b -e 2776851 2776768 a e 2787731 592 b -e 2787731 2787648 a e 2798803 592 b -e 2798803 2798720 a e 2804563 592 b -e 2804563 2804480 a e 2812880 592 ba -e 2816851 2812880 b -e 2816851 2816768 a -e 2816768 2812880 a e 2828304 592 ba -e 2830483 2828304 b -e 2830483 2830400 a -e 2830400 2828304 a e 2853395 592 b -e 2853395 2853312 a e 2873299 592 b -e 2873299 2873216 a e 2883603 592 b -e 2883603 2883520 a e 2899347 592 b -e 2899347 2899264 a e 2904907 592 b e 2905107 592 b -e 2905107 2904960 a e 2908107 592 b e 2911827 592 b -e 2911827 2911744 a e 2932691 592 b -e 2932691 2932608 a e 2938515 592 b -e 2938515 2938432 a e 2960851 592 b -e 2960851 2960768 a e 2966483 592 b -e 2966483 2966400 a e 2972243 592 b -e 2972243 2972160 a e 2992851 592 b -e 2992851 2992768 a e 3004947 592 b -e 3004947 3004864 a e 3011283 592 b -e 3011283 3011200 a e 3029843 592 b -e 3029843 3029760 a e 3035539 592 b -e 3035539 3035456 a e 3041299 592 b -e 3041299 3041216 a e 3047763 592 b -e 3047763 3047680 a e 3053971 592 b -e 3053971 3053888 a e 3096851 592 b -e 3096851 3096768 a e 3102483 592 b -e 3102483 3102400 a e 3113107 592 b -e 3113107 3113024 a e 3118995 592 b -e 3118995 3118912 a e 3124819 592 b -e 3124819 3124736 a e 3130643 592 b -e 3130643 3130560 a e 3142419 592 b -e 3142419 3142336 a e 3155091 592 b -e 3155091 3155008 a e 3166675 592 b -e 3166675 3166592 a e 3176787 592 b -e 3176787 3176704 a e 3182227 592 b -e 3182227 3182144 a e 3187859 592 b -e 3187859 3187776 a e 3199059 592 b -e 3199059 3198976 a e 3204627 592 b -e 3204627 3204544 a e 3220371 592 b -e 3220371 3220288 a e 3233683 592 b -e 3233683 3233600 a e 3239507 592 b -e 3239507 3239424 a e 3246035 592 b -e 3246035 3245952 a e 3257107 592 b -e 3257107 3257024 a e 3260688 592 ba -e 3262931 3260688 b -e 3262931 3262848 a -e 3262848 3260688 a e 3268048 592 ba -e 3269971 3268048 b -e 3269971 3269888 a -e 3269888 3268048 a e 3273872 592 ba -e 3277579 3273872 b -e 3277635 3273872 a e 3281939 592 b -e 3281939 3281856 a e 3307155 592 b -e 3307155 3307072 a e 3357779 592 b -e 3357779 3357696 a e 3365075 592 b -e 3365075 3364992 a e 3372499 592 b -e 3372499 3372416 a e 3378067 592 b -e 3378067 3377984 a e 3383763 592 b -e 3383763 3383680 a e 3389843 592 b -e 3389843 3389760 a e 3391368 592 b -e 3391507 3391368 b -e 3391507 3391424 a e 3404243 592 b -e 3404243 3404160 a e 3411347 592 b -e 3411347 3411264 a e 3412552 592 b -e 3412691 3412552 b -e 3412691 3412608 a e 3418131 592 b -e 3418131 3418048 a e 3425171 592 b -e 3425171 3425088 a e 3427784 592 b -e 3427923 3427784 b -e 3427923 3427840 a e 3434131 592 b -e 3434131 3434048 a e 3440659 592 b -e 3440659 3440576 a e 3452179 592 b -e 3452179 3452096 a e 3453896 592 b -e 3454035 3453896 b -e 3454035 3453952 a e 3461011 592 b -e 3461011 3460928 a e 3463176 592 b -e 3463315 3463176 b -e 3463315 3463232 a e 3469011 592 b -e 3469011 3468928 a e 3484563 592 b -e 3484563 3484480 a e 3485587 592 b -e 3485587 3485504 a e 3495827 592 b -e 3495827 3495744 a e 3502931 592 b -e 3502931 3502848 a e 3508691 592 b -e 3508691 3508608 a e 3513747 592 b -e 3513747 3513664 a e 3520339 592 b -e 3520339 3520256 a e 3522771 592 b -e 3522771 3520256 a e 3521928 592 b -e 3522067 3521928 b -e 3522067 3521984 a e 3523592 592 b -e 3523731 3523592 b -e 3523731 3523648 a e 3529875 592 b -e 3529875 3529792 a e 3531080 592 b -e 3531219 3531080 b -e 3531219 3531136 a e 3537171 592 b -e 3537171 3537088 a e 3544147 592 b -e 3544147 3544064 a e 3550803 592 b -e 3550803 3550720 a e 3558355 592 b -e 3558355 3558272 a e 3564115 592 b -e 3564115 3564032 a e 3569939 592 b -e 3569939 3569856 a e 3576211 592 b -e 3576211 3576128 a e 3582035 592 b -e 3582035 3581952 a e 3593043 592 b -e 3593043 3592960 a e 3598547 592 b -e 3598547 3598464 a e 3604435 592 b -e 3604435 3604352 a e 3605768 592 b -e 3605907 3605768 b -e 3605907 3605824 a e 3612755 592 b -e 3612755 3612672 a e 3614472 592 b -e 3614611 3614472 b -e 3614611 3614528 a e 3621139 592 b -e 3621139 3621056 a e 3622408 592 b -e 3622547 3622408 b -e 3622547 3622464 a e 3628371 592 b -e 3628371 3628288 a e 3629192 592 b -e 3629331 3629192 b -e 3629331 3629248 a e 3635347 592 b -e 3635347 3635264 a e 3637000 592 b -e 3637139 3637000 b -e 3637139 3637056 a e 3643027 592 b -e 3643027 3642944 a e 3649875 592 b -e 3649875 3649792 a e 3651528 592 b -e 3651667 3651528 b -e 3651667 3651584 a e 3656851 592 b -e 3656851 3656768 a e 3662803 592 b -e 3662803 3662720 a e 3664456 592 b -e 3664595 3664456 b -e 3664595 3664512 a e 3668240 592 ba -e 3670035 3668240 b -e 3670035 3669952 a -e 3669952 3668240 a e 3684883 592 b -e 3684883 3684800 a e 3686867 592 b -e 3686867 3684800 a e 3688467 592 b -e 3688467 3684800 a e 3689619 592 b -e 3689619 3684800 a e 3686024 592 b -e 3686163 3686024 b -e 3686163 3686080 a e 3687624 592 b -e 3687763 3687624 b -e 3687763 3687680 a e 3688840 592 b -e 3688979 3688840 b -e 3688979 3688896 a e 3689992 592 b -e 3690131 3689992 b -e 3690131 3690048 a e 3695763 592 b -e 3695763 3695680 a e 3701139 592 b -e 3701139 3701056 a e 3701896 592 b -e 3702035 3701896 b -e 3702035 3701952 a e 3707219 592 b -e 3707219 3707136 a e 3708360 592 b -e 3708499 3708360 b -e 3708499 3708416 a e 3713555 592 b -e 3713555 3713472 a e 3718803 592 b -e 3718803 3718720 a e 3719944 592 b -e 3720083 3719944 b -e 3720083 3720000 a e 3725267 592 b -e 3725267 3725184 a e 3730451 592 b -e 3730451 3730368 a e 3735955 592 b -e 3735955 3735872 a e 3743571 592 b -e 3743571 3743488 a e 3745096 592 b -e 3745235 3745096 b -e 3745235 3745152 a e 3750867 592 b -e 3750867 3750784 a e 3766803 592 b -e 3766803 3766720 a e 3782099 592 b -e 3782099 3782016 a e 3790355 592 b -e 3790355 3790272 a e 3799635 592 b -e 3799635 3799552 a e 3802067 592 b -e 3802067 3799552 a e 3803731 592 b -e 3803731 3799552 a e 3801224 592 b -e 3801363 3801224 b -e 3801363 3801280 a e 3802888 592 b -e 3803027 3802888 b -e 3803027 3802944 a e 3812883 592 b -e 3812883 3812800 a e 3822675 592 b -e 3822675 3822592 a e 3825107 592 b -e 3825107 3822592 a e 3826771 592 b -e 3826771 3822592 a e 3824264 592 b -e 3824403 3824264 b -e 3824403 3824320 a e 3825928 592 b -e 3826067 3825928 b -e 3826067 3825984 a e 3837715 592 b -e 3837715 3837632 a e 3838920 592 b -e 3839059 3838920 b -e 3839059 3838976 a e 3845779 592 b -e 3845779 3845696 a e 3848072 592 b -e 3848211 3848072 b -e 3848211 3848128 a e 3856915 592 b -e 3856915 3856832 a e 3859411 592 b -e 3859411 3856832 a e 3861075 592 b -e 3861075 3856832 a e 3862355 592 b -e 3862355 3856832 a e 3858568 592 b -e 3858707 3858568 b -e 3858707 3858624 a e 3860232 592 b -e 3860371 3860232 b -e 3860371 3860288 a e 3861512 592 b -e 3861651 3861512 b -e 3861651 3861568 a e 3863560 592 b -e 3863699 3863560 b -e 3863699 3863616 a e 3869715 592 b -e 3869715 3869632 a e 3878803 592 b -e 3878803 3878720 a e 3881235 592 b -e 3881235 3878720 a e 3882899 592 b -e 3882899 3878720 a e 3880392 592 b -e 3880531 3880392 b -e 3880531 3880448 a e 3882056 592 b -e 3882195 3882056 b -e 3882195 3882112 a e 3883720 592 b -e 3883859 3883720 b -e 3883859 3883776 a e 3893203 592 b -e 3893203 3893120 a e 3896467 592 b -e 3896467 3893120 a e 3898131 592 b -e 3898131 3893120 a e 3899411 592 b -e 3899411 3893120 a e 3895624 592 b -e 3895763 3895624 b -e 3895763 3895680 a e 3897288 592 b -e 3897427 3897288 b -e 3897427 3897344 a e 3898568 592 b -e 3898707 3898568 b -e 3898707 3898624 a e 3900616 592 b -e 3900755 3900616 b -e 3900755 3900672 a e 3907731 592 b -e 3907731 3907648 a e 3918739 592 b -e 3918739 3918656 a e 3921171 592 b -e 3921171 3918656 a e 3922835 592 b -e 3922835 3918656 a e 3924499 592 b -e 3924499 3918656 a e 3920328 592 b -e 3920467 3920328 b -e 3920467 3920384 a e 3921992 592 b -e 3922131 3921992 b -e 3922131 3922048 a e 3923656 592 b -e 3923795 3923656 b -e 3923795 3923712 a e 3925256 592 b -e 3925395 3925256 b -e 3925395 3925312 a e 3931603 592 b -e 3931603 3931520 a e 3938003 592 b -e 3938003 3937920 a e 3939272 592 b -e 3939411 3939272 b -e 3939411 3939328 a e 3946323 592 b -e 3946323 3946240 a e 3948243 592 b -e 3948243 3946240 a e 3949779 592 b -e 3949779 3946240 a e 3947464 592 b -e 3947603 3947464 b -e 3947603 3947520 a e 3949000 592 b -e 3949139 3949000 b -e 3949139 3949056 a e 3950536 592 b -e 3950675 3950536 b -e 3950675 3950592 a e 3956307 592 b -e 3956307 3956224 a e 3962579 592 b -e 3962579 3962496 a e 3964755 592 b -e 3964755 3962496 a e 3963912 592 b -e 3964051 3963912 b -e 3964051 3963968 a e 3965640 592 b -e 3965779 3965640 b -e 3965779 3965696 a e 3971411 592 b -e 3971411 3971328 a e 3978387 592 b -e 3978387 3978304 a e 3981064 592 b -e 3981203 3981064 b -e 3981203 3981120 a e 3988691 592 b -e 3988691 3988608 a e 4001427 592 b -e 4001427 4001344 a e 4006355 592 b -e 4006355 4006272 a e 4012755 592 b -e 4012755 4012672 a e 4026643 592 b -e 4026643 4026560 a e 4030160 592 ba -e 4032275 4030160 b -e 4032275 4032192 a -e 4032192 4030160 a e 4038547 592 b -e 4038547 4038464 a e 4043859 592 b -e 4043859 4043776 a e 4047824 592 ba -e 4049939 4047824 b -e 4049939 4049856 a -e 4049856 4047824 a e 4054032 592 ba -e 4056275 4054032 b -e 4056275 4056192 a -e 4056192 4054032 a e 4062227 592 b -e 4062227 4062144 a e 4068243 592 b -e 4068243 4068160 a e 4074899 592 b -e 4074899 4074816 a e 4082323 592 b -e 4082323 4082240 a e 4084691 592 b -e 4084691 4082240 a e 4083848 592 b -e 4083987 4083848 b -e 4083987 4083904 a e 4085064 592 b -e 4085203 4085064 b -e 4085203 4085120 a e 4090259 592 b -e 4090259 4090176 a e 4095187 592 b -e 4095187 4095104 a e 4096712 592 b -e 4096851 4096712 b -e 4096851 4096768 a e 4102355 592 b -e 4102355 4102272 a e 4137168 592 ba -e 4139347 4137168 b -e 4139347 4139264 a -e 4139264 4137168 a e 4145363 592 b -e 4145363 4145280 a e 4153171 592 b -e 4153171 4153088 a e 4155155 592 b -e 4155155 4153088 a e 4156435 592 b -e 4156435 4153088 a e 4158035 592 b -e 4158035 4153088 a e 4154312 592 b -e 4154451 4154312 b -e 4154451 4154368 a e 4155592 592 b -e 4155731 4155592 b -e 4155731 4155648 a e 4157192 592 b -e 4157331 4157192 b -e 4157331 4157248 a e 4158792 592 b -e 4158931 4158792 b -e 4158931 4158848 a e 4166419 592 b -e 4166419 4166336 a e 4168851 592 b -e 4168851 4166336 a e 4170515 592 b -e 4170515 4166336 a e 4168008 592 b -e 4168147 4168008 b -e 4168147 4168064 a e 4169672 592 b -e 4169811 4169672 b -e 4169811 4169728 a e 4171336 592 b -e 4171475 4171336 b -e 4171475 4171392 a e 4177171 592 b -e 4177171 4177088 a e 4182867 592 b -e 4182867 4182784 a e 4189075 592 b -e 4189075 4188992 a e 4192203 592 b e 4195723 592 b e 4196491 592 b e 4213520 592 ba -e 4215699 4213520 b -e 4215699 4215616 a -e 4215616 4213520 a e 4227280 592 ba -e 4229331 4227280 b -e 4229331 4229248 a -e 4229248 4227280 a e 4232912 592 ba -e 4234963 4232912 b -e 4234963 4234880 a -e 4234880 4232912 a e 4240275 592 b -e 4240275 4240192 a e 4245587 592 b -e 4245587 4245504 a e 4255315 592 b -e 4255315 4255232 a e 4260819 592 b -e 4260819 4255232 a e 4260040 592 b -e 4260179 4260040 b -e 4260179 4260096 a e 4268947 592 b -e 4268947 4268864 a e 4279891 592 b -e 4279891 4279808 a e 4281811 592 b -e 4281811 4279808 a e 4281032 592 b -e 4281171 4281032 b -e 4281171 4281088 a e 4282696 592 b -e 4282835 4282696 b -e 4282835 4282752 a e 4288723 592 b -e 4288723 4288640 a e 4294675 592 b -e 4294675 4294592 a e 4296264 592 b -e 4296403 4296264 b -e 4296403 4296320 a e 4302931 592 b -e 4302931 4302848 a e 4305043 592 b -e 4305043 4302848 a e 4304200 592 b -e 4304339 4304200 b -e 4304339 4304256 a e 4305928 592 b -e 4306067 4305928 b -e 4306067 4305984 a e 4312275 592 b -e 4312275 4312192 a e 4313480 592 b -e 4313619 4313480 b -e 4313619 4313536 a e 4319443 592 b -e 4319443 4319360 a e 4326547 592 b -e 4326547 4326464 a e 4331408 592 ba -e 4333331 4331408 b -e 4333331 4333248 a -e 4333248 4331408 a e 4337168 592 ba -e 4339411 4337168 b -e 4339411 4339328 a -e 4339328 4337168 a e 4344336 592 ba -e 4346323 4344336 b -e 4346323 4346240 a -e 4346240 4344336 a e 4350288 592 ba -e 4353875 4350288 b -e 4353875 4353792 a -e 4356744 4350288 b -e 4356883 4356744 b -e 4356883 4356800 a -e 4353792 4350288 a -e 4356800 4353792 a e 4360720 592 ba -e 4362899 4360720 b -e 4362899 4362816 a -e 4362816 4360720 a e 4367696 592 ba -e 4368080 4367696 ba -e 4368139 4368080 b -e 4368195 4368080 a -e 4372363 4367696 b -e 4372995 4367696 a e 4374416 592 ba -e 4376339 4374416 b -e 4376339 4376256 a -e 4376256 4374416 a e 4384784 592 ba -e 4386707 4384784 b -e 4386707 4386624 a -e 4386624 4384784 a e 4390224 592 ba -e 4392019 4390224 b -e 4392019 4391936 a -e 4391936 4390224 a e 4395408 592 ba -e 4398163 4395408 b -e 4398163 4398080 a -e 4399752 4395408 b -e 4399891 4399752 b -e 4399891 4399808 a -e 4398080 4395408 a -e 4399808 4398080 a e 4403408 592 ba -e 4403792 4403408 ba -e 4403915 4403792 b -e 4404235 4403792 b -e 4404035 4403792 a -e 4404291 4403792 a -e 4405651 4403408 b -e 4405651 4405568 a -e 4406611 4403408 b -e 4406611 4405568 a -e 4406803 4403408 b -e 4406803 4405568 a -e 4406475 4403408 b -e 4406667 4403408 b -e 4408843 4403408 b -e 4407696 4403408 ba -e 4408139 4407696 b -e 4408195 4407696 a -e 4405568 4403408 a -e 4406531 4405568 a -e 4406723 4405568 a -e 4409091 4403408 a e 4410192 592 ba -e 4412371 4410192 b -e 4412371 4412288 a -e 4412288 4410192 a e 4416464 592 ba -e 4419731 4416464 b -e 4419731 4419648 a -e 4421779 4416464 b -e 4421779 4419648 a -e 4420936 4416464 b -e 4421075 4420936 b -e 4421075 4420992 a -e 4422600 4416464 b -e 4422739 4422600 b -e 4422739 4422656 a -e 4419648 4416464 a -e 4420992 4419648 a -e 4422656 4419648 a e 4426448 592 ba -e 4428947 4426448 b -e 4428947 4428864 a -e 4428864 4426448 a e 4438160 592 ba -e 4440083 4438160 b -e 4440083 4440000 a -e 4440000 4438160 a e 4443600 592 ba -e 4446355 4443600 b -e 4446355 4446272 a -e 4447944 4443600 b -e 4448083 4447944 b -e 4448083 4448000 a -e 4446272 4443600 a -e 4448000 4446272 a e 4451600 592 ba -e 4453459 4451600 b -e 4453459 4453376 a -e 4453376 4451600 a e 4456976 592 ba -e 4459155 4456976 b -e 4459155 4459072 a -e 4459072 4456976 a e 4463248 592 ba -e 4466515 4463248 b -e 4466515 4466432 a -e 4468563 4463248 b -e 4468563 4466432 a -e 4467720 4463248 b -e 4467859 4467720 b -e 4467859 4467776 a -e 4469384 4463248 b -e 4469523 4469384 b -e 4469523 4469440 a -e 4466432 4463248 a -e 4467776 4466432 a -e 4469440 4466432 a e 4473232 592 ba -e 4475731 4473232 b -e 4475731 4475648 a -e 4475648 4473232 a e 4480272 592 ba -e 4484883 4480272 b -e 4484883 4484800 a -e 4489288 4480272 b -e 4489427 4489288 b -e 4489427 4489344 a -e 4484800 4480272 a -e 4489344 4484800 a e 4493648 592 ba -e 4494032 4493648 ba -e 4494155 4494032 b -e 4494851 4494032 a -e 4497555 4493648 b -e 4497555 4497472 a -e 4498131 4493648 b -e 4498131 4497472 a -e 4497995 4493648 b -e 4504715 4493648 b -e 4497472 4493648 a -e 4498051 4497472 a -e 4505539 4493648 a e 4507216 592 ba -e 4509267 4507216 b -e 4509267 4509184 a -e 4509184 4507216 a e 4513296 592 ba -e 4516563 4513296 b -e 4516563 4516480 a -e 4518536 4513296 b -e 4518675 4518536 b -e 4518675 4518592 a -e 4516480 4513296 a -e 4518592 4516480 a e 4522384 592 ba -e 4526803 4522384 b -e 4526803 4526720 a -e 4529683 4522384 b -e 4529683 4526720 a -e 4531347 4522384 b -e 4531347 4526720 a -e 4528840 4522384 b -e 4528979 4528840 b -e 4528979 4528896 a -e 4530504 4522384 b -e 4530643 4530504 b -e 4530643 4530560 a -e 4526720 4522384 a -e 4528896 4526720 a -e 4530560 4526720 a e 4536016 592 ba -e 4537875 4536016 b -e 4537875 4537792 a -e 4537792 4536016 a e 4541392 592 ba -e 4543699 4541392 b -e 4543699 4543616 a -e 4543616 4541392 a e 4548304 592 ba -e 4551571 4548304 b -e 4551571 4551488 a -e 4553619 4548304 b -e 4553619 4551488 a -e 4552776 4548304 b -e 4552915 4552776 b -e 4552915 4552832 a -e 4554440 4548304 b -e 4554579 4554440 b -e 4554579 4554496 a -e 4551488 4548304 a -e 4552832 4551488 a -e 4554496 4551488 a e 4558288 592 ba -e 4560787 4558288 b -e 4560787 4560704 a -e 4560704 4558288 a e 4565328 592 ba -e 4569235 4565328 b -e 4569235 4569152 a -e 4571347 4565328 b -e 4571347 4569152 a -e 4573075 4565328 b -e 4573075 4569152 a -e 4574739 4565328 b -e 4574739 4569152 a -e 4570504 4565328 b -e 4570643 4570504 b -e 4570643 4570560 a -e 4572232 4565328 b -e 4572371 4572232 b -e 4572371 4572288 a -e 4573896 4565328 b -e 4574035 4573896 b -e 4574035 4573952 a -e 4569152 4565328 a -e 4570560 4569152 a -e 4572288 4569152 a -e 4573952 4569152 a e 4578640 592 ba -e 4583251 4578640 b -e 4583251 4583168 a -e 4587784 4578640 b -e 4587923 4587784 b -e 4587923 4587840 a -e 4583168 4578640 a -e 4587840 4583168 a e 4592208 592 ba -e 4594963 4592208 b -e 4594963 4594880 a -e 4594880 4592208 a e 4601616 592 ba -e 4603475 4601616 b -e 4603475 4603392 a -e 4603392 4601616 a e 4611216 592 ba -e 4613267 4611216 b -e 4613267 4613184 a -e 4613184 4611216 a e 4617296 592 ba -e 4619219 4617296 b -e 4619219 4619136 a -e 4619136 4617296 a e 4622736 592 ba -e 4625555 4622736 b -e 4625555 4625472 a -e 4625472 4622736 a e 4632784 592 ba -e 4634963 4632784 b -e 4634963 4634880 a -e 4634880 4632784 a e 4639120 592 ba -e 4641107 4639120 b -e 4641107 4641024 a -e 4641024 4639120 a e 4644560 592 ba -e 4646675 4644560 b -e 4646675 4646592 a -e 4646592 4644560 a e 4651152 592 ba -e 4657427 4651152 b -e 4657427 4657344 a -e 4659475 4651152 b -e 4659475 4657344 a -e 4660627 4651152 b -e 4660627 4657344 a -e 4661779 4651152 b -e 4661779 4657344 a -e 4663443 4651152 b -e 4663443 4657344 a -e 4658632 4651152 b -e 4658771 4658632 b -e 4658771 4658688 a -e 4659848 4651152 b -e 4659987 4659848 b -e 4659987 4659904 a -e 4661000 4651152 b -e 4661139 4661000 b -e 4661139 4661056 a -e 4662600 4651152 b -e 4662739 4662600 b -e 4662739 4662656 a -e 4663816 4651152 b -e 4663955 4663816 b -e 4663955 4663872 a -e 4657344 4651152 a -e 4658688 4657344 a -e 4659904 4657344 a -e 4661056 4657344 a -e 4662656 4657344 a -e 4663872 4657344 a e 4667856 592 ba -e 4674131 4667856 b -e 4674131 4674048 a -e 4676179 4667856 b -e 4676179 4674048 a -e 4677331 4667856 b -e 4677331 4674048 a -e 4678611 4667856 b -e 4678611 4674048 a -e 4680275 4667856 b -e 4680275 4674048 a -e 4675336 4667856 b -e 4675475 4675336 b -e 4675475 4675392 a -e 4676552 4667856 b -e 4676691 4676552 b -e 4676691 4676608 a -e 4677768 4667856 b -e 4677907 4677768 b -e 4677907 4677824 a -e 4679432 4667856 b -e 4679571 4679432 b -e 4679571 4679488 a -e 4680648 4667856 b -e 4680787 4680648 b -e 4680787 4680704 a -e 4674048 4667856 a -e 4675392 4674048 a -e 4676608 4674048 a -e 4677824 4674048 a -e 4679488 4674048 a -e 4680704 4674048 a e 4684752 592 ba -e 4686867 4684752 b -e 4686867 4686784 a -e 4686784 4684752 a e 4696211 592 b -e 4696211 4696128 a e 4699795 592 b -e 4699795 4696128 a e 4701075 592 b -e 4701075 4696128 a e 4698952 592 b -e 4699091 4698952 b -e 4699091 4699008 a e 4700232 592 b -e 4700371 4700232 b -e 4700371 4700288 a e 4701512 592 b -e 4701651 4701512 b -e 4701651 4701568 a e 4708435 592 b -e 4708435 4708352 a e 4709704 592 b -e 4709843 4709704 b -e 4709843 4709760 a e 4716243 592 b -e 4716243 4716160 a e 4717512 592 b -e 4717651 4717512 b -e 4717651 4717568 a e 4723795 592 b -e 4723795 4723712 a e 4724936 592 b -e 4725075 4724936 b -e 4725075 4724992 a e 4728528 592 ba -e 4730579 4728528 b -e 4730579 4730496 a -e 4730496 4728528 a e 4734928 592 ba -e 4736979 4734928 b -e 4736979 4736896 a -e 4736896 4734928 a e 899 592 a e 3200 592 a e 8192 592 a @@ -4051,8 +2790,6 @@ e 37632 592 a e 41344 592 a e 42112 592 a e 50112 592 a -e 53696 50112 a -e 54976 50112 a e 60672 592 a e 66880 592 a e 74176 592 a @@ -4061,7 +2798,6 @@ e 93440 592 a e 99712 592 a e 104512 592 a e 112000 592 a -e 114560 112000 a e 120320 592 a e 126464 592 a e 132160 592 a @@ -4090,20 +2826,15 @@ e 297600 592 a e 302528 592 a e 306944 592 a e 312896 592 a -e 315136 312896 a e 320576 592 a e 325056 592 a e 328960 592 a e 334912 592 a -e 337472 334912 a e 343552 592 a -e 344832 343552 a e 350272 592 a e 356032 592 a e 360320 592 a e 366144 592 a -e 367424 366144 a -e 369088 366144 a e 374848 592 a e 381120 592 a e 386880 592 a @@ -4111,30 +2842,20 @@ e 392256 592 a e 397312 592 a e 401792 592 a e 408512 592 a -e 409792 408512 a e 415168 592 a -e 416512 415168 a e 421184 592 a e 426112 592 a e 431168 592 a e 436672 592 a e 443904 592 a -e 445248 443904 a e 452608 592 a -e 453888 452608 a -e 455552 452608 a -e 457216 452608 a -e 458880 452608 a -e 460544 452608 a e 466496 592 a e 471872 592 a e 477824 592 a e 486528 592 a -e 489344 486528 a e 495296 592 a e 500480 592 a e 508032 592 a -e 510848 508032 a e 516416 592 a e 521600 592 a e 527168 592 a @@ -4154,7 +2875,6 @@ e 604544 592 a e 608576 592 a e 613568 592 a e 619840 592 a -e 621632 619840 a e 626880 592 a e 633728 592 a e 641664 592 a @@ -4166,8 +2886,6 @@ e 673408 592 a e 679232 592 a e 684800 592 a e 690816 592 a -e 691776 690816 a -e 693376 690816 a e 698752 592 a e 706432 592 a e 713984 592 a @@ -4176,38 +2894,25 @@ e 726912 592 a e 735744 592 a e 742656 592 a e 749312 592 a -e 751360 749312 a e 758144 592 a -e 760704 758144 a e 766336 592 a e 772352 592 a e 780736 592 a e 789504 592 a -e 792320 789504 a e 799360 592 a -e 801920 799360 a e 808064 592 a e 813632 592 a e 822208 592 a -e 826496 822208 a -e 826563 826496 a -e 827904 822208 a -e 827971 827904 a e 833728 592 a e 848832 592 a e 854784 592 a e 862528 592 a -e 865024 862528 a e 870848 592 a e 877056 592 a e 883008 592 a e 892096 592 a -e 895040 892096 a -e 896704 892096 a -e 898368 892096 a e 904960 592 a e 913792 592 a -e 916224 913792 a e 921920 592 a e 927360 592 a e 932992 592 a @@ -4215,51 +2920,31 @@ e 939072 592 a e 946048 592 a e 953344 592 a e 965120 592 a -e 966848 965120 a -e 968512 965120 a -e 970176 965120 a e 975936 592 a e 981120 592 a e 986176 592 a e 992000 592 a -e 994112 992000 a e 999744 592 a e 1006144 592 a -e 1007936 1006144 a e 1014528 592 a -e 1016704 1014528 a e 1022656 592 a -e 1024000 1022656 a e 1030272 592 a -e 1032064 1030272 a e 1042688 592 a -e 1044096 1042688 a e 1054784 592 a e 1064128 592 a -e 1065984 1064128 a e 1075136 592 a -e 1077184 1075136 a e 1089216 592 a e 1124352 592 a -e 1126080 1124352 a -e 1127680 1124352 a -e 1129216 1124352 a e 1135936 592 a e 1142336 592 a e 1147648 592 a e 1152896 592 a e 1158720 592 a e 1164736 592 a -e 1166080 1164736 a e 1173443 592 a e 1177152 592 a -e 1178432 1177152 a e 1185152 592 a -e 1186880 1185152 a e 1193792 592 a -e 1195136 1193792 a -e 1196800 1193792 a -e 1198464 1193792 a e 1204288 592 a e 1209728 592 a e 1215296 592 a @@ -4290,54 +2975,36 @@ e 1472512 592 a e 1477760 592 a e 1503168 592 a e 1511040 592 a -e 1514304 1511040 a e 1520768 592 a -e 1522176 1520768 a e 1529408 592 a -e 1531456 1529408 a e 1543488 592 a e 1551680 592 a -e 1554304 1551680 a e 1564736 592 a e 1571840 592 a e 1577280 592 a e 1584704 592 a -e 1586560 1584704 a -e 1588288 1584704 a e 1594368 592 a e 1601024 592 a e 1608192 592 a -e 1609984 1608192 a -e 1611648 1608192 a e 1618624 592 a e 1630144 592 a e 1639168 592 a e 1647488 592 a e 1658240 592 a e 1668160 592 a -e 1670784 1668160 a e 1677760 592 a -e 1679552 1677760 a e 1689472 592 a -e 1691200 1689472 a e 1705152 592 a -e 1706496 1705152 a e 1714304 592 a -e 1715648 1714304 a -e 1717312 1714304 a e 1722496 592 a e 1727872 592 a e 1736512 592 a e 1747584 592 a e 1753408 592 a e 1762944 592 a -e 1768064 1762944 a e 1780032 592 a -e 1781888 1780032 a e 1788224 592 a -e 1789632 1788224 a e 1800000 592 a -e 1801344 1800000 a e 1811840 592 a e 1820416 592 a e 1831936 592 a @@ -4355,16 +3022,10 @@ e 1917568 592 a e 1923520 592 a e 1948992 592 a e 1975808 592 a -e 1981312 1975808 a -e 1982528 1975808 a e 1990720 592 a -e 1992960 1990720 a -e 1994560 1990720 a e 2000192 592 a e 2005504 592 a e 2012416 592 a -e 2014528 2012416 a -e 2016128 2012416 a e 2031872 592 a e 2038016 592 a e 2043776 592 a @@ -4373,24 +3034,17 @@ e 2055104 592 a e 2075648 592 a e 2079683 592 a e 2080000 592 a -e 2080067 2080000 a e 2081091 592 a e 2081664 592 a -e 2081731 2081664 a e 2083011 592 a e 2083648 592 a -e 2083715 2083648 a -e 2083777 2083648 a -e 2083843 2083777 a e 2084611 592 a e 2107968 592 a e 2113280 592 a e 2144960 592 a e 2149888 592 a e 2159424 592 a -e 2160384 2159424 a e 2166016 592 a -e 2167424 2166016 a e 2177600 592 a e 2185219 592 a e 2190339 592 a @@ -4433,15 +3087,10 @@ e 2472832 592 a e 2478528 592 a e 2486915 592 a e 2487296 592 a -e 2487363 2487296 a e 2488323 592 a e 2488960 592 a -e 2489027 2488960 a e 2489923 592 a e 2490560 592 a -e 2490627 2490560 a -e 2490689 2490560 a -e 2490755 2490689 a e 2491459 592 a e 2494528 592 a e 2499904 592 a @@ -4455,7 +3104,6 @@ e 2564032 592 a e 2584832 592 a e 2595264 592 a e 2607360 592 a -e 2609664 2607360 a e 2615680 592 a e 2623104 592 a e 2628800 592 a @@ -4465,15 +3113,10 @@ e 2645696 592 a e 2651520 592 a e 2661699 592 a e 2662080 592 a -e 2662147 2662080 a e 2663043 592 a e 2663680 592 a -e 2663747 2663680 a e 2664643 592 a e 2665280 592 a -e 2665347 2665280 a -e 2665409 2665280 a -e 2665475 2665409 a e 2666179 592 a e 2699904 592 a e 2722688 592 a @@ -4486,44 +3129,28 @@ e 2798720 592 a e 2804480 592 a e 2834115 592 a e 2834496 592 a -e 2834563 2834496 a e 2835395 592 a e 2836032 592 a -e 2836099 2836032 a e 2836931 592 a e 2837568 592 a -e 2837635 2837568 a -e 2837697 2837568 a -e 2837763 2837697 a e 2838467 592 a e 2839872 592 a -e 2839939 2839872 a e 2840771 592 a e 2841408 592 a -e 2841475 2841408 a e 2842371 592 a e 2843008 592 a -e 2843075 2843008 a -e 2843137 2843008 a -e 2843203 2843137 a e 2843907 592 a e 2845312 592 a -e 2845379 2845312 a e 2846467 592 a e 2847168 592 a -e 2847235 2847168 a e 2848579 592 a e 2849216 592 a -e 2849283 2849216 a -e 2849345 2849216 a -e 2849411 2849345 a e 2850243 592 a e 2853312 592 a e 2873216 592 a e 2883520 592 a e 2899264 592 a e 2904960 592 a -e 2905027 2904960 a e 2908163 592 a e 2911744 592 a e 2932608 592 a @@ -4533,15 +3160,10 @@ e 2966400 592 a e 2972160 592 a e 2975875 592 a e 2976256 592 a -e 2976323 2976256 a e 2978691 592 a e 2979328 592 a -e 2979395 2979328 a e 2985219 592 a e 2985856 592 a -e 2985923 2985856 a -e 2985985 2985856 a -e 2986051 2985985 a e 2987523 592 a e 2992768 592 a e 3004864 592 a @@ -4553,26 +3175,16 @@ e 3047680 592 a e 3053888 592 a e 3057475 592 a e 3057856 592 a -e 3057923 3057856 a e 3058883 592 a e 3059520 592 a -e 3059587 3059520 a e 3060483 592 a e 3061120 592 a -e 3061187 3061120 a -e 3061249 3061120 a -e 3061315 3061249 a e 3062083 592 a e 3063552 592 a -e 3063619 3063552 a e 3069379 592 a e 3070080 592 a -e 3070147 3070080 a e 3086915 592 a e 3087552 592 a -e 3087619 3087552 a -e 3087681 3087552 a -e 3087747 3087681 a e 3091715 592 a e 3096768 592 a e 3102400 592 a @@ -4601,31 +3213,21 @@ e 3372416 592 a e 3377984 592 a e 3383680 592 a e 3389760 592 a -e 3391424 3389760 a e 3394947 592 a e 3395072 592 a -e 3395139 3395072 a e 3396547 592 a e 3397120 592 a -e 3397187 3397120 a e 3399299 592 a e 3399936 592 a -e 3400003 3399936 a -e 3400065 3399936 a -e 3400131 3400065 a e 3400963 592 a e 3404160 592 a e 3411264 592 a -e 3412608 3411264 a e 3418048 592 a e 3425088 592 a -e 3427840 3425088 a e 3434048 592 a e 3440576 592 a e 3452096 592 a -e 3453952 3452096 a e 3460928 592 a -e 3463232 3460928 a e 3468928 592 a e 3484480 592 a e 3485504 592 a @@ -4634,10 +3236,7 @@ e 3502848 592 a e 3508608 592 a e 3513664 592 a e 3520256 592 a -e 3521984 3520256 a -e 3523648 3520256 a e 3529792 592 a -e 3531136 3529792 a e 3537088 592 a e 3544064 592 a e 3550720 592 a @@ -4649,105 +3248,53 @@ e 3581952 592 a e 3592960 592 a e 3598464 592 a e 3604352 592 a -e 3605824 3604352 a e 3612672 592 a -e 3614528 3612672 a e 3621056 592 a -e 3622464 3621056 a e 3628288 592 a -e 3629248 3628288 a e 3635264 592 a -e 3637056 3635264 a e 3642944 592 a e 3649792 592 a -e 3651584 3649792 a e 3656768 592 a e 3662720 592 a -e 3664512 3662720 a e 3673475 592 a e 3673792 592 a -e 3673859 3673792 a -e 3674624 3673792 a -e 3674691 3674624 a e 3675075 592 a e 3675584 592 a -e 3675651 3675584 a -e 3676800 3675584 a -e 3676867 3676800 a e 3677507 592 a e 3678144 592 a -e 3678211 3678144 a -e 3678273 3678144 a -e 3678339 3678273 a e 3679107 592 a e 3684800 592 a -e 3686080 3684800 a -e 3687680 3684800 a -e 3688896 3684800 a -e 3690048 3684800 a e 3695680 592 a e 3701056 592 a -e 3701952 3701056 a e 3707136 592 a -e 3708416 3707136 a e 3713472 592 a e 3718720 592 a -e 3720000 3718720 a e 3725184 592 a e 3730368 592 a e 3735872 592 a e 3743488 592 a -e 3745152 3743488 a e 3750784 592 a e 3766720 592 a e 3782016 592 a e 3790272 592 a e 3799552 592 a -e 3801280 3799552 a -e 3802944 3799552 a e 3812800 592 a e 3822592 592 a -e 3824320 3822592 a -e 3825984 3822592 a e 3837632 592 a -e 3838976 3837632 a e 3845696 592 a -e 3848128 3845696 a e 3856832 592 a -e 3858624 3856832 a -e 3860288 3856832 a -e 3861568 3856832 a -e 3863616 3856832 a e 3869632 592 a e 3878720 592 a -e 3880448 3878720 a -e 3882112 3878720 a -e 3883776 3878720 a e 3893120 592 a -e 3895680 3893120 a -e 3897344 3893120 a -e 3898624 3893120 a -e 3900672 3893120 a e 3907648 592 a e 3918656 592 a -e 3920384 3918656 a -e 3922048 3918656 a -e 3923712 3918656 a -e 3925312 3918656 a e 3931520 592 a e 3937920 592 a -e 3939328 3937920 a e 3946240 592 a -e 3947520 3946240 a -e 3949056 3946240 a -e 3950592 3946240 a e 3956224 592 a e 3962496 592 a -e 3963968 3962496 a -e 3965696 3962496 a e 3971328 592 a e 3978304 592 a -e 3981120 3978304 a e 3988608 592 a e 4001344 592 a e 4006272 592 a @@ -4759,22 +3306,12 @@ e 4062144 592 a e 4068160 592 a e 4074816 592 a e 4082240 592 a -e 4083904 4082240 a -e 4085120 4082240 a e 4090176 592 a e 4095104 592 a -e 4096768 4095104 a e 4102272 592 a e 4145280 592 a e 4153088 592 a -e 4154368 4153088 a -e 4155648 4153088 a -e 4157248 4153088 a -e 4158848 4153088 a e 4166336 592 a -e 4168064 4166336 a -e 4169728 4166336 a -e 4171392 4166336 a e 4177088 592 a e 4182784 592 a e 4188992 592 a @@ -4784,30 +3321,1493 @@ e 4196547 592 a e 4240192 592 a e 4245504 592 a e 4255232 592 a -e 4260096 4255232 a e 4268864 592 a e 4279808 592 a -e 4281088 4279808 a -e 4282752 4279808 a e 4288640 592 a e 4294592 592 a -e 4296320 4294592 a e 4302848 592 a -e 4304256 4302848 a -e 4305984 4302848 a e 4312192 592 a -e 4313536 4312192 a e 4319360 592 a e 4326464 592 a e 4696128 592 a -e 4699008 4696128 a -e 4700288 4696128 a -e 4701568 4696128 a e 4708352 592 a -e 4709760 4708352 a e 4716160 592 a -e 4717568 4716160 a e 4723712 592 a -e 4724992 4723712 a +e 53779 53640 b +e 55059 54920 b +e 114643 114504 b +e 247955 245968 b +e 247872 245968 a +e 247955 247872 a +e 315219 315080 b +e 337555 337416 b +e 344915 344776 b +e 367507 367368 b +e 369171 369032 b +e 409875 409736 b +e 416595 416456 b +e 445331 445192 b +e 453971 453832 b +e 455635 455496 b +e 457299 457160 b +e 458963 458824 b +e 460627 460488 b +e 489427 489288 b +e 510931 510792 b +e 621715 621576 b +e 691859 691720 b +e 693459 693320 b +e 751443 751304 b +e 760787 760648 b +e 792403 792264 b +e 802003 801864 b +e 819968 817808 a +e 820035 819968 a +e 840467 837584 b +e 842387 837584 b +e 841608 837584 b +e 843144 837584 b +e 840384 837584 a +e 841747 841608 b +e 843283 843144 b +e 840467 840384 a +e 842387 840384 a +e 841664 840384 a +e 843200 840384 a +e 841747 841664 a +e 843283 843200 a +e 865107 864968 b +e 895123 894984 b +e 896787 896648 b +e 898451 898312 b +e 916307 916168 b +e 966931 966792 b +e 968595 968456 b +e 970259 970120 b +e 994195 994056 b +e 1008019 1007880 b +e 1016787 1016648 b +e 1024083 1023944 b +e 1032147 1032008 b +e 1044179 1044040 b +e 1066067 1065928 b +e 1077267 1077128 b +e 1126163 1126024 b +e 1127763 1127624 b +e 1129299 1129160 b +e 1166163 1166024 b +e 1178515 1178376 b +e 1186963 1186824 b +e 1195219 1195080 b +e 1196883 1196744 b +e 1198547 1198408 b +e 1244179 1242064 b +e 1244096 1242064 a +e 1244179 1244096 a +e 1374931 1372816 b +e 1374848 1372816 a +e 1374931 1374848 a +e 1392019 1389904 b +e 1391936 1389904 a +e 1392019 1391936 a +e 1398419 1396432 b +e 1398336 1396432 a +e 1398419 1398336 a +e 1409939 1407760 b +e 1409856 1407760 a +e 1409939 1409856 a +e 1433171 1431376 b +e 1433088 1431376 a +e 1433171 1433088 a +e 1483923 1481808 b +e 1483840 1481808 a +e 1483923 1483840 a +e 1514387 1514248 b +e 1522259 1522120 b +e 1531539 1531400 b +e 1554387 1554248 b +e 1586643 1586504 b +e 1588371 1588232 b +e 1610067 1609928 b +e 1611731 1611592 b +e 1670867 1670728 b +e 1679635 1679496 b +e 1691283 1691144 b +e 1706579 1706440 b +e 1715731 1715592 b +e 1717395 1717256 b +e 1741971 1740048 b +e 1741888 1740048 a +e 1741971 1741888 a +e 1768147 1768008 b +e 1781971 1781832 b +e 1789715 1789576 b +e 1801427 1801288 b +e 1826067 1823952 b +e 1825984 1823952 a +e 1826067 1825984 a +e 1897299 1895184 b +e 1897216 1895184 a +e 1897299 1897216 a +e 1910291 1907792 b +e 1910208 1907792 a +e 1910291 1910208 a +e 1929875 1927632 b +e 1929792 1927632 a +e 1929875 1929792 a +e 1936467 1934416 b +e 1936384 1934416 a +e 1936467 1936384 a +e 1942739 1940496 b +e 1942656 1940496 a +e 1942739 1942656 a +e 1956499 1953936 b +e 1956416 1953936 a +e 1956499 1956416 a +e 1964627 1962064 b +e 1964544 1962064 a +e 1964627 1964544 a +e 1981395 1981256 b +e 1982611 1982472 b +e 1993043 1992904 b +e 1994643 1994504 b +e 2014611 2014472 b +e 2016211 2016072 b +e 2026067 2024080 b +e 2025984 2024080 a +e 2026067 2025984 a +e 2070163 2067984 b +e 2070080 2067984 a +e 2070163 2070080 a +e 2087891 2085776 b +e 2087808 2085776 a +e 2087891 2087808 a +e 2094099 2091984 b +e 2094016 2091984 a +e 2094099 2094016 a +e 2139347 2137360 b +e 2139264 2137360 a +e 2139347 2139264 a +e 2160467 2160328 b +e 2167507 2167368 b +e 2609747 2609608 b +e 2816851 2812880 b +e 2816768 2812880 a +e 2816851 2816768 a +e 2830483 2828304 b +e 2830400 2828304 a +e 2830483 2830400 a +e 3262931 3260688 b +e 3262848 3260688 a +e 3262931 3262848 a +e 3269971 3268048 b +e 3269888 3268048 a +e 3269971 3269888 a +e 3277579 3273872 b +e 3277635 3273872 a +e 3391507 3391368 b +e 3412691 3412552 b +e 3427923 3427784 b +e 3454035 3453896 b +e 3463315 3463176 b +e 3522067 3521928 b +e 3523731 3523592 b +e 3531219 3531080 b +e 3605907 3605768 b +e 3614611 3614472 b +e 3622547 3622408 b +e 3629331 3629192 b +e 3637139 3637000 b +e 3651667 3651528 b +e 3664595 3664456 b +e 3670035 3668240 b +e 3669952 3668240 a +e 3670035 3669952 a +e 3686163 3686024 b +e 3687763 3687624 b +e 3688979 3688840 b +e 3690131 3689992 b +e 3702035 3701896 b +e 3708499 3708360 b +e 3720083 3719944 b +e 3745235 3745096 b +e 3801363 3801224 b +e 3803027 3802888 b +e 3824403 3824264 b +e 3826067 3825928 b +e 3839059 3838920 b +e 3848211 3848072 b +e 3858707 3858568 b +e 3860371 3860232 b +e 3861651 3861512 b +e 3863699 3863560 b +e 3880531 3880392 b +e 3882195 3882056 b +e 3883859 3883720 b +e 3895763 3895624 b +e 3897427 3897288 b +e 3898707 3898568 b +e 3900755 3900616 b +e 3920467 3920328 b +e 3922131 3921992 b +e 3923795 3923656 b +e 3925395 3925256 b +e 3939411 3939272 b +e 3947603 3947464 b +e 3949139 3949000 b +e 3950675 3950536 b +e 3964051 3963912 b +e 3965779 3965640 b +e 3981203 3981064 b +e 4032275 4030160 b +e 4032192 4030160 a +e 4032275 4032192 a +e 4049939 4047824 b +e 4049856 4047824 a +e 4049939 4049856 a +e 4056275 4054032 b +e 4056192 4054032 a +e 4056275 4056192 a +e 4083987 4083848 b +e 4085203 4085064 b +e 4096851 4096712 b +e 4139347 4137168 b +e 4139264 4137168 a +e 4139347 4139264 a +e 4154451 4154312 b +e 4155731 4155592 b +e 4157331 4157192 b +e 4158931 4158792 b +e 4168147 4168008 b +e 4169811 4169672 b +e 4171475 4171336 b +e 4215699 4213520 b +e 4215616 4213520 a +e 4215699 4215616 a +e 4229331 4227280 b +e 4229248 4227280 a +e 4229331 4229248 a +e 4234963 4232912 b +e 4234880 4232912 a +e 4234963 4234880 a +e 4260179 4260040 b +e 4281171 4281032 b +e 4282835 4282696 b +e 4296403 4296264 b +e 4304339 4304200 b +e 4306067 4305928 b +e 4313619 4313480 b +e 4333331 4331408 b +e 4333248 4331408 a +e 4333331 4333248 a +e 4339411 4337168 b +e 4339328 4337168 a +e 4339411 4339328 a +e 4346323 4344336 b +e 4346240 4344336 a +e 4346323 4346240 a +e 4353875 4350288 b +e 4356744 4350288 b +e 4353792 4350288 a +e 4356883 4356744 b +e 4353875 4353792 a +e 4356800 4353792 a +e 4356883 4356800 a +e 4362899 4360720 b +e 4362816 4360720 a +e 4362899 4362816 a +e 4368080 4367696 ba +e 4372363 4367696 b +e 4372995 4367696 a +e 4368139 4368080 b +e 4368195 4368080 a +e 4376339 4374416 b +e 4376256 4374416 a +e 4376339 4376256 a +e 4386707 4384784 b +e 4386624 4384784 a +e 4386707 4386624 a +e 4392019 4390224 b +e 4391936 4390224 a +e 4392019 4391936 a +e 4398163 4395408 b +e 4399752 4395408 b +e 4398080 4395408 a +e 4399891 4399752 b +e 4398163 4398080 a +e 4399808 4398080 a +e 4399891 4399808 a +e 4403792 4403408 ba +e 4405651 4403408 b +e 4406611 4403408 b +e 4406803 4403408 b +e 4406475 4403408 b +e 4406667 4403408 b +e 4408843 4403408 b +e 4407696 4403408 ba +e 4405568 4403408 a +e 4409091 4403408 a +e 4403915 4403792 b +e 4404235 4403792 b +e 4404035 4403792 a +e 4404291 4403792 a +e 4408139 4407696 b +e 4408195 4407696 a +e 4405651 4405568 a +e 4406611 4405568 a +e 4406803 4405568 a +e 4406531 4405568 a +e 4406723 4405568 a +e 4412371 4410192 b +e 4412288 4410192 a +e 4412371 4412288 a +e 4419731 4416464 b +e 4421779 4416464 b +e 4420936 4416464 b +e 4422600 4416464 b +e 4419648 4416464 a +e 4421075 4420936 b +e 4422739 4422600 b +e 4419731 4419648 a +e 4421779 4419648 a +e 4420992 4419648 a +e 4422656 4419648 a +e 4421075 4420992 a +e 4422739 4422656 a +e 4428947 4426448 b +e 4428864 4426448 a +e 4428947 4428864 a +e 4440083 4438160 b +e 4440000 4438160 a +e 4440083 4440000 a +e 4446355 4443600 b +e 4447944 4443600 b +e 4446272 4443600 a +e 4448083 4447944 b +e 4446355 4446272 a +e 4448000 4446272 a +e 4448083 4448000 a +e 4453459 4451600 b +e 4453376 4451600 a +e 4453459 4453376 a +e 4459155 4456976 b +e 4459072 4456976 a +e 4459155 4459072 a +e 4466515 4463248 b +e 4468563 4463248 b +e 4467720 4463248 b +e 4469384 4463248 b +e 4466432 4463248 a +e 4467859 4467720 b +e 4469523 4469384 b +e 4466515 4466432 a +e 4468563 4466432 a +e 4467776 4466432 a +e 4469440 4466432 a +e 4467859 4467776 a +e 4469523 4469440 a +e 4475731 4473232 b +e 4475648 4473232 a +e 4475731 4475648 a +e 4484883 4480272 b +e 4489288 4480272 b +e 4484800 4480272 a +e 4489427 4489288 b +e 4484883 4484800 a +e 4489344 4484800 a +e 4489427 4489344 a +e 4494032 4493648 ba +e 4497555 4493648 b +e 4498131 4493648 b +e 4497995 4493648 b +e 4504715 4493648 b +e 4497472 4493648 a +e 4505539 4493648 a +e 4494155 4494032 b +e 4494851 4494032 a +e 4497555 4497472 a +e 4498131 4497472 a +e 4498051 4497472 a +e 4509267 4507216 b +e 4509184 4507216 a +e 4509267 4509184 a +e 4516563 4513296 b +e 4518536 4513296 b +e 4516480 4513296 a +e 4518675 4518536 b +e 4516563 4516480 a +e 4518592 4516480 a +e 4518675 4518592 a +e 4526803 4522384 b +e 4529683 4522384 b +e 4531347 4522384 b +e 4528840 4522384 b +e 4530504 4522384 b +e 4526720 4522384 a +e 4528979 4528840 b +e 4530643 4530504 b +e 4526803 4526720 a +e 4529683 4526720 a +e 4531347 4526720 a +e 4528896 4526720 a +e 4530560 4526720 a +e 4528979 4528896 a +e 4530643 4530560 a +e 4537875 4536016 b +e 4537792 4536016 a +e 4537875 4537792 a +e 4543699 4541392 b +e 4543616 4541392 a +e 4543699 4543616 a +e 4551571 4548304 b +e 4553619 4548304 b +e 4552776 4548304 b +e 4554440 4548304 b +e 4551488 4548304 a +e 4552915 4552776 b +e 4554579 4554440 b +e 4551571 4551488 a +e 4553619 4551488 a +e 4552832 4551488 a +e 4554496 4551488 a +e 4552915 4552832 a +e 4554579 4554496 a +e 4560787 4558288 b +e 4560704 4558288 a +e 4560787 4560704 a +e 4569235 4565328 b +e 4571347 4565328 b +e 4573075 4565328 b +e 4574739 4565328 b +e 4570504 4565328 b +e 4572232 4565328 b +e 4573896 4565328 b +e 4569152 4565328 a +e 4570643 4570504 b +e 4572371 4572232 b +e 4574035 4573896 b +e 4569235 4569152 a +e 4571347 4569152 a +e 4573075 4569152 a +e 4574739 4569152 a +e 4570560 4569152 a +e 4572288 4569152 a +e 4573952 4569152 a +e 4570643 4570560 a +e 4572371 4572288 a +e 4574035 4573952 a +e 4583251 4578640 b +e 4587784 4578640 b +e 4583168 4578640 a +e 4587923 4587784 b +e 4583251 4583168 a +e 4587840 4583168 a +e 4587923 4587840 a +e 4594963 4592208 b +e 4594880 4592208 a +e 4594963 4594880 a +e 4603475 4601616 b +e 4603392 4601616 a +e 4603475 4603392 a +e 4613267 4611216 b +e 4613184 4611216 a +e 4613267 4613184 a +e 4619219 4617296 b +e 4619136 4617296 a +e 4619219 4619136 a +e 4625555 4622736 b +e 4625472 4622736 a +e 4625555 4625472 a +e 4634963 4632784 b +e 4634880 4632784 a +e 4634963 4634880 a +e 4641107 4639120 b +e 4641024 4639120 a +e 4641107 4641024 a +e 4646675 4644560 b +e 4646592 4644560 a +e 4646675 4646592 a +e 4657427 4651152 b +e 4659475 4651152 b +e 4660627 4651152 b +e 4661779 4651152 b +e 4663443 4651152 b +e 4658632 4651152 b +e 4659848 4651152 b +e 4661000 4651152 b +e 4662600 4651152 b +e 4663816 4651152 b +e 4657344 4651152 a +e 4658771 4658632 b +e 4659987 4659848 b +e 4661139 4661000 b +e 4662739 4662600 b +e 4663955 4663816 b +e 4657427 4657344 a +e 4659475 4657344 a +e 4660627 4657344 a +e 4661779 4657344 a +e 4663443 4657344 a +e 4658688 4657344 a +e 4659904 4657344 a +e 4661056 4657344 a +e 4662656 4657344 a +e 4663872 4657344 a +e 4658771 4658688 a +e 4659987 4659904 a +e 4661139 4661056 a +e 4662739 4662656 a +e 4663955 4663872 a +e 4674131 4667856 b +e 4676179 4667856 b +e 4677331 4667856 b +e 4678611 4667856 b +e 4680275 4667856 b +e 4675336 4667856 b +e 4676552 4667856 b +e 4677768 4667856 b +e 4679432 4667856 b +e 4680648 4667856 b +e 4674048 4667856 a +e 4675475 4675336 b +e 4676691 4676552 b +e 4677907 4677768 b +e 4679571 4679432 b +e 4680787 4680648 b +e 4674131 4674048 a +e 4676179 4674048 a +e 4677331 4674048 a +e 4678611 4674048 a +e 4680275 4674048 a +e 4675392 4674048 a +e 4676608 4674048 a +e 4677824 4674048 a +e 4679488 4674048 a +e 4680704 4674048 a +e 4675475 4675392 a +e 4676691 4676608 a +e 4677907 4677824 a +e 4679571 4679488 a +e 4680787 4680704 a +e 4686867 4684752 b +e 4686784 4684752 a +e 4686867 4686784 a +e 4699091 4698952 b +e 4700371 4700232 b +e 4701651 4701512 b +e 4709843 4709704 b +e 4717651 4717512 b +e 4725075 4724936 b +e 4730579 4728528 b +e 4730496 4728528 a +e 4730579 4730496 a +e 4736979 4734928 b +e 4736896 4734928 a +e 4736979 4736896 a +e 3283 3200 a +e 8275 8192 a +e 9107 9024 a +e 14547 14464 a +e 22355 22272 a +e 27731 27648 a +e 31059 30976 a +e 32467 32384 a +e 37715 37632 a +e 41427 41344 a +e 42195 42112 a +e 50195 50112 a +e 54483 50112 a +e 55763 50112 a +e 53696 50112 a +e 54976 50112 a +e 53779 53696 a +e 55059 54976 a +e 60755 60672 a +e 66963 66880 a +e 74259 74176 a +e 83347 83264 a +e 93523 93440 a +e 99795 99712 a +e 104595 104512 a +e 112083 112000 a +e 114560 112000 a +e 114643 114560 a +e 120403 120320 a +e 126547 126464 a +e 132243 132160 a +e 136467 136384 a +e 141267 141184 a +e 149139 149056 a +e 157267 157184 a +e 163475 163392 a +e 170771 170688 a +e 182675 182592 a +e 188691 188608 a +e 190227 190144 a +e 195667 195584 a +e 200339 200256 a +e 205971 205888 a +e 213139 213056 a +e 219219 219136 a +e 226067 225984 a +e 254099 254016 a +e 261971 261888 a +e 271187 271104 a +e 280659 280576 a +e 286483 286400 a +e 291411 291328 a +e 297683 297600 a +e 302611 302528 a +e 307027 306944 a +e 312979 312896 a +e 315136 312896 a +e 315219 315136 a +e 320659 320576 a +e 325139 325056 a +e 329043 328960 a +e 334995 334912 a +e 337472 334912 a +e 337555 337472 a +e 343635 343552 a +e 344832 343552 a +e 344915 344832 a +e 350355 350272 a +e 356115 356032 a +e 360403 360320 a +e 366227 366144 a +e 368147 366144 a +e 367424 366144 a +e 369088 366144 a +e 367507 367424 a +e 369171 369088 a +e 374931 374848 a +e 381203 381120 a +e 386963 386880 a +e 392339 392256 a +e 397395 397312 a +e 401875 401792 a +e 408595 408512 a +e 409792 408512 a +e 409875 409792 a +e 415251 415168 a +e 416512 415168 a +e 416595 416512 a +e 421267 421184 a +e 426195 426112 a +e 431251 431168 a +e 436755 436672 a +e 443987 443904 a +e 445248 443904 a +e 445331 445248 a +e 452691 452608 a +e 454675 452608 a +e 456339 452608 a +e 458003 452608 a +e 459667 452608 a +e 453888 452608 a +e 455552 452608 a +e 457216 452608 a +e 458880 452608 a +e 460544 452608 a +e 453971 453888 a +e 455635 455552 a +e 457299 457216 a +e 458963 458880 a +e 460627 460544 a +e 466579 466496 a +e 471955 471872 a +e 477907 477824 a +e 486611 486528 a +e 490131 486528 a +e 489344 486528 a +e 489427 489344 a +e 495379 495296 a +e 500563 500480 a +e 508115 508032 a +e 510848 508032 a +e 510931 510848 a +e 516499 516416 a +e 521683 521600 a +e 527251 527168 a +e 534419 534336 a +e 542739 542656 a +e 551699 551616 a +e 560915 560832 a +e 566291 566208 a +e 572051 571968 a +e 579155 579072 a +e 591571 591488 a +e 592403 592320 a +e 596627 596544 a +e 599699 599616 a +e 600403 600320 a +e 604627 604544 a +e 608659 608576 a +e 613651 613568 a +e 619923 619840 a +e 621632 619840 a +e 621715 621632 a +e 626963 626880 a +e 633811 633728 a +e 641747 641664 a +e 647827 647744 a +e 653779 653696 a +e 659923 659840 a +e 666963 666880 a +e 673491 673408 a +e 679315 679232 a +e 684883 684800 a +e 690899 690816 a +e 692563 690816 a +e 691776 690816 a +e 693376 690816 a +e 691859 691776 a +e 693459 693376 a +e 698835 698752 a +e 706515 706432 a +e 714067 713984 a +e 720403 720320 a +e 726995 726912 a +e 735827 735744 a +e 742739 742656 a +e 749395 749312 a +e 751360 749312 a +e 751443 751360 a +e 758227 758144 a +e 760704 758144 a +e 760787 760704 a +e 766419 766336 a +e 772435 772352 a +e 780819 780736 a +e 789587 789504 a +e 792320 789504 a +e 792403 792320 a +e 799443 799360 a +e 801920 799360 a +e 802003 801920 a +e 808147 808064 a +e 813715 813632 a +e 822291 822208 a +e 827155 822208 a +e 826496 822208 a +e 827904 822208 a +e 826563 826496 a +e 827971 827904 a +e 833811 833728 a +e 848915 848832 a +e 854867 854784 a +e 862611 862528 a +e 865024 862528 a +e 865107 865024 a +e 870931 870848 a +e 877139 877056 a +e 883091 883008 a +e 892179 892096 a +e 895827 892096 a +e 897491 892096 a +e 895040 892096 a +e 896704 892096 a +e 898368 892096 a +e 895123 895040 a +e 896787 896704 a +e 898451 898368 a +e 905043 904960 a +e 913875 913792 a +e 916224 913792 a +e 916307 916224 a +e 922003 921920 a +e 927443 927360 a +e 933075 932992 a +e 939155 939072 a +e 946131 946048 a +e 953427 953344 a +e 965203 965120 a +e 967635 965120 a +e 969299 965120 a +e 966848 965120 a +e 968512 965120 a +e 970176 965120 a +e 966931 966848 a +e 968595 968512 a +e 970259 970176 a +e 976019 975936 a +e 981203 981120 a +e 986259 986176 a +e 992083 992000 a +e 994112 992000 a +e 994195 994112 a +e 999827 999744 a +e 1006227 1006144 a +e 1007936 1006144 a +e 1008019 1007936 a +e 1014611 1014528 a +e 1016704 1014528 a +e 1016787 1016704 a +e 1022739 1022656 a +e 1024000 1022656 a +e 1024083 1024000 a +e 1030355 1030272 a +e 1032064 1030272 a +e 1032147 1032064 a +e 1042771 1042688 a +e 1044096 1042688 a +e 1044179 1044096 a +e 1054867 1054784 a +e 1064211 1064128 a +e 1066771 1064128 a +e 1065984 1064128 a +e 1066067 1065984 a +e 1075219 1075136 a +e 1077184 1075136 a +e 1077267 1077184 a +e 1089299 1089216 a +e 1124435 1124352 a +e 1126867 1124352 a +e 1128403 1124352 a +e 1130003 1124352 a +e 1126080 1124352 a +e 1127680 1124352 a +e 1129216 1124352 a +e 1126163 1126080 a +e 1127763 1127680 a +e 1129299 1129216 a +e 1136019 1135936 a +e 1142419 1142336 a +e 1147731 1147648 a +e 1152979 1152896 a +e 1158803 1158720 a +e 1164819 1164736 a +e 1166080 1164736 a +e 1166163 1166080 a +e 1177235 1177152 a +e 1179155 1177152 a +e 1178432 1177152 a +e 1178515 1178432 a +e 1185235 1185152 a +e 1186880 1185152 a +e 1186963 1186880 a +e 1193875 1193792 a +e 1195923 1193792 a +e 1197587 1193792 a +e 1195136 1193792 a +e 1196800 1193792 a +e 1198464 1193792 a +e 1195219 1195136 a +e 1196883 1196800 a +e 1198547 1198464 a +e 1204371 1204288 a +e 1209811 1209728 a +e 1215379 1215296 a +e 1226771 1226688 a +e 1232403 1232320 a +e 1237779 1237696 a +e 1250387 1250304 a +e 1255571 1255488 a +e 1260563 1260480 a +e 1265427 1265344 a +e 1293587 1293504 a +e 1307411 1307328 a +e 1312723 1312640 a +e 1328979 1328896 a +e 1338259 1338176 a +e 1344595 1344512 a +e 1350163 1350080 a +e 1364307 1364224 a +e 1369363 1369280 a +e 1381139 1381056 a +e 1386451 1386368 a +e 1404243 1404160 a +e 1451731 1451648 a +e 1457107 1457024 a +e 1462483 1462400 a +e 1472595 1472512 a +e 1477843 1477760 a +e 1503251 1503168 a +e 1511123 1511040 a +e 1514304 1511040 a +e 1514387 1514304 a +e 1520851 1520768 a +e 1522176 1520768 a +e 1522259 1522176 a +e 1529491 1529408 a +e 1532243 1529408 a +e 1531456 1529408 a +e 1531539 1531456 a +e 1543571 1543488 a +e 1551763 1551680 a +e 1555091 1551680 a +e 1554304 1551680 a +e 1554387 1554304 a +e 1564819 1564736 a +e 1571923 1571840 a +e 1577363 1577280 a +e 1584787 1584704 a +e 1587347 1584704 a +e 1586560 1584704 a +e 1588288 1584704 a +e 1586643 1586560 a +e 1588371 1588288 a +e 1594451 1594368 a +e 1601107 1601024 a +e 1608275 1608192 a +e 1610771 1608192 a +e 1609984 1608192 a +e 1611648 1608192 a +e 1610067 1609984 a +e 1611731 1611648 a +e 1618707 1618624 a +e 1630227 1630144 a +e 1639251 1639168 a +e 1647571 1647488 a +e 1658323 1658240 a +e 1668243 1668160 a +e 1671571 1668160 a +e 1670784 1668160 a +e 1670867 1670784 a +e 1677843 1677760 a +e 1679552 1677760 a +e 1679635 1679552 a +e 1689555 1689472 a +e 1691987 1689472 a +e 1691200 1689472 a +e 1691283 1691200 a +e 1705235 1705152 a +e 1707283 1705152 a +e 1706496 1705152 a +e 1706579 1706496 a +e 1714387 1714304 a +e 1716435 1714304 a +e 1715648 1714304 a +e 1717312 1714304 a +e 1715731 1715648 a +e 1717395 1717312 a +e 1722579 1722496 a +e 1727955 1727872 a +e 1736595 1736512 a +e 1747667 1747584 a +e 1753491 1753408 a +e 1763027 1762944 a +e 1768787 1762944 a +e 1768064 1762944 a +e 1768147 1768064 a +e 1780115 1780032 a +e 1781888 1780032 a +e 1781971 1781888 a +e 1788307 1788224 a +e 1789632 1788224 a +e 1789715 1789632 a +e 1800083 1800000 a +e 1801344 1800000 a +e 1801427 1801344 a +e 1811923 1811840 a +e 1820499 1820416 a +e 1832019 1831936 a +e 1837523 1837440 a +e 1844051 1843968 a +e 1851411 1851328 a +e 1856723 1856640 a +e 1862099 1862016 a +e 1867347 1867264 a +e 1877779 1877696 a +e 1885651 1885568 a +e 1891795 1891712 a +e 1902931 1902848 a +e 1917651 1917568 a +e 1923603 1923520 a +e 1949075 1948992 a +e 1975891 1975808 a +e 1982099 1975808 a +e 1981312 1975808 a +e 1982528 1975808 a +e 1981395 1981312 a +e 1982611 1982528 a +e 1990803 1990720 a +e 1993747 1990720 a +e 1992960 1990720 a +e 1994560 1990720 a +e 1993043 1992960 a +e 1994643 1994560 a +e 2000275 2000192 a +e 2005587 2005504 a +e 2012499 2012416 a +e 2015315 2012416 a +e 2014528 2012416 a +e 2016128 2012416 a +e 2014611 2014528 a +e 2016211 2016128 a +e 2031955 2031872 a +e 2038099 2038016 a +e 2043859 2043776 a +e 2049491 2049408 a +e 2055187 2055104 a +e 2075731 2075648 a +e 2080067 2080000 a +e 2081731 2081664 a +e 2083715 2083648 a +e 2083777 2083648 a +e 2083843 2083777 a +e 2108051 2107968 a +e 2113363 2113280 a +e 2145043 2144960 a +e 2149971 2149888 a +e 2159507 2159424 a +e 2160384 2159424 a +e 2160467 2160384 a +e 2166099 2166016 a +e 2167424 2166016 a +e 2167507 2167424 a +e 2177683 2177600 a +e 2191699 2191616 a +e 2192915 2192832 a +e 2198547 2198464 a +e 2204115 2204032 a +e 2210387 2210304 a +e 2215571 2215488 a +e 2219155 2219072 a +e 2220115 2220032 a +e 2225811 2225728 a +e 2230163 2230080 a +e 2237587 2237504 a +e 2243795 2243712 a +e 2250515 2250432 a +e 2256659 2256576 a +e 2271315 2271232 a +e 2283347 2283264 a +e 2290451 2290368 a +e 2297235 2297152 a +e 2302803 2302720 a +e 2308563 2308480 a +e 2314963 2314880 a +e 2328147 2328064 a +e 2339091 2339008 a +e 2344723 2344640 a +e 2350483 2350400 a +e 2361491 2361408 a +e 2367251 2367168 a +e 2380883 2380800 a +e 2409043 2408960 a +e 2421587 2421504 a +e 2427219 2427136 a +e 2448019 2447936 a +e 2453907 2453824 a +e 2460755 2460672 a +e 2466451 2466368 a +e 2472915 2472832 a +e 2478611 2478528 a +e 2487363 2487296 a +e 2489027 2488960 a +e 2490627 2490560 a +e 2490689 2490560 a +e 2490755 2490689 a +e 2494611 2494528 a +e 2499987 2499904 a +e 2514579 2514496 a +e 2525971 2525888 a +e 2538067 2537984 a +e 2544019 2543936 a +e 2551123 2551040 a +e 2558099 2558016 a +e 2564115 2564032 a +e 2584915 2584832 a +e 2595347 2595264 a +e 2607443 2607360 a +e 2609664 2607360 a +e 2609747 2609664 a +e 2615763 2615680 a +e 2623187 2623104 a +e 2628883 2628800 a +e 2634515 2634432 a +e 2640147 2640064 a +e 2645779 2645696 a +e 2651603 2651520 a +e 2662147 2662080 a +e 2663747 2663680 a +e 2665347 2665280 a +e 2665409 2665280 a +e 2665475 2665409 a +e 2699987 2699904 a +e 2722771 2722688 a +e 2737107 2737024 a +e 2750611 2750528 a +e 2760531 2760448 a +e 2776851 2776768 a +e 2787731 2787648 a +e 2798803 2798720 a +e 2804563 2804480 a +e 2834563 2834496 a +e 2836099 2836032 a +e 2837635 2837568 a +e 2837697 2837568 a +e 2837763 2837697 a +e 2839939 2839872 a +e 2841475 2841408 a +e 2843075 2843008 a +e 2843137 2843008 a +e 2843203 2843137 a +e 2845379 2845312 a +e 2847235 2847168 a +e 2849283 2849216 a +e 2849345 2849216 a +e 2849411 2849345 a +e 2853395 2853312 a +e 2873299 2873216 a +e 2883603 2883520 a +e 2899347 2899264 a +e 2905107 2904960 a +e 2905027 2904960 a +e 2911827 2911744 a +e 2932691 2932608 a +e 2938515 2938432 a +e 2960851 2960768 a +e 2966483 2966400 a +e 2972243 2972160 a +e 2976323 2976256 a +e 2979395 2979328 a +e 2985923 2985856 a +e 2985985 2985856 a +e 2986051 2985985 a +e 2992851 2992768 a +e 3004947 3004864 a +e 3011283 3011200 a +e 3029843 3029760 a +e 3035539 3035456 a +e 3041299 3041216 a +e 3047763 3047680 a +e 3053971 3053888 a +e 3057923 3057856 a +e 3059587 3059520 a +e 3061187 3061120 a +e 3061249 3061120 a +e 3061315 3061249 a +e 3063619 3063552 a +e 3070147 3070080 a +e 3087619 3087552 a +e 3087681 3087552 a +e 3087747 3087681 a +e 3096851 3096768 a +e 3102483 3102400 a +e 3113107 3113024 a +e 3118995 3118912 a +e 3124819 3124736 a +e 3130643 3130560 a +e 3142419 3142336 a +e 3155091 3155008 a +e 3166675 3166592 a +e 3176787 3176704 a +e 3182227 3182144 a +e 3187859 3187776 a +e 3199059 3198976 a +e 3204627 3204544 a +e 3220371 3220288 a +e 3233683 3233600 a +e 3239507 3239424 a +e 3246035 3245952 a +e 3257107 3257024 a +e 3281939 3281856 a +e 3307155 3307072 a +e 3357779 3357696 a +e 3365075 3364992 a +e 3372499 3372416 a +e 3378067 3377984 a +e 3383763 3383680 a +e 3389843 3389760 a +e 3391424 3389760 a +e 3391507 3391424 a +e 3395139 3395072 a +e 3397187 3397120 a +e 3400003 3399936 a +e 3400065 3399936 a +e 3400131 3400065 a +e 3404243 3404160 a +e 3411347 3411264 a +e 3412608 3411264 a +e 3412691 3412608 a +e 3418131 3418048 a +e 3425171 3425088 a +e 3427840 3425088 a +e 3427923 3427840 a +e 3434131 3434048 a +e 3440659 3440576 a +e 3452179 3452096 a +e 3453952 3452096 a +e 3454035 3453952 a +e 3461011 3460928 a +e 3463232 3460928 a +e 3463315 3463232 a +e 3469011 3468928 a +e 3484563 3484480 a +e 3485587 3485504 a +e 3495827 3495744 a +e 3502931 3502848 a +e 3508691 3508608 a +e 3513747 3513664 a +e 3520339 3520256 a +e 3522771 3520256 a +e 3521984 3520256 a +e 3523648 3520256 a +e 3522067 3521984 a +e 3523731 3523648 a +e 3529875 3529792 a +e 3531136 3529792 a +e 3531219 3531136 a +e 3537171 3537088 a +e 3544147 3544064 a +e 3550803 3550720 a +e 3558355 3558272 a +e 3564115 3564032 a +e 3569939 3569856 a +e 3576211 3576128 a +e 3582035 3581952 a +e 3593043 3592960 a +e 3598547 3598464 a +e 3604435 3604352 a +e 3605824 3604352 a +e 3605907 3605824 a +e 3612755 3612672 a +e 3614528 3612672 a +e 3614611 3614528 a +e 3621139 3621056 a +e 3622464 3621056 a +e 3622547 3622464 a +e 3628371 3628288 a +e 3629248 3628288 a +e 3629331 3629248 a +e 3635347 3635264 a +e 3637056 3635264 a +e 3637139 3637056 a +e 3643027 3642944 a +e 3649875 3649792 a +e 3651584 3649792 a +e 3651667 3651584 a +e 3656851 3656768 a +e 3662803 3662720 a +e 3664512 3662720 a +e 3664595 3664512 a +e 3673859 3673792 a +e 3674624 3673792 a +e 3674691 3674624 a +e 3675651 3675584 a +e 3676800 3675584 a +e 3676867 3676800 a +e 3678211 3678144 a +e 3678273 3678144 a +e 3678339 3678273 a +e 3684883 3684800 a +e 3686867 3684800 a +e 3688467 3684800 a +e 3689619 3684800 a +e 3686080 3684800 a +e 3687680 3684800 a +e 3688896 3684800 a +e 3690048 3684800 a +e 3686163 3686080 a +e 3687763 3687680 a +e 3688979 3688896 a +e 3690131 3690048 a +e 3695763 3695680 a +e 3701139 3701056 a +e 3701952 3701056 a +e 3702035 3701952 a +e 3707219 3707136 a +e 3708416 3707136 a +e 3708499 3708416 a +e 3713555 3713472 a +e 3718803 3718720 a +e 3720000 3718720 a +e 3720083 3720000 a +e 3725267 3725184 a +e 3730451 3730368 a +e 3735955 3735872 a +e 3743571 3743488 a +e 3745152 3743488 a +e 3745235 3745152 a +e 3750867 3750784 a +e 3766803 3766720 a +e 3782099 3782016 a +e 3790355 3790272 a +e 3799635 3799552 a +e 3802067 3799552 a +e 3803731 3799552 a +e 3801280 3799552 a +e 3802944 3799552 a +e 3801363 3801280 a +e 3803027 3802944 a +e 3812883 3812800 a +e 3822675 3822592 a +e 3825107 3822592 a +e 3826771 3822592 a +e 3824320 3822592 a +e 3825984 3822592 a +e 3824403 3824320 a +e 3826067 3825984 a +e 3837715 3837632 a +e 3838976 3837632 a +e 3839059 3838976 a +e 3845779 3845696 a +e 3848128 3845696 a +e 3848211 3848128 a +e 3856915 3856832 a +e 3859411 3856832 a +e 3861075 3856832 a +e 3862355 3856832 a +e 3858624 3856832 a +e 3860288 3856832 a +e 3861568 3856832 a +e 3863616 3856832 a +e 3858707 3858624 a +e 3860371 3860288 a +e 3861651 3861568 a +e 3863699 3863616 a +e 3869715 3869632 a +e 3878803 3878720 a +e 3881235 3878720 a +e 3882899 3878720 a +e 3880448 3878720 a +e 3882112 3878720 a +e 3883776 3878720 a +e 3880531 3880448 a +e 3882195 3882112 a +e 3883859 3883776 a +e 3893203 3893120 a +e 3896467 3893120 a +e 3898131 3893120 a +e 3899411 3893120 a +e 3895680 3893120 a +e 3897344 3893120 a +e 3898624 3893120 a +e 3900672 3893120 a +e 3895763 3895680 a +e 3897427 3897344 a +e 3898707 3898624 a +e 3900755 3900672 a +e 3907731 3907648 a +e 3918739 3918656 a +e 3921171 3918656 a +e 3922835 3918656 a +e 3924499 3918656 a +e 3920384 3918656 a +e 3922048 3918656 a +e 3923712 3918656 a +e 3925312 3918656 a +e 3920467 3920384 a +e 3922131 3922048 a +e 3923795 3923712 a +e 3925395 3925312 a +e 3931603 3931520 a +e 3938003 3937920 a +e 3939328 3937920 a +e 3939411 3939328 a +e 3946323 3946240 a +e 3948243 3946240 a +e 3949779 3946240 a +e 3947520 3946240 a +e 3949056 3946240 a +e 3950592 3946240 a +e 3947603 3947520 a +e 3949139 3949056 a +e 3950675 3950592 a +e 3956307 3956224 a +e 3962579 3962496 a +e 3964755 3962496 a +e 3963968 3962496 a +e 3965696 3962496 a +e 3964051 3963968 a +e 3965779 3965696 a +e 3971411 3971328 a +e 3978387 3978304 a +e 3981120 3978304 a +e 3981203 3981120 a +e 3988691 3988608 a +e 4001427 4001344 a +e 4006355 4006272 a +e 4012755 4012672 a +e 4026643 4026560 a +e 4038547 4038464 a +e 4043859 4043776 a +e 4062227 4062144 a +e 4068243 4068160 a +e 4074899 4074816 a +e 4082323 4082240 a +e 4084691 4082240 a +e 4083904 4082240 a +e 4085120 4082240 a +e 4083987 4083904 a +e 4085203 4085120 a +e 4090259 4090176 a +e 4095187 4095104 a +e 4096768 4095104 a +e 4096851 4096768 a +e 4102355 4102272 a +e 4145363 4145280 a +e 4153171 4153088 a +e 4155155 4153088 a +e 4156435 4153088 a +e 4158035 4153088 a +e 4154368 4153088 a +e 4155648 4153088 a +e 4157248 4153088 a +e 4158848 4153088 a +e 4154451 4154368 a +e 4155731 4155648 a +e 4157331 4157248 a +e 4158931 4158848 a +e 4166419 4166336 a +e 4168851 4166336 a +e 4170515 4166336 a +e 4168064 4166336 a +e 4169728 4166336 a +e 4171392 4166336 a +e 4168147 4168064 a +e 4169811 4169728 a +e 4171475 4171392 a +e 4177171 4177088 a +e 4182867 4182784 a +e 4189075 4188992 a +e 4240275 4240192 a +e 4245587 4245504 a +e 4255315 4255232 a +e 4260819 4255232 a +e 4260096 4255232 a +e 4260179 4260096 a +e 4268947 4268864 a +e 4279891 4279808 a +e 4281811 4279808 a +e 4281088 4279808 a +e 4282752 4279808 a +e 4281171 4281088 a +e 4282835 4282752 a +e 4288723 4288640 a +e 4294675 4294592 a +e 4296320 4294592 a +e 4296403 4296320 a +e 4302931 4302848 a +e 4305043 4302848 a +e 4304256 4302848 a +e 4305984 4302848 a +e 4304339 4304256 a +e 4306067 4305984 a +e 4312275 4312192 a +e 4313536 4312192 a +e 4313619 4313536 a +e 4319443 4319360 a +e 4326547 4326464 a +e 4696211 4696128 a +e 4699795 4696128 a +e 4701075 4696128 a +e 4699008 4696128 a +e 4700288 4696128 a +e 4701568 4696128 a +e 4699091 4699008 a +e 4700371 4700288 a +e 4701651 4701568 a +e 4708435 4708352 a +e 4709760 4708352 a +e 4709843 4709760 a +e 4716243 4716160 a +e 4717568 4716160 a +e 4717651 4717568 a +e 4723795 4723712 a +e 4724992 4723712 a +e 4725075 4724992 a diff --git a/src/test/resources/multilinemacros/diffWithComments_expected.lg b/src/test/resources/multilinemacros/diffWithComments_expected.lg index ce94c7e49..c18cf4a5d 100644 --- a/src/test/resources/multilinemacros/diffWithComments_expected.lg +++ b/src/test/resources/multilinemacros/diffWithComments_expected.lg @@ -7,12 +7,12 @@ v 595 NON;ARTIFACT;(old: 6, diff: 8, new: 8);(old: 7, diff: 9, new: 9);; v 723 NON;ARTIFACT;(old: 7, diff: 10, new: 10);(old: 8, diff: 11, new: 11);;foo(); v 131 ADD;ARTIFACT;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);;#define multi \;kulti v 640 ADD;IF;(old: -1, diff: 9, new: 9);(old: -1, diff: 11, new: 11);A&B;#if A & B +e 131 16 a;-1,0 e 275 16 ba;0,1 e 339 16 ba;1,2 e 403 16 ba;2,3 e 467 16 ba;3,4 e 595 16 ba;4,5 e 723 16 b;5,-1 -e 723 640 a;-1,0 -e 131 16 a;-1,0 e 640 16 a;-1,6 +e 723 640 a;-1,0 diff --git a/src/test/resources/multilinemacros/inline_comments_1_expected.lg b/src/test/resources/multilinemacros/inline_comments_1_expected.lg index 241ccd6d1..912fb06b2 100644 --- a/src/test/resources/multilinemacros/inline_comments_1_expected.lg +++ b/src/test/resources/multilinemacros/inline_comments_1_expected.lg @@ -7,10 +7,10 @@ v 843 REM;ARTIFACT;(old: 10, diff: 12, new: -1);(old: 11, diff: 13, new: -1);; v 771 ADD;ARTIFACT;(old: -1, diff: 11, new: 10);(old: -1, diff: 12, new: 11);; baz(); v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);A & C & D;# if A && /* inline; comment */ C \; && D e 136 16 b;0,-1 -e 403 136 b;0,-1 -e 403 128 a;-1,0 +e 128 16 a;-1,0 e 531 16 ba;1,1 e 592 16 ba;2,2 +e 403 136 b;0,-1 e 843 592 b;0,-1 e 771 592 a;-1,0 -e 128 16 a;-1,0 +e 403 128 a;-1,0 diff --git a/src/test/resources/multilinemacros/inline_comments_2_expected.lg b/src/test/resources/multilinemacros/inline_comments_2_expected.lg index cb4af0742..e6d567028 100644 --- a/src/test/resources/multilinemacros/inline_comments_2_expected.lg +++ b/src/test/resources/multilinemacros/inline_comments_2_expected.lg @@ -7,10 +7,10 @@ v 1099 REM;ARTIFACT;(old: 14, diff: 16, new: -1);(old: 15, diff: 17, new: -1);; v 1027 ADD;ARTIFACT;(old: -1, diff: 15, new: 14);(old: -1, diff: 16, new: 15);; baz(); v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 8, new: 7);A & C & D;# if A && \;/* inline;comment */ \; C \; && D e 136 16 b;0,-1 -e 531 136 b;0,-1 -e 531 128 a;-1,0 +e 128 16 a;-1,0 e 659 16 ba;1,1 e 720 16 ba;2,2 +e 531 136 b;0,-1 e 1099 720 b;0,-1 e 1027 720 a;-1,0 -e 128 16 a;-1,0 +e 531 128 a;-1,0 diff --git a/src/test/resources/multilinemacros/inline_comments_3_expected.lg b/src/test/resources/multilinemacros/inline_comments_3_expected.lg index 7ea557356..1ba5cd78c 100644 --- a/src/test/resources/multilinemacros/inline_comments_3_expected.lg +++ b/src/test/resources/multilinemacros/inline_comments_3_expected.lg @@ -7,10 +7,10 @@ v 1355 REM;ARTIFACT;(old: 18, diff: 20, new: -1);(old: 19, diff: 21, new: -1);; v 1283 ADD;ARTIFACT;(old: -1, diff: 19, new: 18);(old: -1, diff: 20, new: 19);; baz(); v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);A & C & D;# if A && \;/* inline;comment;with multiple;lines;*/ \; C \; && D e 136 16 b;0,-1 -e 723 136 b;0,-1 -e 723 128 a;-1,0 +e 128 16 a;-1,0 e 851 16 ba;1,1 e 912 16 ba;2,2 +e 723 136 b;0,-1 e 1355 912 b;0,-1 e 1283 912 a;-1,0 -e 128 16 a;-1,0 +e 723 128 a;-1,0 diff --git a/src/test/resources/multilinemacros/inline_comments_4_expected.lg b/src/test/resources/multilinemacros/inline_comments_4_expected.lg index a25a1a85c..4e7454a98 100644 --- a/src/test/resources/multilinemacros/inline_comments_4_expected.lg +++ b/src/test/resources/multilinemacros/inline_comments_4_expected.lg @@ -7,10 +7,10 @@ v 1163 REM;ARTIFACT;(old: 15, diff: 17, new: -1);(old: 16, diff: 18, new: -1);; v 1091 ADD;ARTIFACT;(old: -1, diff: 16, new: 15);(old: -1, diff: 17, new: 16);; baz(); v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 9, new: 8);A & B & C & E & D;# if A && /* multiple inline;comments */ B && /* that */ C && /*;are distributed;*/ \; E \; && D e 136 16 b;0,-1 -e 595 136 b;0,-1 -e 595 128 a;-1,0 +e 128 16 a;-1,0 e 723 16 ba;1,1 e 784 16 ba;2,2 +e 595 136 b;0,-1 e 1163 784 b;0,-1 e 1091 784 a;-1,0 -e 128 16 a;-1,0 +e 595 128 a;-1,0 diff --git a/src/test/resources/multilinemacros/inline_comments_5_expected.lg b/src/test/resources/multilinemacros/inline_comments_5_expected.lg index 0c22c138a..c98f54da0 100644 --- a/src/test/resources/multilinemacros/inline_comments_5_expected.lg +++ b/src/test/resources/multilinemacros/inline_comments_5_expected.lg @@ -11,14 +11,14 @@ v 1107 NON;ARTIFACT;(old: 14, diff: 16, new: 14);(old: 15, diff: 17, new: 15);;/ v 1171 NON;ARTIFACT;(old: 15, diff: 17, new: 15);(old: 16, diff: 18, new: 16);;text v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);A & C & D;# if A && /* inline; comment */ C \; && D //* no continuation e 136 16 b;0,-1 -e 403 136 b;0,-1 -e 403 128 a;-1,0 +e 128 16 a;-1,0 e 531 16 ba;1,1 e 592 16 ba;2,2 -e 843 592 b;0,-1 -e 771 592 a;-1,0 e 979 16 ba;3,3 e 1043 16 ba;4,4 e 1107 16 ba;5,5 e 1171 16 ba;6,6 -e 128 16 a;-1,0 +e 403 136 b;0,-1 +e 843 592 b;0,-1 +e 771 592 a;-1,0 +e 403 128 a;-1,0 diff --git a/src/test/resources/multilinemacros/inline_comments_6_expected.lg b/src/test/resources/multilinemacros/inline_comments_6_expected.lg index 91805d3cf..4e80108fa 100644 --- a/src/test/resources/multilinemacros/inline_comments_6_expected.lg +++ b/src/test/resources/multilinemacros/inline_comments_6_expected.lg @@ -3,6 +3,6 @@ v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 6, diff: 7, new: -1);A & B & D;# i v 467 NON;ARTIFACT;(old: 5, diff: 6, new: 5);(old: 6, diff: 7, new: 6);; baz(); v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 7, new: 6);A & C & D;# if A && /* inline;// Some inner line comment; comment */ C \; && D e 136 16 b;0,-1 +e 128 16 a;-1,0 e 467 136 b;0,-1 e 467 128 a;-1,0 -e 128 16 a;-1,0 diff --git a/src/test/resources/multilinemacros/mldiff1_expected.lg b/src/test/resources/multilinemacros/mldiff1_expected.lg index 10ef7f3a1..15471215e 100644 --- a/src/test/resources/multilinemacros/mldiff1_expected.lg +++ b/src/test/resources/multilinemacros/mldiff1_expected.lg @@ -20,24 +20,24 @@ v 1280 ADD;IF;(old: -1, diff: 19, new: 18);(old: -1, diff: 24, new: 22);A & (ADD v 1728 ADD;IF;(old: -1, diff: 26, new: 24);(old: -1, diff: 30, new: 28);X & Y | defined(Z) | W;#if (X && Y) \; || defined(Z) \; || W e 147 16 ba;0,0 e 208 16 ba;1,1 -e 339 208 ba;0,0 e 467 16 ba;2,2 e 659 16 b;3,-1 -e 659 512 a;-1,0 +e 512 16 a;-1,3 e 787 16 ba;4,4 e 840 16 b;5,-1 -e 1107 840 b;0,-1 -e 1107 832 a;-1,0 +e 832 16 a;-1,5 e 1235 16 ba;6,6 e 1288 16 b;7,-1 -e 1555 1288 b;0,-1 -e 1555 1280 a;-1,0 +e 1280 16 a;-1,7 e 1683 16 ba;8,8 e 1736 16 b;9,-1 +e 1728 16 a;-1,9 +e 2067 16 ba;10,10 +e 339 208 ba;0,0 +e 1107 840 b;0,-1 +e 1555 1288 b;0,-1 e 1939 1736 b;0,-1 +e 659 512 a;-1,0 +e 1107 832 a;-1,0 +e 1555 1280 a;-1,0 e 1939 1728 a;-1,0 -e 2067 16 ba;10,10 -e 512 16 a;-1,3 -e 832 16 a;-1,5 -e 1280 16 a;-1,7 -e 1728 16 a;-1,9 diff --git a/src/test/resources/tree-diffing/.gitignore b/src/test/resources/tree-diffing/.gitignore index 0745fb4f5..844a6fbc3 100644 --- a/src/test/resources/tree-diffing/.gitignore +++ b/src/test/resources/tree-diffing/.gitignore @@ -1,2 +1,2 @@ -/tex/ +tex/ *_actual.lg diff --git a/src/test/resources/tree-diffing/06_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/06_gumtree-hybrid_expected.lg deleted file mode 100644 index ed9ff5794..000000000 --- a/src/test/resources/tree-diffing/06_gumtree-hybrid_expected.lg +++ /dev/null @@ -1,10 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 1, new: 4);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line A -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line B -v 322 ADD;ELIF;(old: -1, diff: 4, new: 3);(old: -1, diff: 4, new: 5);B;#elif B -e 144 80 ba;0,0 -e 211 144 ba;0,0 -e 275 144 b;1,-1 -e 275 322 a;-1,0 -e 322 144 a;-1,1 diff --git a/src/test/resources/tree-diffing/06_gumtree_expected.lg b/src/test/resources/tree-diffing/06_gumtree_expected.lg deleted file mode 100644 index ed9ff5794..000000000 --- a/src/test/resources/tree-diffing/06_gumtree_expected.lg +++ /dev/null @@ -1,10 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 1, new: 4);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line A -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line B -v 322 ADD;ELIF;(old: -1, diff: 4, new: 3);(old: -1, diff: 4, new: 5);B;#elif B -e 144 80 ba;0,0 -e 211 144 ba;0,0 -e 275 144 b;1,-1 -e 275 322 a;-1,0 -e 322 144 a;-1,1 diff --git a/src/test/resources/tree-diffing/07_change-distiller-theta_expected.lg b/src/test/resources/tree-diffing/07_change-distiller-theta_expected.lg deleted file mode 100644 index aa4fcbe2b..000000000 --- a/src/test/resources/tree-diffing/07_change-distiller-theta_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(CONFIG_A);#ifdef CONFIG_A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(CONFIG_B);#ifdef CONFIG_B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_classic-gumtree-theta_expected.lg b/src/test/resources/tree-diffing/07_classic-gumtree-theta_expected.lg deleted file mode 100644 index aa4fcbe2b..000000000 --- a/src/test/resources/tree-diffing/07_classic-gumtree-theta_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(CONFIG_A);#ifdef CONFIG_A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(CONFIG_B);#ifdef CONFIG_B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/07_gumtree-partition-id_expected.lg deleted file mode 100644 index aa4fcbe2b..000000000 --- a/src/test/resources/tree-diffing/07_gumtree-partition-id_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(CONFIG_A);#ifdef CONFIG_A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(CONFIG_B);#ifdef CONFIG_B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_gumtree-simple-id-theta_expected.lg b/src/test/resources/tree-diffing/07_gumtree-simple-id-theta_expected.lg deleted file mode 100644 index aa4fcbe2b..000000000 --- a/src/test/resources/tree-diffing/07_gumtree-simple-id-theta_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(CONFIG_A);#ifdef CONFIG_A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(CONFIG_B);#ifdef CONFIG_B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_theta_expected.lg b/src/test/resources/tree-diffing/07_theta_expected.lg deleted file mode 100644 index aa4fcbe2b..000000000 --- a/src/test/resources/tree-diffing/07_theta_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(CONFIG_A);#ifdef CONFIG_A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(CONFIG_B);#ifdef CONFIG_B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_change-distiller-theta_expected.lg b/src/test/resources/tree-diffing/08_change-distiller-theta_expected.lg deleted file mode 100644 index 3303e4528..000000000 --- a/src/test/resources/tree-diffing/08_change-distiller-theta_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(A);#ifdef A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(B);#ifdef B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_classic-gumtree-theta_expected.lg b/src/test/resources/tree-diffing/08_classic-gumtree-theta_expected.lg deleted file mode 100644 index 3303e4528..000000000 --- a/src/test/resources/tree-diffing/08_classic-gumtree-theta_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(A);#ifdef A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(B);#ifdef B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/08_gumtree-partition-id_expected.lg deleted file mode 100644 index 3303e4528..000000000 --- a/src/test/resources/tree-diffing/08_gumtree-partition-id_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(A);#ifdef A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(B);#ifdef B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_gumtree-simple-id-theta_expected.lg b/src/test/resources/tree-diffing/08_gumtree-simple-id-theta_expected.lg deleted file mode 100644 index 3303e4528..000000000 --- a/src/test/resources/tree-diffing/08_gumtree-simple-id-theta_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(A);#ifdef A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(B);#ifdef B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_theta_expected.lg b/src/test/resources/tree-diffing/08_theta_expected.lg deleted file mode 100644 index 3303e4528..000000000 --- a/src/test/resources/tree-diffing/08_theta_expected.lg +++ /dev/null @@ -1,12 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(A);#ifdef A -v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(B);#ifdef B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line -v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 -e 384 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_change-distiller-theta_expected.lg b/src/test/resources/tree-diffing/09_change-distiller-theta_expected.lg deleted file mode 100644 index 30efe1ca9..000000000 --- a/src/test/resources/tree-diffing/09_change-distiller-theta_expected.lg +++ /dev/null @@ -1,23 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 -v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B -v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 -v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 -v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 -v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B -e 144 80 b;0,-1 -e 144 640 a;-1,0 -e 211 144 ba;0,0 -e 275 144 ba;1,1 -e 339 144 ba;2,2 -e 392 144 b;3,-1 -e 467 392 b;0,-1 -e 467 144 a;-1,3 -e 531 392 b;1,-1 -e 531 144 a;-1,4 -e 595 392 b;2,-1 -e 595 144 a;-1,5 -e 640 80 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_change-distiller_expected.lg b/src/test/resources/tree-diffing/09_change-distiller_expected.lg deleted file mode 100644 index 30efe1ca9..000000000 --- a/src/test/resources/tree-diffing/09_change-distiller_expected.lg +++ /dev/null @@ -1,23 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 -v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B -v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 -v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 -v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 -v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B -e 144 80 b;0,-1 -e 144 640 a;-1,0 -e 211 144 ba;0,0 -e 275 144 ba;1,1 -e 339 144 ba;2,2 -e 392 144 b;3,-1 -e 467 392 b;0,-1 -e 467 144 a;-1,3 -e 531 392 b;1,-1 -e 531 144 a;-1,4 -e 595 392 b;2,-1 -e 595 144 a;-1,5 -e 640 80 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_classic-gumtree-theta_expected.lg b/src/test/resources/tree-diffing/09_classic-gumtree-theta_expected.lg deleted file mode 100644 index 30efe1ca9..000000000 --- a/src/test/resources/tree-diffing/09_classic-gumtree-theta_expected.lg +++ /dev/null @@ -1,23 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 -v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B -v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 -v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 -v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 -v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B -e 144 80 b;0,-1 -e 144 640 a;-1,0 -e 211 144 ba;0,0 -e 275 144 ba;1,1 -e 339 144 ba;2,2 -e 392 144 b;3,-1 -e 467 392 b;0,-1 -e 467 144 a;-1,3 -e 531 392 b;1,-1 -e 531 144 a;-1,4 -e 595 392 b;2,-1 -e 595 144 a;-1,5 -e 640 80 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/09_gumtree-partition-id_expected.lg deleted file mode 100644 index 30efe1ca9..000000000 --- a/src/test/resources/tree-diffing/09_gumtree-partition-id_expected.lg +++ /dev/null @@ -1,23 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 -v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B -v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 -v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 -v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 -v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B -e 144 80 b;0,-1 -e 144 640 a;-1,0 -e 211 144 ba;0,0 -e 275 144 ba;1,1 -e 339 144 ba;2,2 -e 392 144 b;3,-1 -e 467 392 b;0,-1 -e 467 144 a;-1,3 -e 531 392 b;1,-1 -e 531 144 a;-1,4 -e 595 392 b;2,-1 -e 595 144 a;-1,5 -e 640 80 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_gumtree-simple-id-theta_expected.lg b/src/test/resources/tree-diffing/09_gumtree-simple-id-theta_expected.lg deleted file mode 100644 index 30efe1ca9..000000000 --- a/src/test/resources/tree-diffing/09_gumtree-simple-id-theta_expected.lg +++ /dev/null @@ -1,23 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 -v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B -v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 -v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 -v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 -v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B -e 144 80 b;0,-1 -e 144 640 a;-1,0 -e 211 144 ba;0,0 -e 275 144 ba;1,1 -e 339 144 ba;2,2 -e 392 144 b;3,-1 -e 467 392 b;0,-1 -e 467 144 a;-1,3 -e 531 392 b;1,-1 -e 531 144 a;-1,4 -e 595 392 b;2,-1 -e 595 144 a;-1,5 -e 640 80 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/09_gumtree-simple-id_expected.lg deleted file mode 100644 index 30efe1ca9..000000000 --- a/src/test/resources/tree-diffing/09_gumtree-simple-id_expected.lg +++ /dev/null @@ -1,23 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 -v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B -v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 -v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 -v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 -v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B -e 144 80 b;0,-1 -e 144 640 a;-1,0 -e 211 144 ba;0,0 -e 275 144 ba;1,1 -e 339 144 ba;2,2 -e 392 144 b;3,-1 -e 467 392 b;0,-1 -e 467 144 a;-1,3 -e 531 392 b;1,-1 -e 531 144 a;-1,4 -e 595 392 b;2,-1 -e 595 144 a;-1,5 -e 640 80 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/09_gumtree-simple_expected.lg deleted file mode 100644 index 30efe1ca9..000000000 --- a/src/test/resources/tree-diffing/09_gumtree-simple_expected.lg +++ /dev/null @@ -1,23 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 -v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B -v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 -v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 -v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 -v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B -e 144 80 b;0,-1 -e 144 640 a;-1,0 -e 211 144 ba;0,0 -e 275 144 ba;1,1 -e 339 144 ba;2,2 -e 392 144 b;3,-1 -e 467 392 b;0,-1 -e 467 144 a;-1,3 -e 531 392 b;1,-1 -e 531 144 a;-1,4 -e 595 392 b;2,-1 -e 595 144 a;-1,5 -e 640 80 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_theta_expected.lg b/src/test/resources/tree-diffing/09_theta_expected.lg deleted file mode 100644 index 30efe1ca9..000000000 --- a/src/test/resources/tree-diffing/09_theta_expected.lg +++ /dev/null @@ -1,23 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 -v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B -v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 -v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 -v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 -v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B -e 144 80 b;0,-1 -e 144 640 a;-1,0 -e 211 144 ba;0,0 -e 275 144 ba;1,1 -e 339 144 ba;2,2 -e 392 144 b;3,-1 -e 467 392 b;0,-1 -e 467 144 a;-1,3 -e 531 392 b;1,-1 -e 531 144 a;-1,4 -e 595 392 b;2,-1 -e 595 144 a;-1,5 -e 640 80 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_xy_expected.lg b/src/test/resources/tree-diffing/09_xy_expected.lg deleted file mode 100644 index 30efe1ca9..000000000 --- a/src/test/resources/tree-diffing/09_xy_expected.lg +++ /dev/null @@ -1,23 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 -v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B -v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 -v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 -v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 -v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B -e 144 80 b;0,-1 -e 144 640 a;-1,0 -e 211 144 ba;0,0 -e 275 144 ba;1,1 -e 339 144 ba;2,2 -e 392 144 b;3,-1 -e 467 392 b;0,-1 -e 467 144 a;-1,3 -e 531 392 b;1,-1 -e 531 144 a;-1,4 -e 595 392 b;2,-1 -e 595 144 a;-1,5 -e 640 80 a;-1,0 diff --git a/src/test/resources/tree-diffing/10_change-distiller_expected.lg b/src/test/resources/tree-diffing/10_change-distiller_expected.lg deleted file mode 100644 index bb645cdad..000000000 --- a/src/test/resources/tree-diffing/10_change-distiller_expected.lg +++ /dev/null @@ -1,9 +0,0 @@ -v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 1, new: 4);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;456 -v 267 REM;ARTIFACT;(old: 3, diff: 3, new: -1);(old: 4, diff: 3, new: -1);;123 -v 323 ADD;ARTIFACT;(old: -1, diff: 4, new: 2);(old: -1, diff: 4, new: 3);;123 -e 144 80 ba;0,0 -e 211 144 ba;0,1 -e 267 144 b;1,-1 -e 323 144 a;-1,0 diff --git a/src/test/resources/tree-diffing/01_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/01_gumtree-hybrid_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/01_gumtree-hybrid_expected.lg rename to src/test/resources/tree-diffing/createMatching/01_gumtree-hybrid_expected.lg diff --git a/src/test/resources/tree-diffing/01_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/01_gumtree_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/01_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/01_gumtree_expected.lg diff --git a/src/test/resources/tree-diffing/02_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/02_gumtree-hybrid_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/02_gumtree-hybrid_expected.lg rename to src/test/resources/tree-diffing/createMatching/02_gumtree-hybrid_expected.lg diff --git a/src/test/resources/tree-diffing/02_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/02_gumtree_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/02_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/02_gumtree_expected.lg diff --git a/src/test/resources/tree-diffing/03_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/03_gumtree-hybrid_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/03_gumtree-hybrid_expected.lg rename to src/test/resources/tree-diffing/createMatching/03_gumtree-hybrid_expected.lg diff --git a/src/test/resources/tree-diffing/03_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/03_gumtree_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/03_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/03_gumtree_expected.lg diff --git a/src/test/resources/tree-diffing/04_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/04_gumtree-hybrid_expected.lg similarity index 73% rename from src/test/resources/tree-diffing/04_gumtree-hybrid_expected.lg rename to src/test/resources/tree-diffing/createMatching/04_gumtree-hybrid_expected.lg index 840767659..4824623c9 100644 --- a/src/test/resources/tree-diffing/04_gumtree-hybrid_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/04_gumtree-hybrid_expected.lg @@ -1,6 +1,6 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 1, new: 2);;Line +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 2);(old: 2, diff: 1, new: 3);;Line v 192 ADD;IF;(old: -1, diff: 2, new: 1);(old: -1, diff: 2, new: 3);defined(A);#ifdef A e 147 80 b;0,-1 -e 147 192 a;-1,0 e 192 80 a;-1,0 +e 147 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/04_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/04_gumtree_expected.lg similarity index 73% rename from src/test/resources/tree-diffing/04_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/04_gumtree_expected.lg index 840767659..4824623c9 100644 --- a/src/test/resources/tree-diffing/04_gumtree_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/04_gumtree_expected.lg @@ -1,6 +1,6 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 1, new: 2);;Line +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 2);(old: 2, diff: 1, new: 3);;Line v 192 ADD;IF;(old: -1, diff: 2, new: 1);(old: -1, diff: 2, new: 3);defined(A);#ifdef A e 147 80 b;0,-1 -e 147 192 a;-1,0 e 192 80 a;-1,0 +e 147 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/05_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/05_gumtree-hybrid_expected.lg similarity index 73% rename from src/test/resources/tree-diffing/05_gumtree-hybrid_expected.lg rename to src/test/resources/tree-diffing/createMatching/05_gumtree-hybrid_expected.lg index 1b1f5340d..a9b885eaa 100644 --- a/src/test/resources/tree-diffing/05_gumtree-hybrid_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/05_gumtree-hybrid_expected.lg @@ -1,6 +1,6 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 1, new: -1);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 2, new: 2);;Line e 136 80 b;0,-1 -e 211 136 b;0,-1 e 211 80 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/05_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/05_gumtree_expected.lg similarity index 73% rename from src/test/resources/tree-diffing/05_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/05_gumtree_expected.lg index 1b1f5340d..a9b885eaa 100644 --- a/src/test/resources/tree-diffing/05_gumtree_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/05_gumtree_expected.lg @@ -1,6 +1,6 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 1, new: -1);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 2, new: 2);;Line e 136 80 b;0,-1 -e 211 136 b;0,-1 e 211 80 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/createMatching/06_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/06_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..007fe1a88 --- /dev/null +++ b/src/test/resources/tree-diffing/createMatching/06_gumtree-hybrid_expected.lg @@ -0,0 +1,13 @@ +v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 1, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line A +v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 4);(old: 4, diff: 3, new: 5);;Line B +v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 3);defined(A);#ifdef A +v 386 ADD;ELIF;(old: -1, diff: 5, new: 3);(old: -1, diff: 5, new: 5);B;#elif B +e 136 80 b;0,-1 +e 320 80 a;-1,0 +e 211 136 b;0,-1 +e 275 136 b;1,-1 +e 211 320 a;-1,0 +e 386 320 a;-1,1 +e 275 386 a;-1,0 diff --git a/src/test/resources/tree-diffing/createMatching/06_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/06_gumtree_expected.lg new file mode 100644 index 000000000..007fe1a88 --- /dev/null +++ b/src/test/resources/tree-diffing/createMatching/06_gumtree_expected.lg @@ -0,0 +1,13 @@ +v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 1, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line A +v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 4);(old: 4, diff: 3, new: 5);;Line B +v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 3);defined(A);#ifdef A +v 386 ADD;ELIF;(old: -1, diff: 5, new: 3);(old: -1, diff: 5, new: 5);B;#elif B +e 136 80 b;0,-1 +e 320 80 a;-1,0 +e 211 136 b;0,-1 +e 275 136 b;1,-1 +e 211 320 a;-1,0 +e 386 320 a;-1,1 +e 275 386 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_change-distiller_expected.lg b/src/test/resources/tree-diffing/createMatching/07_change-distiller_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/07_change-distiller_expected.lg rename to src/test/resources/tree-diffing/createMatching/07_change-distiller_expected.lg index aa4fcbe2b..a07a12b73 100644 --- a/src/test/resources/tree-diffing/07_change-distiller_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/07_change-distiller_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/createMatching/07_gumtree-hybrid-id_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/07_gumtree-hybrid-id_expected.lg rename to src/test/resources/tree-diffing/createMatching/07_gumtree-hybrid-id_expected.lg index aa4fcbe2b..a07a12b73 100644 --- a/src/test/resources/tree-diffing/07_gumtree-hybrid-id_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/07_gumtree-hybrid-id_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/07_gumtree-hybrid_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/07_gumtree-hybrid_expected.lg rename to src/test/resources/tree-diffing/createMatching/07_gumtree-hybrid_expected.lg index aa4fcbe2b..a07a12b73 100644 --- a/src/test/resources/tree-diffing/07_gumtree-hybrid_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/07_gumtree-hybrid_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/createMatching/07_gumtree-simple-id_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/07_gumtree-simple-id_expected.lg rename to src/test/resources/tree-diffing/createMatching/07_gumtree-simple-id_expected.lg index aa4fcbe2b..a07a12b73 100644 --- a/src/test/resources/tree-diffing/07_gumtree-simple-id_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/07_gumtree-simple-id_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/createMatching/07_gumtree-simple_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/07_gumtree-simple_expected.lg rename to src/test/resources/tree-diffing/createMatching/07_gumtree-simple_expected.lg index aa4fcbe2b..a07a12b73 100644 --- a/src/test/resources/tree-diffing/07_gumtree-simple_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/07_gumtree-simple_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/07_gumtree_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/07_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/07_gumtree_expected.lg index aa4fcbe2b..a07a12b73 100644 --- a/src/test/resources/tree-diffing/07_gumtree_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/07_gumtree_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/createMatching/07_longestCommonSequence_expected.lg similarity index 58% rename from src/test/resources/tree-diffing/07_longestCommonSequence_expected.lg rename to src/test/resources/tree-diffing/createMatching/07_longestCommonSequence_expected.lg index aa4fcbe2b..2e680785a 100644 --- a/src/test/resources/tree-diffing/07_longestCommonSequence_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/07_longestCommonSequence_expected.lg @@ -1,12 +1,11 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(CONFIG_A);#ifdef CONFIG_A +v 144 NON;IF;(old: 1, diff: 1, new: 2);(old: 5, diff: 1, new: 4);defined(CONFIG_A);#ifdef CONFIG_A v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(CONFIG_B);#ifdef CONFIG_B v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 +e 144 80 b;0,-1 e 320 80 a;-1,0 -e 384 320 a;-1,0 +e 200 144 b;0,-1 +e 275 144 a;-1,0 +e 275 200 b;0,-1 +e 144 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/07_xy_expected.lg b/src/test/resources/tree-diffing/createMatching/07_xy_expected.lg similarity index 73% rename from src/test/resources/tree-diffing/07_xy_expected.lg rename to src/test/resources/tree-diffing/createMatching/07_xy_expected.lg index aa4fcbe2b..c520a3cf2 100644 --- a/src/test/resources/tree-diffing/07_xy_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/07_xy_expected.lg @@ -1,12 +1,13 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(CONFIG_A);#ifdef CONFIG_A v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(CONFIG_B);#ifdef CONFIG_B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line +v 267 REM;ARTIFACT;(old: 3, diff: 3, new: -1);(old: 4, diff: 3, new: -1);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(CONFIG_B);#ifdef CONFIG_B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +v 451 ADD;ARTIFACT;(old: -1, diff: 6, new: 3);(old: -1, diff: 6, new: 4);;Line e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 e 320 80 a;-1,0 +e 200 136 b;0,-1 +e 267 200 b;0,-1 e 384 320 a;-1,0 +e 451 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_change-distiller_expected.lg b/src/test/resources/tree-diffing/createMatching/08_change-distiller_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/08_change-distiller_expected.lg rename to src/test/resources/tree-diffing/createMatching/08_change-distiller_expected.lg index 3303e4528..c87160f14 100644 --- a/src/test/resources/tree-diffing/08_change-distiller_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/08_change-distiller_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/createMatching/08_gumtree-hybrid-id_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/08_gumtree-hybrid-id_expected.lg rename to src/test/resources/tree-diffing/createMatching/08_gumtree-hybrid-id_expected.lg index 3303e4528..c87160f14 100644 --- a/src/test/resources/tree-diffing/08_gumtree-hybrid-id_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/08_gumtree-hybrid-id_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/08_gumtree-hybrid_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/08_gumtree-hybrid_expected.lg rename to src/test/resources/tree-diffing/createMatching/08_gumtree-hybrid_expected.lg index 3303e4528..c87160f14 100644 --- a/src/test/resources/tree-diffing/08_gumtree-hybrid_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/08_gumtree-hybrid_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/createMatching/08_gumtree-simple-id_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/08_gumtree-simple-id_expected.lg rename to src/test/resources/tree-diffing/createMatching/08_gumtree-simple-id_expected.lg index 3303e4528..c87160f14 100644 --- a/src/test/resources/tree-diffing/08_gumtree-simple-id_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/08_gumtree-simple-id_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/createMatching/08_gumtree-simple_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/08_gumtree-simple_expected.lg rename to src/test/resources/tree-diffing/createMatching/08_gumtree-simple_expected.lg index 3303e4528..c87160f14 100644 --- a/src/test/resources/tree-diffing/08_gumtree-simple_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/08_gumtree-simple_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/08_gumtree_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/08_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/08_gumtree_expected.lg index 3303e4528..c87160f14 100644 --- a/src/test/resources/tree-diffing/08_gumtree_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/08_gumtree_expected.lg @@ -5,8 +5,8 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A e 136 80 b;0,-1 +e 320 80 a;-1,0 e 200 136 b;0,-1 e 275 200 b;0,-1 -e 275 384 a;-1,0 -e 320 80 a;-1,0 e 384 320 a;-1,0 +e 275 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/createMatching/08_longestCommonSequence_expected.lg similarity index 59% rename from src/test/resources/tree-diffing/08_longestCommonSequence_expected.lg rename to src/test/resources/tree-diffing/createMatching/08_longestCommonSequence_expected.lg index 3303e4528..d537c5e32 100644 --- a/src/test/resources/tree-diffing/08_longestCommonSequence_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/08_longestCommonSequence_expected.lg @@ -1,12 +1,11 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(A);#ifdef A +v 144 NON;IF;(old: 1, diff: 1, new: 2);(old: 5, diff: 1, new: 4);defined(A);#ifdef A v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(B);#ifdef B v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B -v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A -e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 +e 144 80 b;0,-1 e 320 80 a;-1,0 -e 384 320 a;-1,0 +e 200 144 b;0,-1 +e 275 144 a;-1,0 +e 275 200 b;0,-1 +e 144 320 a;-1,0 diff --git a/src/test/resources/tree-diffing/08_xy_expected.lg b/src/test/resources/tree-diffing/createMatching/08_xy_expected.lg similarity index 71% rename from src/test/resources/tree-diffing/08_xy_expected.lg rename to src/test/resources/tree-diffing/createMatching/08_xy_expected.lg index 3303e4528..dadb7225b 100644 --- a/src/test/resources/tree-diffing/08_xy_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/08_xy_expected.lg @@ -1,12 +1,13 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 5, diff: 1, new: -1);defined(A);#ifdef A v 200 REM;IF;(old: 2, diff: 2, new: -1);(old: 4, diff: 2, new: -1);defined(B);#ifdef B -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line +v 267 REM;ARTIFACT;(old: 3, diff: 3, new: -1);(old: 4, diff: 3, new: -1);;Line v 320 ADD;IF;(old: -1, diff: 4, new: 1);(old: -1, diff: 4, new: 5);defined(B);#ifdef B v 384 ADD;IF;(old: -1, diff: 5, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +v 451 ADD;ARTIFACT;(old: -1, diff: 6, new: 3);(old: -1, diff: 6, new: 4);;Line e 136 80 b;0,-1 -e 200 136 b;0,-1 -e 275 200 b;0,-1 -e 275 384 a;-1,0 e 320 80 a;-1,0 +e 200 136 b;0,-1 +e 267 200 b;0,-1 e 384 320 a;-1,0 +e 451 384 a;-1,0 diff --git a/src/test/resources/tree-diffing/createMatching/09_change-distiller_expected.lg b/src/test/resources/tree-diffing/createMatching/09_change-distiller_expected.lg new file mode 100644 index 000000000..26b79040b --- /dev/null +++ b/src/test/resources/tree-diffing/createMatching/09_change-distiller_expected.lg @@ -0,0 +1,32 @@ +v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 2);(old: 10, diff: 1, new: 9);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 2, new: -1);;Line 1 +v 267 REM;ARTIFACT;(old: 3, diff: 3, new: -1);(old: 4, diff: 3, new: -1);;Line 2 +v 331 REM;ARTIFACT;(old: 4, diff: 4, new: -1);(old: 5, diff: 4, new: -1);;Line 3 +v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B +v 459 REM;ARTIFACT;(old: 6, diff: 6, new: -1);(old: 7, diff: 6, new: -1);;Line 4 +v 523 REM;ARTIFACT;(old: 7, diff: 7, new: -1);(old: 8, diff: 7, new: -1);;Line 5 +v 587 REM;ARTIFACT;(old: 8, diff: 8, new: -1);(old: 9, diff: 8, new: -1);;Line 6 +v 643 ADD;ARTIFACT;(old: -1, diff: 9, new: 3);(old: -1, diff: 9, new: 4);;Line 1 +v 707 ADD;ARTIFACT;(old: -1, diff: 10, new: 4);(old: -1, diff: 10, new: 5);;Line 2 +v 771 ADD;ARTIFACT;(old: -1, diff: 11, new: 5);(old: -1, diff: 11, new: 6);;Line 3 +v 835 ADD;ARTIFACT;(old: -1, diff: 12, new: 6);(old: -1, diff: 12, new: 7);;Line 4 +v 899 ADD;ARTIFACT;(old: -1, diff: 13, new: 7);(old: -1, diff: 13, new: 8);;Line 5 +v 963 ADD;ARTIFACT;(old: -1, diff: 14, new: 8);(old: -1, diff: 14, new: 9);;Line 6 +v 1024 ADD;IF;(old: -1, diff: 15, new: 1);(old: -1, diff: 15, new: 10);defined(B);#ifdef B +e 144 80 b;0,-1 +e 1024 80 a;-1,0 +e 203 144 b;0,-1 +e 267 144 b;1,-1 +e 331 144 b;2,-1 +e 392 144 b;3,-1 +e 643 144 a;-1,0 +e 707 144 a;-1,1 +e 771 144 a;-1,2 +e 835 144 a;-1,3 +e 899 144 a;-1,4 +e 963 144 a;-1,5 +e 459 392 b;0,-1 +e 523 392 b;1,-1 +e 587 392 b;2,-1 +e 144 1024 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/createMatching/09_gumtree-hybrid-id_expected.lg similarity index 68% rename from src/test/resources/tree-diffing/09_gumtree-hybrid-id_expected.lg rename to src/test/resources/tree-diffing/createMatching/09_gumtree-hybrid-id_expected.lg index 30efe1ca9..dd0703090 100644 --- a/src/test/resources/tree-diffing/09_gumtree-hybrid-id_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/09_gumtree-hybrid-id_expected.lg @@ -1,23 +1,23 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 +v 144 NON;IF;(old: 1, diff: 1, new: 2);(old: 10, diff: 1, new: 9);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 3);(old: 3, diff: 2, new: 4);;Line 1 +v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 4);(old: 4, diff: 3, new: 5);;Line 2 +v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 5);(old: 5, diff: 4, new: 6);;Line 3 v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B e 144 80 b;0,-1 -e 144 640 a;-1,0 +e 640 80 a;-1,0 e 211 144 ba;0,0 e 275 144 ba;1,1 e 339 144 ba;2,2 e 392 144 b;3,-1 -e 467 392 b;0,-1 e 467 144 a;-1,3 -e 531 392 b;1,-1 e 531 144 a;-1,4 -e 595 392 b;2,-1 e 595 144 a;-1,5 -e 640 80 a;-1,0 +e 467 392 b;0,-1 +e 531 392 b;1,-1 +e 595 392 b;2,-1 +e 144 640 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/09_gumtree-hybrid_expected.lg similarity index 68% rename from src/test/resources/tree-diffing/09_gumtree-hybrid_expected.lg rename to src/test/resources/tree-diffing/createMatching/09_gumtree-hybrid_expected.lg index 30efe1ca9..dd0703090 100644 --- a/src/test/resources/tree-diffing/09_gumtree-hybrid_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/09_gumtree-hybrid_expected.lg @@ -1,23 +1,23 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 +v 144 NON;IF;(old: 1, diff: 1, new: 2);(old: 10, diff: 1, new: 9);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 3);(old: 3, diff: 2, new: 4);;Line 1 +v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 4);(old: 4, diff: 3, new: 5);;Line 2 +v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 5);(old: 5, diff: 4, new: 6);;Line 3 v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B e 144 80 b;0,-1 -e 144 640 a;-1,0 +e 640 80 a;-1,0 e 211 144 ba;0,0 e 275 144 ba;1,1 e 339 144 ba;2,2 e 392 144 b;3,-1 -e 467 392 b;0,-1 e 467 144 a;-1,3 -e 531 392 b;1,-1 e 531 144 a;-1,4 -e 595 392 b;2,-1 e 595 144 a;-1,5 -e 640 80 a;-1,0 +e 467 392 b;0,-1 +e 531 392 b;1,-1 +e 595 392 b;2,-1 +e 144 640 a;-1,0 diff --git a/src/test/resources/tree-diffing/createMatching/09_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/createMatching/09_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..8f1ea0152 --- /dev/null +++ b/src/test/resources/tree-diffing/createMatching/09_gumtree-simple-id_expected.lg @@ -0,0 +1,30 @@ +v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 10, diff: 1, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 2, new: -1);;Line 1 +v 267 REM;ARTIFACT;(old: 3, diff: 3, new: -1);(old: 4, diff: 3, new: -1);;Line 2 +v 331 REM;ARTIFACT;(old: 4, diff: 4, new: -1);(old: 5, diff: 4, new: -1);;Line 3 +v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B +v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 +v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 +v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 +v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B +v 704 ADD;IF;(old: -1, diff: 10, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +v 771 ADD;ARTIFACT;(old: -1, diff: 11, new: 3);(old: -1, diff: 11, new: 4);;Line 1 +v 835 ADD;ARTIFACT;(old: -1, diff: 12, new: 4);(old: -1, diff: 12, new: 5);;Line 2 +v 899 ADD;ARTIFACT;(old: -1, diff: 13, new: 5);(old: -1, diff: 13, new: 6);;Line 3 +e 136 80 b;0,-1 +e 640 80 a;-1,0 +e 203 136 b;0,-1 +e 267 136 b;1,-1 +e 331 136 b;2,-1 +e 392 136 b;3,-1 +e 467 392 b;0,-1 +e 531 392 b;1,-1 +e 595 392 b;2,-1 +e 704 640 a;-1,0 +e 771 704 a;-1,0 +e 835 704 a;-1,1 +e 899 704 a;-1,2 +e 467 704 a;-1,3 +e 531 704 a;-1,4 +e 595 704 a;-1,5 diff --git a/src/test/resources/tree-diffing/createMatching/09_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/createMatching/09_gumtree-simple_expected.lg new file mode 100644 index 000000000..8f1ea0152 --- /dev/null +++ b/src/test/resources/tree-diffing/createMatching/09_gumtree-simple_expected.lg @@ -0,0 +1,30 @@ +v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 10, diff: 1, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 2, new: -1);;Line 1 +v 267 REM;ARTIFACT;(old: 3, diff: 3, new: -1);(old: 4, diff: 3, new: -1);;Line 2 +v 331 REM;ARTIFACT;(old: 4, diff: 4, new: -1);(old: 5, diff: 4, new: -1);;Line 3 +v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B +v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 +v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 +v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 +v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B +v 704 ADD;IF;(old: -1, diff: 10, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +v 771 ADD;ARTIFACT;(old: -1, diff: 11, new: 3);(old: -1, diff: 11, new: 4);;Line 1 +v 835 ADD;ARTIFACT;(old: -1, diff: 12, new: 4);(old: -1, diff: 12, new: 5);;Line 2 +v 899 ADD;ARTIFACT;(old: -1, diff: 13, new: 5);(old: -1, diff: 13, new: 6);;Line 3 +e 136 80 b;0,-1 +e 640 80 a;-1,0 +e 203 136 b;0,-1 +e 267 136 b;1,-1 +e 331 136 b;2,-1 +e 392 136 b;3,-1 +e 467 392 b;0,-1 +e 531 392 b;1,-1 +e 595 392 b;2,-1 +e 704 640 a;-1,0 +e 771 704 a;-1,0 +e 835 704 a;-1,1 +e 899 704 a;-1,2 +e 467 704 a;-1,3 +e 531 704 a;-1,4 +e 595 704 a;-1,5 diff --git a/src/test/resources/tree-diffing/09_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/09_gumtree_expected.lg similarity index 68% rename from src/test/resources/tree-diffing/09_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/09_gumtree_expected.lg index 30efe1ca9..dd0703090 100644 --- a/src/test/resources/tree-diffing/09_gumtree_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/09_gumtree_expected.lg @@ -1,23 +1,23 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 +v 144 NON;IF;(old: 1, diff: 1, new: 2);(old: 10, diff: 1, new: 9);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 3);(old: 3, diff: 2, new: 4);;Line 1 +v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 4);(old: 4, diff: 3, new: 5);;Line 2 +v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 5);(old: 5, diff: 4, new: 6);;Line 3 v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B e 144 80 b;0,-1 -e 144 640 a;-1,0 +e 640 80 a;-1,0 e 211 144 ba;0,0 e 275 144 ba;1,1 e 339 144 ba;2,2 e 392 144 b;3,-1 -e 467 392 b;0,-1 e 467 144 a;-1,3 -e 531 392 b;1,-1 e 531 144 a;-1,4 -e 595 392 b;2,-1 e 595 144 a;-1,5 -e 640 80 a;-1,0 +e 467 392 b;0,-1 +e 531 392 b;1,-1 +e 595 392 b;2,-1 +e 144 640 a;-1,0 diff --git a/src/test/resources/tree-diffing/09_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/createMatching/09_longestCommonSequence_expected.lg similarity index 68% rename from src/test/resources/tree-diffing/09_longestCommonSequence_expected.lg rename to src/test/resources/tree-diffing/createMatching/09_longestCommonSequence_expected.lg index 30efe1ca9..dd0703090 100644 --- a/src/test/resources/tree-diffing/09_longestCommonSequence_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/09_longestCommonSequence_expected.lg @@ -1,23 +1,23 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True -v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 10, diff: 1, new: 10);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;Line 1 -v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;Line 2 -v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 4);(old: 5, diff: 4, new: 5);;Line 3 +v 144 NON;IF;(old: 1, diff: 1, new: 2);(old: 10, diff: 1, new: 9);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 3);(old: 3, diff: 2, new: 4);;Line 1 +v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 4);(old: 4, diff: 3, new: 5);;Line 2 +v 339 NON;ARTIFACT;(old: 4, diff: 4, new: 5);(old: 5, diff: 4, new: 6);;Line 3 v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B v 467 NON;ARTIFACT;(old: 6, diff: 6, new: 6);(old: 7, diff: 6, new: 7);;Line 4 v 531 NON;ARTIFACT;(old: 7, diff: 7, new: 7);(old: 8, diff: 7, new: 8);;Line 5 v 595 NON;ARTIFACT;(old: 8, diff: 8, new: 8);(old: 9, diff: 8, new: 9);;Line 6 v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B e 144 80 b;0,-1 -e 144 640 a;-1,0 +e 640 80 a;-1,0 e 211 144 ba;0,0 e 275 144 ba;1,1 e 339 144 ba;2,2 e 392 144 b;3,-1 -e 467 392 b;0,-1 e 467 144 a;-1,3 -e 531 392 b;1,-1 e 531 144 a;-1,4 -e 595 392 b;2,-1 e 595 144 a;-1,5 -e 640 80 a;-1,0 +e 467 392 b;0,-1 +e 531 392 b;1,-1 +e 595 392 b;2,-1 +e 144 640 a;-1,0 diff --git a/src/test/resources/tree-diffing/createMatching/09_xy_expected.lg b/src/test/resources/tree-diffing/createMatching/09_xy_expected.lg new file mode 100644 index 000000000..fa0eefc85 --- /dev/null +++ b/src/test/resources/tree-diffing/createMatching/09_xy_expected.lg @@ -0,0 +1,33 @@ +v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 10, diff: 1, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 2, new: -1);;Line 1 +v 267 REM;ARTIFACT;(old: 3, diff: 3, new: -1);(old: 4, diff: 3, new: -1);;Line 2 +v 331 REM;ARTIFACT;(old: 4, diff: 4, new: -1);(old: 5, diff: 4, new: -1);;Line 3 +v 392 REM;IF;(old: 5, diff: 5, new: -1);(old: 9, diff: 5, new: -1);defined(B);#ifdef B +v 459 REM;ARTIFACT;(old: 6, diff: 6, new: -1);(old: 7, diff: 6, new: -1);;Line 4 +v 523 REM;ARTIFACT;(old: 7, diff: 7, new: -1);(old: 8, diff: 7, new: -1);;Line 5 +v 587 REM;ARTIFACT;(old: 8, diff: 8, new: -1);(old: 9, diff: 8, new: -1);;Line 6 +v 640 ADD;IF;(old: -1, diff: 9, new: 1);(old: -1, diff: 9, new: 10);defined(B);#ifdef B +v 704 ADD;IF;(old: -1, diff: 10, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +v 771 ADD;ARTIFACT;(old: -1, diff: 11, new: 3);(old: -1, diff: 11, new: 4);;Line 1 +v 835 ADD;ARTIFACT;(old: -1, diff: 12, new: 4);(old: -1, diff: 12, new: 5);;Line 2 +v 899 ADD;ARTIFACT;(old: -1, diff: 13, new: 5);(old: -1, diff: 13, new: 6);;Line 3 +v 963 ADD;ARTIFACT;(old: -1, diff: 14, new: 6);(old: -1, diff: 14, new: 7);;Line 4 +v 1027 ADD;ARTIFACT;(old: -1, diff: 15, new: 7);(old: -1, diff: 15, new: 8);;Line 5 +v 1091 ADD;ARTIFACT;(old: -1, diff: 16, new: 8);(old: -1, diff: 16, new: 9);;Line 6 +e 136 80 b;0,-1 +e 640 80 a;-1,0 +e 203 136 b;0,-1 +e 267 136 b;1,-1 +e 331 136 b;2,-1 +e 392 136 b;3,-1 +e 459 392 b;0,-1 +e 523 392 b;1,-1 +e 587 392 b;2,-1 +e 704 640 a;-1,0 +e 771 704 a;-1,0 +e 835 704 a;-1,1 +e 899 704 a;-1,2 +e 963 704 a;-1,3 +e 1027 704 a;-1,4 +e 1091 704 a;-1,5 diff --git a/src/test/resources/tree-diffing/createMatching/10_change-distiller_expected.lg b/src/test/resources/tree-diffing/createMatching/10_change-distiller_expected.lg new file mode 100644 index 000000000..374c4bbd8 --- /dev/null +++ b/src/test/resources/tree-diffing/createMatching/10_change-distiller_expected.lg @@ -0,0 +1,8 @@ +v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 1, new: 4);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 3);(old: 3, diff: 2, new: 4);;456 +v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 2);(old: 4, diff: 3, new: 3);;123 +e 144 80 ba;0,0 +e 275 144 a;1,0 +e 211 144 ba;0,1 +e 275 144 b;1,0 diff --git a/src/test/resources/tree-diffing/10_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/createMatching/10_gumtree-hybrid_expected.lg similarity index 83% rename from src/test/resources/tree-diffing/10_gumtree-hybrid_expected.lg rename to src/test/resources/tree-diffing/createMatching/10_gumtree-hybrid_expected.lg index bb645cdad..d3b568636 100644 --- a/src/test/resources/tree-diffing/10_gumtree-hybrid_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/10_gumtree-hybrid_expected.lg @@ -1,9 +1,9 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 1, new: 4);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;456 +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 3);(old: 3, diff: 2, new: 4);;456 v 267 REM;ARTIFACT;(old: 3, diff: 3, new: -1);(old: 4, diff: 3, new: -1);;123 v 323 ADD;ARTIFACT;(old: -1, diff: 4, new: 2);(old: -1, diff: 4, new: 3);;123 e 144 80 ba;0,0 +e 323 144 a;-1,0 e 211 144 ba;0,1 e 267 144 b;1,-1 -e 323 144 a;-1,0 diff --git a/src/test/resources/tree-diffing/10_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/10_gumtree_expected.lg similarity index 83% rename from src/test/resources/tree-diffing/10_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/10_gumtree_expected.lg index bb645cdad..d3b568636 100644 --- a/src/test/resources/tree-diffing/10_gumtree_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/10_gumtree_expected.lg @@ -1,9 +1,9 @@ v 80 NON;IF;(old: -1, diff: 0, new: -1);(old: -1, diff: 0, new: -1);True v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 1, new: 4);defined(A);#ifdef A -v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 2, new: 3);;456 +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 3);(old: 3, diff: 2, new: 4);;456 v 267 REM;ARTIFACT;(old: 3, diff: 3, new: -1);(old: 4, diff: 3, new: -1);;123 v 323 ADD;ARTIFACT;(old: -1, diff: 4, new: 2);(old: -1, diff: 4, new: 3);;123 e 144 80 ba;0,0 +e 323 144 a;-1,0 e 211 144 ba;0,1 e 267 144 b;1,-1 -e 323 144 a;-1,0 diff --git a/src/test/resources/tree-diffing/11_gumtree_expected.lg b/src/test/resources/tree-diffing/createMatching/11_gumtree_expected.lg similarity index 100% rename from src/test/resources/tree-diffing/11_gumtree_expected.lg rename to src/test/resources/tree-diffing/createMatching/11_gumtree_expected.lg index 2a31da89b..dd58e9c3b 100644 --- a/src/test/resources/tree-diffing/11_gumtree_expected.lg +++ b/src/test/resources/tree-diffing/createMatching/11_gumtree_expected.lg @@ -5,5 +5,5 @@ v 275 NON;ARTIFACT;(old: 3, diff: 3, new: 3);(old: 4, diff: 3, new: 4);;3 v 323 ADD;ARTIFACT;(old: -1, diff: 4, new: 2);(old: -1, diff: 4, new: 3);;B e 147 80 ba;0,0 e 203 80 b;1,-1 -e 275 80 ba;2,2 e 323 80 a;-1,1 +e 275 80 ba;2,2 diff --git a/src/test/resources/tree-diffing/improveMatching/01_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/01_change-distiller_expected.lg new file mode 100644 index 000000000..f398d4d2f --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/01_change-distiller_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line +e 144 16 ba;0,0 +e 211 144 ba;0,0 diff --git a/src/test/resources/tree-diffing/improveMatching/01_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/01_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..f398d4d2f --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/01_gumtree-hybrid-id_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line +e 144 16 ba;0,0 +e 211 144 ba;0,0 diff --git a/src/test/resources/tree-diffing/improveMatching/01_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/01_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..f398d4d2f --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/01_gumtree-hybrid_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line +e 144 16 ba;0,0 +e 211 144 ba;0,0 diff --git a/src/test/resources/tree-diffing/improveMatching/01_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/01_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..f398d4d2f --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/01_gumtree-partition-id_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line +e 144 16 ba;0,0 +e 211 144 ba;0,0 diff --git a/src/test/resources/tree-diffing/improveMatching/01_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/01_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..f398d4d2f --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/01_gumtree-simple-id_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line +e 144 16 ba;0,0 +e 211 144 ba;0,0 diff --git a/src/test/resources/tree-diffing/improveMatching/01_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/01_gumtree-simple_expected.lg new file mode 100644 index 000000000..f398d4d2f --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/01_gumtree-simple_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line +e 144 16 ba;0,0 +e 211 144 ba;0,0 diff --git a/src/test/resources/tree-diffing/improveMatching/01_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/01_gumtree_expected.lg new file mode 100644 index 000000000..f398d4d2f --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/01_gumtree_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line +e 144 16 ba;0,0 +e 211 144 ba;0,0 diff --git a/src/test/resources/tree-diffing/improveMatching/01_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/01_longestCommonSequence_expected.lg new file mode 100644 index 000000000..f398d4d2f --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/01_longestCommonSequence_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line +e 144 16 ba;0,0 +e 211 144 ba;0,0 diff --git a/src/test/resources/tree-diffing/improveMatching/01_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/01_xy_expected.lg new file mode 100644 index 000000000..f398d4d2f --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/01_xy_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 3, diff: 3, new: 3);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line +e 144 16 ba;0,0 +e 211 144 ba;0,0 diff --git a/src/test/resources/tree-diffing/improveMatching/02_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/02_change-distiller_expected.lg new file mode 100644 index 000000000..ee75963ed --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/02_change-distiller_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;Line +e 128 16 a;-1,0 +e 195 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/02_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/02_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..ee75963ed --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/02_gumtree-hybrid-id_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;Line +e 128 16 a;-1,0 +e 195 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/02_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/02_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..ee75963ed --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/02_gumtree-hybrid_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;Line +e 128 16 a;-1,0 +e 195 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/02_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/02_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..ee75963ed --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/02_gumtree-partition-id_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;Line +e 128 16 a;-1,0 +e 195 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/02_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/02_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..ee75963ed --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/02_gumtree-simple-id_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;Line +e 128 16 a;-1,0 +e 195 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/02_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/02_gumtree-simple_expected.lg new file mode 100644 index 000000000..ee75963ed --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/02_gumtree-simple_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;Line +e 128 16 a;-1,0 +e 195 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/02_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/02_gumtree_expected.lg new file mode 100644 index 000000000..ee75963ed --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/02_gumtree_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;Line +e 128 16 a;-1,0 +e 195 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/02_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/02_longestCommonSequence_expected.lg new file mode 100644 index 000000000..ee75963ed --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/02_longestCommonSequence_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;Line +e 128 16 a;-1,0 +e 195 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/02_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/02_xy_expected.lg new file mode 100644 index 000000000..ee75963ed --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/02_xy_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;Line +e 128 16 a;-1,0 +e 195 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/03_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/03_change-distiller_expected.lg new file mode 100644 index 000000000..eca44f07a --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/03_change-distiller_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;Line +e 136 16 b;0,-1 +e 203 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/03_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/03_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..eca44f07a --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/03_gumtree-hybrid-id_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;Line +e 136 16 b;0,-1 +e 203 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/03_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/03_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..eca44f07a --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/03_gumtree-hybrid_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;Line +e 136 16 b;0,-1 +e 203 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/03_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/03_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..eca44f07a --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/03_gumtree-partition-id_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;Line +e 136 16 b;0,-1 +e 203 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/03_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/03_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..eca44f07a --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/03_gumtree-simple-id_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;Line +e 136 16 b;0,-1 +e 203 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/03_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/03_gumtree-simple_expected.lg new file mode 100644 index 000000000..eca44f07a --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/03_gumtree-simple_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;Line +e 136 16 b;0,-1 +e 203 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/03_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/03_gumtree_expected.lg new file mode 100644 index 000000000..eca44f07a --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/03_gumtree_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;Line +e 136 16 b;0,-1 +e 203 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/03_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/03_longestCommonSequence_expected.lg new file mode 100644 index 000000000..eca44f07a --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/03_longestCommonSequence_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;Line +e 136 16 b;0,-1 +e 203 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/03_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/03_xy_expected.lg new file mode 100644 index 000000000..eca44f07a --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/03_xy_expected.lg @@ -0,0 +1,5 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;Line +e 136 16 b;0,-1 +e 203 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/04_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/04_change-distiller_expected.lg new file mode 100644 index 000000000..042594bf8 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/04_change-distiller_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 211 NON;ARTIFACT;(old: 1, diff: 2, new: 2);(old: 2, diff: 3, new: 3);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +e 211 16 b;0,-1 +e 128 16 a;-1,0 +e 211 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/04_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/04_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..042594bf8 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/04_gumtree-hybrid-id_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 211 NON;ARTIFACT;(old: 1, diff: 2, new: 2);(old: 2, diff: 3, new: 3);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +e 211 16 b;0,-1 +e 128 16 a;-1,0 +e 211 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/04_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/04_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..042594bf8 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/04_gumtree-hybrid_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 211 NON;ARTIFACT;(old: 1, diff: 2, new: 2);(old: 2, diff: 3, new: 3);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +e 211 16 b;0,-1 +e 128 16 a;-1,0 +e 211 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/04_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/04_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..042594bf8 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/04_gumtree-partition-id_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 211 NON;ARTIFACT;(old: 1, diff: 2, new: 2);(old: 2, diff: 3, new: 3);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +e 211 16 b;0,-1 +e 128 16 a;-1,0 +e 211 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/04_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/04_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..042594bf8 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/04_gumtree-simple-id_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 211 NON;ARTIFACT;(old: 1, diff: 2, new: 2);(old: 2, diff: 3, new: 3);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +e 211 16 b;0,-1 +e 128 16 a;-1,0 +e 211 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/04_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/04_gumtree-simple_expected.lg new file mode 100644 index 000000000..042594bf8 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/04_gumtree-simple_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 211 NON;ARTIFACT;(old: 1, diff: 2, new: 2);(old: 2, diff: 3, new: 3);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +e 211 16 b;0,-1 +e 128 16 a;-1,0 +e 211 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/04_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/04_gumtree_expected.lg new file mode 100644 index 000000000..042594bf8 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/04_gumtree_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 211 NON;ARTIFACT;(old: 1, diff: 2, new: 2);(old: 2, diff: 3, new: 3);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +e 211 16 b;0,-1 +e 128 16 a;-1,0 +e 211 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/04_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/04_longestCommonSequence_expected.lg new file mode 100644 index 000000000..042594bf8 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/04_longestCommonSequence_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 211 NON;ARTIFACT;(old: 1, diff: 2, new: 2);(old: 2, diff: 3, new: 3);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +e 211 16 b;0,-1 +e 128 16 a;-1,0 +e 211 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/04_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/04_xy_expected.lg new file mode 100644 index 000000000..042594bf8 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/04_xy_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 211 NON;ARTIFACT;(old: 1, diff: 2, new: 2);(old: 2, diff: 3, new: 3);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 3, new: 3);defined(A);#ifdef A +e 211 16 b;0,-1 +e 128 16 a;-1,0 +e 211 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/05_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/05_change-distiller_expected.lg new file mode 100644 index 000000000..ddbfad5f2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/05_change-distiller_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);;Line +e 136 16 b;0,-1 +e 211 16 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/05_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/05_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..ddbfad5f2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/05_gumtree-hybrid-id_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);;Line +e 136 16 b;0,-1 +e 211 16 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/05_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/05_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..ddbfad5f2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/05_gumtree-hybrid_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);;Line +e 136 16 b;0,-1 +e 211 16 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/05_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/05_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..ddbfad5f2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/05_gumtree-partition-id_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);;Line +e 136 16 b;0,-1 +e 211 16 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/05_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/05_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..ddbfad5f2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/05_gumtree-simple-id_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);;Line +e 136 16 b;0,-1 +e 211 16 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/05_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/05_gumtree-simple_expected.lg new file mode 100644 index 000000000..ddbfad5f2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/05_gumtree-simple_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);;Line +e 136 16 b;0,-1 +e 211 16 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/05_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/05_gumtree_expected.lg new file mode 100644 index 000000000..ddbfad5f2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/05_gumtree_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);;Line +e 136 16 b;0,-1 +e 211 16 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/05_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/05_longestCommonSequence_expected.lg new file mode 100644 index 000000000..ddbfad5f2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/05_longestCommonSequence_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);;Line +e 136 16 b;0,-1 +e 211 16 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/05_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/05_xy_expected.lg new file mode 100644 index 000000000..ddbfad5f2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/05_xy_expected.lg @@ -0,0 +1,6 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 3, diff: 3, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 1);(old: 3, diff: 3, new: 2);;Line +e 136 16 b;0,-1 +e 211 16 a;-1,0 +e 211 136 b;0,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/06_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/06_change-distiller_expected.lg new file mode 100644 index 000000000..ad74b36d2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/06_change-distiller_expected.lg @@ -0,0 +1,13 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 5, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line A +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line B +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(A);#ifdef A +v 258 ADD;ELIF;(old: -1, diff: 3, new: 3);(old: -1, diff: 6, new: 5);B;#elif B +e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 339 136 b;1,-1 +e 211 128 a;-1,0 +e 258 128 a;-1,1 +e 339 258 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/06_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/06_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..ad74b36d2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/06_gumtree-hybrid-id_expected.lg @@ -0,0 +1,13 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 5, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line A +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line B +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(A);#ifdef A +v 258 ADD;ELIF;(old: -1, diff: 3, new: 3);(old: -1, diff: 6, new: 5);B;#elif B +e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 339 136 b;1,-1 +e 211 128 a;-1,0 +e 258 128 a;-1,1 +e 339 258 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/06_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/06_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..ad74b36d2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/06_gumtree-hybrid_expected.lg @@ -0,0 +1,13 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 5, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line A +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line B +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(A);#ifdef A +v 258 ADD;ELIF;(old: -1, diff: 3, new: 3);(old: -1, diff: 6, new: 5);B;#elif B +e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 339 136 b;1,-1 +e 211 128 a;-1,0 +e 258 128 a;-1,1 +e 339 258 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/06_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/06_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..ad74b36d2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/06_gumtree-partition-id_expected.lg @@ -0,0 +1,13 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 5, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line A +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line B +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(A);#ifdef A +v 258 ADD;ELIF;(old: -1, diff: 3, new: 3);(old: -1, diff: 6, new: 5);B;#elif B +e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 339 136 b;1,-1 +e 211 128 a;-1,0 +e 258 128 a;-1,1 +e 339 258 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/06_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/06_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..ad74b36d2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/06_gumtree-simple-id_expected.lg @@ -0,0 +1,13 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 5, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line A +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line B +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(A);#ifdef A +v 258 ADD;ELIF;(old: -1, diff: 3, new: 3);(old: -1, diff: 6, new: 5);B;#elif B +e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 339 136 b;1,-1 +e 211 128 a;-1,0 +e 258 128 a;-1,1 +e 339 258 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/06_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/06_gumtree-simple_expected.lg new file mode 100644 index 000000000..ad74b36d2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/06_gumtree-simple_expected.lg @@ -0,0 +1,13 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 5, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line A +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line B +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(A);#ifdef A +v 258 ADD;ELIF;(old: -1, diff: 3, new: 3);(old: -1, diff: 6, new: 5);B;#elif B +e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 339 136 b;1,-1 +e 211 128 a;-1,0 +e 258 128 a;-1,1 +e 339 258 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/06_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/06_gumtree_expected.lg new file mode 100644 index 000000000..ad74b36d2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/06_gumtree_expected.lg @@ -0,0 +1,13 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 5, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line A +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line B +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(A);#ifdef A +v 258 ADD;ELIF;(old: -1, diff: 3, new: 3);(old: -1, diff: 6, new: 5);B;#elif B +e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 339 136 b;1,-1 +e 211 128 a;-1,0 +e 258 128 a;-1,1 +e 339 258 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/06_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/06_longestCommonSequence_expected.lg new file mode 100644 index 000000000..ad74b36d2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/06_longestCommonSequence_expected.lg @@ -0,0 +1,13 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 5, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line A +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line B +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(A);#ifdef A +v 258 ADD;ELIF;(old: -1, diff: 3, new: 3);(old: -1, diff: 6, new: 5);B;#elif B +e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 339 136 b;1,-1 +e 211 128 a;-1,0 +e 258 128 a;-1,1 +e 339 258 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/06_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/06_xy_expected.lg new file mode 100644 index 000000000..ad74b36d2 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/06_xy_expected.lg @@ -0,0 +1,13 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 136 REM;IF;(old: 1, diff: 1, new: -1);(old: 4, diff: 5, new: -1);defined(A);#ifdef A +v 211 NON;ARTIFACT;(old: 2, diff: 2, new: 2);(old: 3, diff: 3, new: 3);;Line A +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line B +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 5, new: 3);defined(A);#ifdef A +v 258 ADD;ELIF;(old: -1, diff: 3, new: 3);(old: -1, diff: 6, new: 5);B;#elif B +e 136 16 b;0,-1 +e 128 16 a;-1,0 +e 211 136 b;0,-1 +e 339 136 b;1,-1 +e 211 128 a;-1,0 +e 258 128 a;-1,1 +e 339 258 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/07_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/07_change-distiller_expected.lg new file mode 100644 index 000000000..74202aadf --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/07_change-distiller_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(CONFIG_A);#ifdef CONFIG_A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(CONFIG_B);#ifdef CONFIG_B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(CONFIG_B);#ifdef CONFIG_B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/07_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/07_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..74202aadf --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/07_gumtree-hybrid-id_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(CONFIG_A);#ifdef CONFIG_A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(CONFIG_B);#ifdef CONFIG_B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(CONFIG_B);#ifdef CONFIG_B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/07_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/07_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..74202aadf --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/07_gumtree-hybrid_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(CONFIG_A);#ifdef CONFIG_A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(CONFIG_B);#ifdef CONFIG_B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(CONFIG_B);#ifdef CONFIG_B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/07_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/07_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..74202aadf --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/07_gumtree-partition-id_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(CONFIG_A);#ifdef CONFIG_A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(CONFIG_B);#ifdef CONFIG_B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(CONFIG_B);#ifdef CONFIG_B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/07_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/07_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..74202aadf --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/07_gumtree-simple-id_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(CONFIG_A);#ifdef CONFIG_A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(CONFIG_B);#ifdef CONFIG_B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(CONFIG_B);#ifdef CONFIG_B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/07_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/07_gumtree-simple_expected.lg new file mode 100644 index 000000000..74202aadf --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/07_gumtree-simple_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(CONFIG_A);#ifdef CONFIG_A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(CONFIG_B);#ifdef CONFIG_B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(CONFIG_B);#ifdef CONFIG_B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/07_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/07_gumtree_expected.lg new file mode 100644 index 000000000..74202aadf --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/07_gumtree_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(CONFIG_A);#ifdef CONFIG_A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(CONFIG_B);#ifdef CONFIG_B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(CONFIG_B);#ifdef CONFIG_B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/07_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/07_longestCommonSequence_expected.lg new file mode 100644 index 000000000..c9b1545b7 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/07_longestCommonSequence_expected.lg @@ -0,0 +1,11 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 208 NON;IF;(old: 1, diff: 2, new: 2);(old: 5, diff: 6, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(CONFIG_B);#ifdef CONFIG_B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(CONFIG_B);#ifdef CONFIG_B +e 208 16 b;0,-1 +e 128 16 a;-1,0 +e 264 208 b;0,-1 +e 339 208 a;-1,0 +e 339 264 b;0,-1 +e 208 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/07_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/07_xy_expected.lg new file mode 100644 index 000000000..74202aadf --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/07_xy_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(CONFIG_A);#ifdef CONFIG_A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(CONFIG_B);#ifdef CONFIG_B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(CONFIG_B);#ifdef CONFIG_B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(CONFIG_A);#ifdef CONFIG_A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/08_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/08_change-distiller_expected.lg new file mode 100644 index 000000000..1a086a222 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/08_change-distiller_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(A);#ifdef A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(B);#ifdef B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/08_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/08_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..1a086a222 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/08_gumtree-hybrid-id_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(A);#ifdef A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(B);#ifdef B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/08_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/08_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..1a086a222 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/08_gumtree-hybrid_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(A);#ifdef A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(B);#ifdef B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/08_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/08_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..1a086a222 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/08_gumtree-partition-id_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(A);#ifdef A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(B);#ifdef B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/08_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/08_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..1a086a222 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/08_gumtree-simple-id_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(A);#ifdef A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(B);#ifdef B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/08_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/08_gumtree-simple_expected.lg new file mode 100644 index 000000000..1a086a222 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/08_gumtree-simple_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(A);#ifdef A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(B);#ifdef B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/08_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/08_gumtree_expected.lg new file mode 100644 index 000000000..1a086a222 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/08_gumtree_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(A);#ifdef A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(B);#ifdef B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/08_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/08_longestCommonSequence_expected.lg new file mode 100644 index 000000000..583cfd7c3 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/08_longestCommonSequence_expected.lg @@ -0,0 +1,11 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 208 NON;IF;(old: 1, diff: 2, new: 2);(old: 5, diff: 6, new: 4);defined(A);#ifdef A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(B);#ifdef B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(B);#ifdef B +e 208 16 b;0,-1 +e 128 16 a;-1,0 +e 264 208 b;0,-1 +e 339 208 a;-1,0 +e 339 264 b;0,-1 +e 208 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/08_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/08_xy_expected.lg new file mode 100644 index 000000000..1a086a222 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/08_xy_expected.lg @@ -0,0 +1,12 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 5, diff: 6, new: -1);defined(A);#ifdef A +v 264 REM;IF;(old: 2, diff: 3, new: -1);(old: 4, diff: 5, new: -1);defined(B);#ifdef B +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;Line +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 6, new: 5);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 5, new: 4);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 264 200 b;0,-1 +e 339 264 b;0,-1 +e 192 128 a;-1,0 +e 339 192 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/09_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/09_change-distiller_expected.lg new file mode 100644 index 000000000..254b343c0 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/09_change-distiller_expected.lg @@ -0,0 +1,23 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 208 NON;IF;(old: 1, diff: 2, new: 2);(old: 10, diff: 11, new: 9);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;Line 1 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line 2 +v 403 NON;ARTIFACT;(old: 4, diff: 5, new: 5);(old: 5, diff: 6, new: 6);;Line 3 +v 456 REM;IF;(old: 5, diff: 6, new: -1);(old: 9, diff: 10, new: -1);defined(B);#ifdef B +v 531 NON;ARTIFACT;(old: 6, diff: 7, new: 6);(old: 7, diff: 8, new: 7);;Line 4 +v 595 NON;ARTIFACT;(old: 7, diff: 8, new: 7);(old: 8, diff: 9, new: 8);;Line 5 +v 659 NON;ARTIFACT;(old: 8, diff: 9, new: 8);(old: 9, diff: 10, new: 9);;Line 6 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);defined(B);#ifdef B +e 208 16 b;0,-1 +e 128 16 a;-1,0 +e 275 208 ba;0,0 +e 339 208 ba;1,1 +e 403 208 ba;2,2 +e 456 208 b;3,-1 +e 531 208 a;-1,3 +e 595 208 a;-1,4 +e 659 208 a;-1,5 +e 531 456 b;0,-1 +e 595 456 b;1,-1 +e 659 456 b;2,-1 +e 208 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/09_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/09_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..44b437996 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/09_gumtree-hybrid-id_expected.lg @@ -0,0 +1,27 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 10, diff: 11, new: -1);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;Line 1 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line 2 +v 403 NON;ARTIFACT;(old: 4, diff: 5, new: 5);(old: 5, diff: 6, new: 6);;Line 3 +v 456 REM;IF;(old: 5, diff: 6, new: -1);(old: 9, diff: 10, new: -1);defined(B);#ifdef B +v 531 NON;ARTIFACT;(old: 6, diff: 7, new: 6);(old: 7, diff: 8, new: 7);;Line 4 +v 595 NON;ARTIFACT;(old: 7, diff: 8, new: 7);(old: 8, diff: 9, new: 8);;Line 5 +v 659 NON;ARTIFACT;(old: 8, diff: 9, new: 8);(old: 9, diff: 10, new: 9);;Line 6 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 275 200 b;0,-1 +e 339 200 b;1,-1 +e 403 200 b;2,-1 +e 456 200 b;3,-1 +e 531 456 b;0,-1 +e 595 456 b;1,-1 +e 659 456 b;2,-1 +e 192 128 a;-1,0 +e 275 192 a;-1,0 +e 339 192 a;-1,1 +e 403 192 a;-1,2 +e 531 192 a;-1,3 +e 595 192 a;-1,4 +e 659 192 a;-1,5 diff --git a/src/test/resources/tree-diffing/improveMatching/09_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/09_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..44b437996 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/09_gumtree-hybrid_expected.lg @@ -0,0 +1,27 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 10, diff: 11, new: -1);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;Line 1 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line 2 +v 403 NON;ARTIFACT;(old: 4, diff: 5, new: 5);(old: 5, diff: 6, new: 6);;Line 3 +v 456 REM;IF;(old: 5, diff: 6, new: -1);(old: 9, diff: 10, new: -1);defined(B);#ifdef B +v 531 NON;ARTIFACT;(old: 6, diff: 7, new: 6);(old: 7, diff: 8, new: 7);;Line 4 +v 595 NON;ARTIFACT;(old: 7, diff: 8, new: 7);(old: 8, diff: 9, new: 8);;Line 5 +v 659 NON;ARTIFACT;(old: 8, diff: 9, new: 8);(old: 9, diff: 10, new: 9);;Line 6 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 275 200 b;0,-1 +e 339 200 b;1,-1 +e 403 200 b;2,-1 +e 456 200 b;3,-1 +e 531 456 b;0,-1 +e 595 456 b;1,-1 +e 659 456 b;2,-1 +e 192 128 a;-1,0 +e 275 192 a;-1,0 +e 339 192 a;-1,1 +e 403 192 a;-1,2 +e 531 192 a;-1,3 +e 595 192 a;-1,4 +e 659 192 a;-1,5 diff --git a/src/test/resources/tree-diffing/improveMatching/09_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/09_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..44b437996 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/09_gumtree-partition-id_expected.lg @@ -0,0 +1,27 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 10, diff: 11, new: -1);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;Line 1 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line 2 +v 403 NON;ARTIFACT;(old: 4, diff: 5, new: 5);(old: 5, diff: 6, new: 6);;Line 3 +v 456 REM;IF;(old: 5, diff: 6, new: -1);(old: 9, diff: 10, new: -1);defined(B);#ifdef B +v 531 NON;ARTIFACT;(old: 6, diff: 7, new: 6);(old: 7, diff: 8, new: 7);;Line 4 +v 595 NON;ARTIFACT;(old: 7, diff: 8, new: 7);(old: 8, diff: 9, new: 8);;Line 5 +v 659 NON;ARTIFACT;(old: 8, diff: 9, new: 8);(old: 9, diff: 10, new: 9);;Line 6 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 275 200 b;0,-1 +e 339 200 b;1,-1 +e 403 200 b;2,-1 +e 456 200 b;3,-1 +e 531 456 b;0,-1 +e 595 456 b;1,-1 +e 659 456 b;2,-1 +e 192 128 a;-1,0 +e 275 192 a;-1,0 +e 339 192 a;-1,1 +e 403 192 a;-1,2 +e 531 192 a;-1,3 +e 595 192 a;-1,4 +e 659 192 a;-1,5 diff --git a/src/test/resources/tree-diffing/improveMatching/09_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/09_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..44b437996 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/09_gumtree-simple-id_expected.lg @@ -0,0 +1,27 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 10, diff: 11, new: -1);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;Line 1 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line 2 +v 403 NON;ARTIFACT;(old: 4, diff: 5, new: 5);(old: 5, diff: 6, new: 6);;Line 3 +v 456 REM;IF;(old: 5, diff: 6, new: -1);(old: 9, diff: 10, new: -1);defined(B);#ifdef B +v 531 NON;ARTIFACT;(old: 6, diff: 7, new: 6);(old: 7, diff: 8, new: 7);;Line 4 +v 595 NON;ARTIFACT;(old: 7, diff: 8, new: 7);(old: 8, diff: 9, new: 8);;Line 5 +v 659 NON;ARTIFACT;(old: 8, diff: 9, new: 8);(old: 9, diff: 10, new: 9);;Line 6 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 275 200 b;0,-1 +e 339 200 b;1,-1 +e 403 200 b;2,-1 +e 456 200 b;3,-1 +e 531 456 b;0,-1 +e 595 456 b;1,-1 +e 659 456 b;2,-1 +e 192 128 a;-1,0 +e 275 192 a;-1,0 +e 339 192 a;-1,1 +e 403 192 a;-1,2 +e 531 192 a;-1,3 +e 595 192 a;-1,4 +e 659 192 a;-1,5 diff --git a/src/test/resources/tree-diffing/improveMatching/09_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/09_gumtree-simple_expected.lg new file mode 100644 index 000000000..44b437996 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/09_gumtree-simple_expected.lg @@ -0,0 +1,27 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 10, diff: 11, new: -1);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;Line 1 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line 2 +v 403 NON;ARTIFACT;(old: 4, diff: 5, new: 5);(old: 5, diff: 6, new: 6);;Line 3 +v 456 REM;IF;(old: 5, diff: 6, new: -1);(old: 9, diff: 10, new: -1);defined(B);#ifdef B +v 531 NON;ARTIFACT;(old: 6, diff: 7, new: 6);(old: 7, diff: 8, new: 7);;Line 4 +v 595 NON;ARTIFACT;(old: 7, diff: 8, new: 7);(old: 8, diff: 9, new: 8);;Line 5 +v 659 NON;ARTIFACT;(old: 8, diff: 9, new: 8);(old: 9, diff: 10, new: 9);;Line 6 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 275 200 b;0,-1 +e 339 200 b;1,-1 +e 403 200 b;2,-1 +e 456 200 b;3,-1 +e 531 456 b;0,-1 +e 595 456 b;1,-1 +e 659 456 b;2,-1 +e 192 128 a;-1,0 +e 275 192 a;-1,0 +e 339 192 a;-1,1 +e 403 192 a;-1,2 +e 531 192 a;-1,3 +e 595 192 a;-1,4 +e 659 192 a;-1,5 diff --git a/src/test/resources/tree-diffing/improveMatching/09_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/09_gumtree_expected.lg new file mode 100644 index 000000000..44b437996 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/09_gumtree_expected.lg @@ -0,0 +1,27 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 10, diff: 11, new: -1);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;Line 1 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line 2 +v 403 NON;ARTIFACT;(old: 4, diff: 5, new: 5);(old: 5, diff: 6, new: 6);;Line 3 +v 456 REM;IF;(old: 5, diff: 6, new: -1);(old: 9, diff: 10, new: -1);defined(B);#ifdef B +v 531 NON;ARTIFACT;(old: 6, diff: 7, new: 6);(old: 7, diff: 8, new: 7);;Line 4 +v 595 NON;ARTIFACT;(old: 7, diff: 8, new: 7);(old: 8, diff: 9, new: 8);;Line 5 +v 659 NON;ARTIFACT;(old: 8, diff: 9, new: 8);(old: 9, diff: 10, new: 9);;Line 6 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 275 200 b;0,-1 +e 339 200 b;1,-1 +e 403 200 b;2,-1 +e 456 200 b;3,-1 +e 531 456 b;0,-1 +e 595 456 b;1,-1 +e 659 456 b;2,-1 +e 192 128 a;-1,0 +e 275 192 a;-1,0 +e 339 192 a;-1,1 +e 403 192 a;-1,2 +e 531 192 a;-1,3 +e 595 192 a;-1,4 +e 659 192 a;-1,5 diff --git a/src/test/resources/tree-diffing/improveMatching/09_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/09_longestCommonSequence_expected.lg new file mode 100644 index 000000000..254b343c0 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/09_longestCommonSequence_expected.lg @@ -0,0 +1,23 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 208 NON;IF;(old: 1, diff: 2, new: 2);(old: 10, diff: 11, new: 9);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;Line 1 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line 2 +v 403 NON;ARTIFACT;(old: 4, diff: 5, new: 5);(old: 5, diff: 6, new: 6);;Line 3 +v 456 REM;IF;(old: 5, diff: 6, new: -1);(old: 9, diff: 10, new: -1);defined(B);#ifdef B +v 531 NON;ARTIFACT;(old: 6, diff: 7, new: 6);(old: 7, diff: 8, new: 7);;Line 4 +v 595 NON;ARTIFACT;(old: 7, diff: 8, new: 7);(old: 8, diff: 9, new: 8);;Line 5 +v 659 NON;ARTIFACT;(old: 8, diff: 9, new: 8);(old: 9, diff: 10, new: 9);;Line 6 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);defined(B);#ifdef B +e 208 16 b;0,-1 +e 128 16 a;-1,0 +e 275 208 ba;0,0 +e 339 208 ba;1,1 +e 403 208 ba;2,2 +e 456 208 b;3,-1 +e 531 208 a;-1,3 +e 595 208 a;-1,4 +e 659 208 a;-1,5 +e 531 456 b;0,-1 +e 595 456 b;1,-1 +e 659 456 b;2,-1 +e 208 128 a;-1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/09_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/09_xy_expected.lg new file mode 100644 index 000000000..44b437996 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/09_xy_expected.lg @@ -0,0 +1,27 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 200 REM;IF;(old: 1, diff: 2, new: -1);(old: 10, diff: 11, new: -1);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;Line 1 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 4);(old: 4, diff: 5, new: 5);;Line 2 +v 403 NON;ARTIFACT;(old: 4, diff: 5, new: 5);(old: 5, diff: 6, new: 6);;Line 3 +v 456 REM;IF;(old: 5, diff: 6, new: -1);(old: 9, diff: 10, new: -1);defined(B);#ifdef B +v 531 NON;ARTIFACT;(old: 6, diff: 7, new: 6);(old: 7, diff: 8, new: 7);;Line 4 +v 595 NON;ARTIFACT;(old: 7, diff: 8, new: 7);(old: 8, diff: 9, new: 8);;Line 5 +v 659 NON;ARTIFACT;(old: 8, diff: 9, new: 8);(old: 9, diff: 10, new: 9);;Line 6 +v 128 ADD;IF;(old: -1, diff: 1, new: 1);(old: -1, diff: 11, new: 10);defined(B);#ifdef B +v 192 ADD;IF;(old: -1, diff: 2, new: 2);(old: -1, diff: 10, new: 9);defined(A);#ifdef A +e 200 16 b;0,-1 +e 128 16 a;-1,0 +e 275 200 b;0,-1 +e 339 200 b;1,-1 +e 403 200 b;2,-1 +e 456 200 b;3,-1 +e 531 456 b;0,-1 +e 595 456 b;1,-1 +e 659 456 b;2,-1 +e 192 128 a;-1,0 +e 275 192 a;-1,0 +e 339 192 a;-1,1 +e 403 192 a;-1,2 +e 531 192 a;-1,3 +e 595 192 a;-1,4 +e 659 192 a;-1,5 diff --git a/src/test/resources/tree-diffing/improveMatching/10_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/10_change-distiller_expected.lg new file mode 100644 index 000000000..953e56d04 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/10_change-distiller_expected.lg @@ -0,0 +1,8 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 5, new: 4);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;456 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 2);(old: 4, diff: 5, new: 3);;123 +e 144 16 ba;0,0 +e 339 144 a;1,0 +e 275 144 ba;0,1 +e 339 144 b;1,0 diff --git a/src/test/resources/tree-diffing/improveMatching/10_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/10_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..b36bd9636 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/10_gumtree-hybrid-id_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 5, new: 4);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;456 +v 331 REM;ARTIFACT;(old: 3, diff: 4, new: -1);(old: 4, diff: 5, new: -1);;123 +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;123 +e 144 16 ba;0,0 +e 195 144 a;-1,0 +e 275 144 ba;0,1 +e 331 144 b;1,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/10_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/10_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..b36bd9636 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/10_gumtree-hybrid_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 5, new: 4);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;456 +v 331 REM;ARTIFACT;(old: 3, diff: 4, new: -1);(old: 4, diff: 5, new: -1);;123 +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;123 +e 144 16 ba;0,0 +e 195 144 a;-1,0 +e 275 144 ba;0,1 +e 331 144 b;1,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/10_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/10_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..b36bd9636 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/10_gumtree-partition-id_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 5, new: 4);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;456 +v 331 REM;ARTIFACT;(old: 3, diff: 4, new: -1);(old: 4, diff: 5, new: -1);;123 +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;123 +e 144 16 ba;0,0 +e 195 144 a;-1,0 +e 275 144 ba;0,1 +e 331 144 b;1,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/10_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/10_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..b36bd9636 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/10_gumtree-simple-id_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 5, new: 4);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;456 +v 331 REM;ARTIFACT;(old: 3, diff: 4, new: -1);(old: 4, diff: 5, new: -1);;123 +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;123 +e 144 16 ba;0,0 +e 195 144 a;-1,0 +e 275 144 ba;0,1 +e 331 144 b;1,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/10_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/10_gumtree-simple_expected.lg new file mode 100644 index 000000000..b36bd9636 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/10_gumtree-simple_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 5, new: 4);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;456 +v 331 REM;ARTIFACT;(old: 3, diff: 4, new: -1);(old: 4, diff: 5, new: -1);;123 +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;123 +e 144 16 ba;0,0 +e 195 144 a;-1,0 +e 275 144 ba;0,1 +e 331 144 b;1,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/10_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/10_gumtree_expected.lg new file mode 100644 index 000000000..b36bd9636 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/10_gumtree_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 5, new: 4);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;456 +v 331 REM;ARTIFACT;(old: 3, diff: 4, new: -1);(old: 4, diff: 5, new: -1);;123 +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;123 +e 144 16 ba;0,0 +e 195 144 a;-1,0 +e 275 144 ba;0,1 +e 331 144 b;1,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/10_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/10_longestCommonSequence_expected.lg new file mode 100644 index 000000000..b36bd9636 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/10_longestCommonSequence_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 5, new: 4);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;456 +v 331 REM;ARTIFACT;(old: 3, diff: 4, new: -1);(old: 4, diff: 5, new: -1);;123 +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;123 +e 144 16 ba;0,0 +e 195 144 a;-1,0 +e 275 144 ba;0,1 +e 331 144 b;1,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/10_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/10_xy_expected.lg new file mode 100644 index 000000000..b36bd9636 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/10_xy_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 144 NON;IF;(old: 1, diff: 1, new: 1);(old: 4, diff: 5, new: 4);defined(A);#ifdef A +v 275 NON;ARTIFACT;(old: 2, diff: 3, new: 3);(old: 3, diff: 4, new: 4);;456 +v 331 REM;ARTIFACT;(old: 3, diff: 4, new: -1);(old: 4, diff: 5, new: -1);;123 +v 195 ADD;ARTIFACT;(old: -1, diff: 2, new: 2);(old: -1, diff: 3, new: 3);;123 +e 144 16 ba;0,0 +e 195 144 a;-1,0 +e 275 144 ba;0,1 +e 331 144 b;1,-1 diff --git a/src/test/resources/tree-diffing/improveMatching/11_change-distiller_expected.lg b/src/test/resources/tree-diffing/improveMatching/11_change-distiller_expected.lg new file mode 100644 index 000000000..0905a5b78 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/11_change-distiller_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;1 +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;2 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;3 +v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;B +e 147 16 ba;0,0 +e 203 16 b;1,-1 +e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/tree-diffing/improveMatching/11_gumtree-hybrid-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/11_gumtree-hybrid-id_expected.lg new file mode 100644 index 000000000..0905a5b78 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/11_gumtree-hybrid-id_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;1 +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;2 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;3 +v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;B +e 147 16 ba;0,0 +e 203 16 b;1,-1 +e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/tree-diffing/improveMatching/11_gumtree-hybrid_expected.lg b/src/test/resources/tree-diffing/improveMatching/11_gumtree-hybrid_expected.lg new file mode 100644 index 000000000..0905a5b78 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/11_gumtree-hybrid_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;1 +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;2 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;3 +v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;B +e 147 16 ba;0,0 +e 203 16 b;1,-1 +e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/tree-diffing/improveMatching/11_gumtree-partition-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/11_gumtree-partition-id_expected.lg new file mode 100644 index 000000000..0905a5b78 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/11_gumtree-partition-id_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;1 +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;2 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;3 +v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;B +e 147 16 ba;0,0 +e 203 16 b;1,-1 +e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/tree-diffing/improveMatching/11_gumtree-simple-id_expected.lg b/src/test/resources/tree-diffing/improveMatching/11_gumtree-simple-id_expected.lg new file mode 100644 index 000000000..0905a5b78 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/11_gumtree-simple-id_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;1 +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;2 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;3 +v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;B +e 147 16 ba;0,0 +e 203 16 b;1,-1 +e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/tree-diffing/improveMatching/11_gumtree-simple_expected.lg b/src/test/resources/tree-diffing/improveMatching/11_gumtree-simple_expected.lg new file mode 100644 index 000000000..0905a5b78 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/11_gumtree-simple_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;1 +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;2 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;3 +v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;B +e 147 16 ba;0,0 +e 203 16 b;1,-1 +e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/tree-diffing/improveMatching/11_gumtree_expected.lg b/src/test/resources/tree-diffing/improveMatching/11_gumtree_expected.lg new file mode 100644 index 000000000..0905a5b78 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/11_gumtree_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;1 +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;2 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;3 +v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;B +e 147 16 ba;0,0 +e 203 16 b;1,-1 +e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/tree-diffing/improveMatching/11_longestCommonSequence_expected.lg b/src/test/resources/tree-diffing/improveMatching/11_longestCommonSequence_expected.lg new file mode 100644 index 000000000..0905a5b78 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/11_longestCommonSequence_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;1 +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;2 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;3 +v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;B +e 147 16 ba;0,0 +e 203 16 b;1,-1 +e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/tree-diffing/improveMatching/11_xy_expected.lg b/src/test/resources/tree-diffing/improveMatching/11_xy_expected.lg new file mode 100644 index 000000000..0905a5b78 --- /dev/null +++ b/src/test/resources/tree-diffing/improveMatching/11_xy_expected.lg @@ -0,0 +1,9 @@ +v 16 NON;IF;(old: -1, diff: -1, new: -1);(old: -1, diff: -1, new: -1);True +v 147 NON;ARTIFACT;(old: 1, diff: 1, new: 1);(old: 2, diff: 2, new: 2);;1 +v 203 REM;ARTIFACT;(old: 2, diff: 2, new: -1);(old: 3, diff: 3, new: -1);;2 +v 339 NON;ARTIFACT;(old: 3, diff: 4, new: 3);(old: 4, diff: 5, new: 4);;3 +v 259 ADD;ARTIFACT;(old: -1, diff: 3, new: 2);(old: -1, diff: 4, new: 3);;B +e 147 16 ba;0,0 +e 203 16 b;1,-1 +e 259 16 a;-1,1 +e 339 16 ba;2,2 diff --git a/src/test/resources/unparser/diffs/01.diff b/src/test/resources/unparser/diffs/01.diff new file mode 100644 index 000000000..471bf6f0f --- /dev/null +++ b/src/test/resources/unparser/diffs/01.diff @@ -0,0 +1,4 @@ + #if A + Code ++#endif A +-#endif B diff --git a/src/test/resources/unparser/diffs/02.diff b/src/test/resources/unparser/diffs/02.diff new file mode 100644 index 000000000..74c2ff65e --- /dev/null +++ b/src/test/resources/unparser/diffs/02.diff @@ -0,0 +1,7 @@ + #ifndef A + code +-#endif + +-#ifndef A + code + #endif // A diff --git a/src/test/resources/unparser/trees/01.txt b/src/test/resources/unparser/trees/01.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/unparser/trees/02.txt b/src/test/resources/unparser/trees/02.txt new file mode 100644 index 000000000..4200a6eb6 --- /dev/null +++ b/src/test/resources/unparser/trees/02.txt @@ -0,0 +1,3 @@ +#ifdef C + boob() +#endif \ No newline at end of file diff --git a/src/test/resources/unparser/trees/03.txt b/src/test/resources/unparser/trees/03.txt new file mode 100644 index 000000000..1e1a94da3 --- /dev/null +++ b/src/test/resources/unparser/trees/03.txt @@ -0,0 +1,11 @@ +#ifdef A + foo(); + bar(); +#else + #ifdef B + baz(); + #endif +#endif +#ifdef C + boob() +#endif \ No newline at end of file diff --git a/src/test/resources/unparser/trees/04.txt b/src/test/resources/unparser/trees/04.txt new file mode 100644 index 000000000..21cb52f21 --- /dev/null +++ b/src/test/resources/unparser/trees/04.txt @@ -0,0 +1,8 @@ +#ifdef A + foo(); + bar(); +#endif + +#if B && (!A || C) + baz(); +#endif \ No newline at end of file diff --git a/src/test/resources/unparser/trees/05.txt b/src/test/resources/unparser/trees/05.txt new file mode 100644 index 000000000..3137d7b23 --- /dev/null +++ b/src/test/resources/unparser/trees/05.txt @@ -0,0 +1,5 @@ +#ifdef A + baz(); + foo(); +#endif +foo(); \ No newline at end of file diff --git a/src/test/resources/unparser/trees/06.txt b/src/test/resources/unparser/trees/06.txt new file mode 100644 index 000000000..b0f909a06 --- /dev/null +++ b/src/test/resources/unparser/trees/06.txt @@ -0,0 +1,5 @@ +#ifdef A + baz(); + foo(); +#endif + diff --git a/src/test/resources/unparser/trees/07.txt b/src/test/resources/unparser/trees/07.txt new file mode 100644 index 000000000..2a248d683 --- /dev/null +++ b/src/test/resources/unparser/trees/07.txt @@ -0,0 +1,9 @@ +#ifdef FEAT_GUI + if (gui.in_use) + gui_mch_set_foreground(); +#else +# ifdef MSWIN + win32_set_foreground(); +# endif +#endif +} diff --git a/src/test/resources/unparser/trees/08.txt b/src/test/resources/unparser/trees/08.txt new file mode 100644 index 000000000..2ba7d7d28 --- /dev/null +++ b/src/test/resources/unparser/trees/08.txt @@ -0,0 +1,11 @@ +#ifdef FEAT_GUI + if (gui.in_use) + { + gui_mch_set_foreground(); + return; + } +#endif +#if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL)) + win32_set_foreground(); +#endif +}