diff options
author | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2013-03-31 18:33:23 -0700 |
---|---|---|
committer | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2013-03-31 18:33:23 -0700 |
commit | 9590dfaacc0bb4ef3057c23b637bb85d258e23b2 (patch) | |
tree | 6e743fb1e7114010ff01d037b31711fc46db0f68 | |
parent | 00fcd46ed0ed3e981e241c8b5458ba821294c669 (diff) | |
parent | 024cdd4136214cec474ec477f04940fcab8ea9c0 (diff) | |
download | scala-9590dfaacc0bb4ef3057c23b637bb85d258e23b2.tar.gz scala-9590dfaacc0bb4ef3057c23b637bb85d258e23b2.tar.bz2 scala-9590dfaacc0bb4ef3057c23b637bb85d258e23b2.zip |
Merge pull request #2330 from adriaanm/partest-difftools
Use java-diff-utils for diffing in partest.
-rw-r--r-- | build.xml | 62 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/nest/Diff.java | 873 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/nest/DiffPrint.java | 606 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/nest/FileManager.scala | 41 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/nest/PathSettings.scala | 3 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/nest/ReflectiveRunner.scala | 5 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/nest/RunnerManager.scala | 1 | ||||
-rw-r--r-- | test/files/run/inline-ex-handlers.check | 915 | ||||
-rw-r--r-- | test/files/run/test-cpp.check | 146 | ||||
-rwxr-xr-x | test/partest | 4 |
10 files changed, 637 insertions, 2019 deletions
@@ -170,11 +170,15 @@ targets exercised: <path id="maven-ant-tasks.classpath" path="${lib-ant.dir}/maven-ant-tasks-2.1.1.jar" /> <typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" /> + <!-- Resolve maven dependencies --> + <!-- work around http://jira.codehaus.org/browse/MANTTASKS-203: java.lang.ClassCastException: org.codehaus.plexus.DefaultPlexusContainer cannot be cast to org.codehaus.plexus.PlexusContainer on repeated use of artifact:dependencies --> <if><not><isset property="maven-deps-done"></isset></not><then> + <mkdir dir="${user.home}/.m2/repository"/> + <!-- This task has an issue where if the user directory does not exist, so we create it above. UGH. --> <artifact:dependencies pathId="extra.tasks.classpath" filesetId="extra.tasks.fileset"> <dependency groupId="biz.aQute" artifactId="bnd" version="1.50.0"/> </artifact:dependencies> @@ -193,16 +197,13 @@ targets exercised: <dependency groupId="org.apache.felix" artifactId="org.apache.felix.framework" version="3.2.2"/> </artifact:dependencies> + <artifact:dependencies pathId="partest.extras.classpath" filesetId="partest.extras.fileset" versionsId="partest.extras.versions"> + <dependency groupId="com.googlecode.java-diff-utils" artifactId="diffutils" version="1.3.0"/> + </artifact:dependencies> + <!-- BND support --> <typedef resource="aQute/bnd/ant/taskdef.properties" classpathref="extra.tasks.classpath" /> - <!-- Resolve maven dependencies --> - <mkdir dir="${user.home}/.m2/repository"/> - <!-- This task has an issue where if the user directory does not exist, so we create it above. UGH. --> - <artifact:dependencies pathId="dependency.classpath" filesetId="dependency.fileset"> - <!--<dependency groupId="com.typesafe" artifactId="config" version="0.4.0"/>--> - </artifact:dependencies> - <!-- Download STARR via maven if `starr.version` is specified. Want to slow down STARR changes, using only released versions. --> <if><isset property="starr.version"/><then> @@ -351,7 +352,6 @@ targets exercised: <fileset dir="${lib-extra.dir}"> <include name="**/*.jar"/> </fileset> - <path refid="dependency.classpath"/> </path> <!-- And print-out what we are building --> @@ -507,6 +507,7 @@ targets exercised: <path id="quick.partest.build.path"> <path refid="quick.scalap.build.path"/> + <path refid="partest.extras.classpath"/> <pathelement location="${scalacheck.jar}"/> </path> @@ -523,6 +524,7 @@ targets exercised: </path> <!-- PACK --> + <!-- also used for docs.* targets TODO: use separate paths for those --> <path id="pack.compiler.path"> <pathelement location="${build-pack.dir}/lib/scala-library.jar"/> <pathelement location="${build-pack.dir}/lib/scala-reflect.jar"/> @@ -532,6 +534,7 @@ targets exercised: <pathelement location="${build-pack.dir}/lib/scala-actors.jar"/> <pathelement location="${ant.jar}"/> <pathelement location="${jline.jar}"/> + <path refid="partest.extras.classpath"/> <path refid="aux.libs"/> </path> @@ -619,6 +622,11 @@ targets exercised: <path id="partest.classpath"> <path refid="pack.compiler.path"/> + <path refid="partest.extras.classpath"/> + </path> + + <path id="partest.build.path"> + <path refid="pack.compiler.path"/> <fileset dir="${partest.dir}/files/lib" includes="*.jar" /> <pathelement location="${pack.dir}/lib/scala-swing.jar"/> <!-- TODO - segregate swing tests (there can't be many) --> </path> @@ -944,6 +952,7 @@ targets exercised: <stopwatch name="docs.@{project}.timer"/> <mkdir dir="${build-docs.dir}/@{project}"/> <if><equals arg1="@{docroot}" arg2="NOT SET"/><then> + <!-- TODO: introduce docs.@{project}.build.path for classpathref --> <scaladoc destdir="${build-docs.dir}/@{project}" doctitle="@{title}" @@ -1100,16 +1109,7 @@ targets exercised: PACKED QUICK BUILD (PACK) ============================================================================ --> <target name="pack.lib" depends="quick.lib, quick.plugins, forkjoin.done"> - <staged-pack project="library"> - <!-- First copy maven dependencies --> - <pre> - <copy todir="${build-pack.dir}/lib"> - <fileset refid="dependency.fileset" /> - <mapper type="flatten" /> - </copy> - </pre> - </staged-pack> - </target> + <staged-pack project="library"/></target> <target name="pack.actors" depends="quick.lib"> <staged-pack project="actors"/> </target> <target name="pack.swing" if="has.java6" depends="quick.swing"> <staged-pack project="swing"/> </target> @@ -1154,8 +1154,15 @@ targets exercised: <!-- depend on quick.done so quick.bin is run when pack.done is --> <target name="pack.done" depends="quick.done, pack.bin"> + <!-- copy dependencies to build/pack/lib, it only takes a second so don't bother with uptodate checks --> + <copy todir="${build-pack.dir}/lib"> + <resources refid="partest.extras.fileset"/> + <mapper classpathref="maven-ant-tasks.classpath" classname="org.apache.maven.artifact.ant.VersionMapper" + from="${partest.extras.versions}" to="flatten"/> + </copy> + <taskdef resource="scala/tools/ant/antlib.xml" classpathref="pack.compiler.path"/> - <taskdef resource="scala/tools/partest/antlib.xml" classpathref="pack.compiler.path"/> + <taskdef resource="scala/tools/partest/antlib.xml" classpathref="partest.classpath"/> </target> @@ -1369,7 +1376,7 @@ targets exercised: srcdir="${partest.srcdir}" scalacopts="${scalac.args.optimise}"> - <compilationpath refid="partest.classpath"/> + <compilationpath refid="partest.build.path"/> <runtests dir="${partest.dir}/${partest.srcdir}/run" includes="*.scala"/> <jvmtests dir="${partest.dir}/${partest.srcdir}/jvm" includes="*.scala"/> </partest> @@ -1380,7 +1387,7 @@ targets exercised: timeout="2400000" srcdir="${partest.srcdir}" scalacopts="${scalac.args.optimise}"> - <compilationpath refid="partest.classpath"/> + <compilationpath refid="partest.build.path"/> <postests dir="${partest.dir}/${partest.srcdir}/pos" includes="*.scala"/> <negtests dir="${partest.dir}/${partest.srcdir}/neg" includes="*.scala"/> <runtests dir="${partest.dir}/${partest.srcdir}/run" includes="*.scala"/> @@ -1407,7 +1414,7 @@ targets exercised: scalacopts="${scalac.args.optimise} -Xplugin-require:continuations -P:continuations:enable"> <compilerarg value="-Xpluginsdir"/> <compilerarg file="${build-quick.dir}/misc/scala-devel/plugins"/> - <compilationpath refid="partest.classpath"/> + <compilationpath refid="partest.build.path"/> <negtests dir="${partest.dir}/${partest.srcdir}/continuations-neg" includes="*.scala"/> <runtests dir="${partest.dir}/${partest.srcdir}/continuations-run" includes="*.scala"/> </partest> @@ -1415,7 +1422,7 @@ targets exercised: <target name="test.scaladoc" depends="pack.done"> <partest erroronfailed="yes" scalacopts="${scalac.args.optimise}" showlog="yes"> - <compilationpath refid="partest.classpath"/> + <compilationpath refid="partest.build.path"/> <runtests dir="${partest.dir}/scaladoc/run" includes="*.scala" /> <scalachecktests dir="${partest.dir}/scaladoc/scalacheck" includes="*.scala" /> </partest> @@ -1423,7 +1430,7 @@ targets exercised: <target name="test.interactive" depends="pack.done"> <partest erroronfailed="yes" scalacopts="${scalac.args.optimise}" showlog="yes"> - <compilationpath refid="partest.classpath"/> + <compilationpath refid="partest.build.path"/> <presentationtests dir="${partest.dir}/${partest.srcdir}/presentation"> <include name="*/*.scala"/> </presentationtests> @@ -1684,6 +1691,13 @@ targets exercised: <include name="scalap.jar"/> </fileset> </copy> + + <copy todir="${dist.dir}/lib"> + <resources refid="partest.extras.fileset"/> + <mapper classpathref="maven-ant-tasks.classpath" classname="org.apache.maven.artifact.ant.VersionMapper" + from="${partest.extras.versions}" to="flatten"/> + </copy> + <mkdir dir="${dist.dir}/bin"/> <!-- TODO - Stop being inefficient and don't copy OSGi bundles overtop other jars. --> <copy-bundle name="scala-library"/> diff --git a/src/partest/scala/tools/partest/nest/Diff.java b/src/partest/scala/tools/partest/nest/Diff.java deleted file mode 100644 index f69fc6858b..0000000000 --- a/src/partest/scala/tools/partest/nest/Diff.java +++ /dev/null @@ -1,873 +0,0 @@ - -package scala.tools.partest.nest; - -import java.util.Hashtable; - -/** A class to compare IndexedSeqs of objects. The result of comparison - is a list of <code>change</code> objects which form an - edit script. The objects compared are traditionally lines - of text from two files. Comparison options such as "ignore - whitespace" are implemented by modifying the <code>equals</code> - and <code>hashcode</code> methods for the objects compared. -<p> - The basic algorithm is described in: </br> - "An O(ND) Difference Algorithm and its Variations", Eugene Myers, - Algorithmica Vol. 1 No. 2, 1986, p 251. -<p> - This class outputs different results from GNU diff 1.15 on some - inputs. Our results are actually better (smaller change list, smaller - total size of changes), but it would be nice to know why. Perhaps - there is a memory overwrite bug in GNU diff 1.15. - - @author Stuart D. Gathman, translated from GNU diff 1.15 - Copyright (C) 2000 Business Management Systems, Inc. -<p> - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. -<p> - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -<p> - You should have received a copy of the <a href=COPYING.txt> - GNU General Public License</a> - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - */ - -public class Diff { - - /** Prepare to find differences between two arrays. Each element of - the arrays is translated to an "equivalence number" based on - the result of <code>equals</code>. The original Object arrays - are no longer needed for computing the differences. They will - be needed again later to print the results of the comparison as - an edit script, if desired. - */ - public Diff(Object[] a,Object[] b) { - Hashtable<Object, Integer> h = new Hashtable<Object, Integer>(a.length + b.length); - filevec[0] = new file_data(a,h); - filevec[1] = new file_data(b,h); - } - - /** 1 more than the maximum equivalence value used for this or its - sibling file. */ - private int equiv_max = 1; - - /** When set to true, the comparison uses a heuristic to speed it up. - With this heuristic, for files with a constant small density - of changes, the algorithm is linear in the file size. */ - public boolean heuristic = false; - - /** When set to true, the algorithm returns a guarranteed minimal - set of changes. This makes things slower, sometimes much slower. */ - public boolean no_discards = false; - - private int[] xvec, yvec; /* IndexedSeqs being compared. */ - private int[] fdiag; /* IndexedSeq, indexed by diagonal, containing - the X coordinate of the point furthest - along the given diagonal in the forward - search of the edit matrix. */ - private int[] bdiag; /* IndexedSeq, indexed by diagonal, containing - the X coordinate of the point furthest - along the given diagonal in the backward - search of the edit matrix. */ - private int fdiagoff, bdiagoff; - private final file_data[] filevec = new file_data[2]; - private int cost; - - /** Find the midpoint of the shortest edit script for a specified - portion of the two files. - - We scan from the beginnings of the files, and simultaneously from the ends, - doing a breadth-first search through the space of edit-sequence. - When the two searches meet, we have found the midpoint of the shortest - edit sequence. - - The value returned is the number of the diagonal on which the midpoint lies. - The diagonal number equals the number of inserted lines minus the number - of deleted lines (counting only lines before the midpoint). - The edit cost is stored into COST; this is the total number of - lines inserted or deleted (counting only lines before the midpoint). - - This function assumes that the first lines of the specified portions - of the two files do not match, and likewise that the last lines do not - match. The caller must trim matching lines from the beginning and end - of the portions it is going to specify. - - Note that if we return the "wrong" diagonal value, or if - the value of bdiag at that diagonal is "wrong", - the worst this can do is cause suboptimal diff output. - It cannot cause incorrect diff output. */ - - private int diag (int xoff, int xlim, int yoff, int ylim) { - final int[] fd = fdiag; // Give the compiler a chance. - final int[] bd = bdiag; // Additional help for the compiler. - final int[] xv = xvec; // Still more help for the compiler. - final int[] yv = yvec; // And more and more . . . - final int dmin = xoff - ylim; // Minimum valid diagonal. - final int dmax = xlim - yoff; // Maximum valid diagonal. - final int fmid = xoff - yoff; // Center diagonal of top-down search. - final int bmid = xlim - ylim; // Center diagonal of bottom-up search. - int fmin = fmid, fmax = fmid; // Limits of top-down search. - int bmin = bmid, bmax = bmid; // Limits of bottom-up search. - /* True if southeast corner is on an odd - diagonal with respect to the northwest. */ - final boolean odd = (fmid - bmid & 1) != 0; - - fd[fdiagoff + fmid] = xoff; - bd[bdiagoff + bmid] = xlim; - - for (int c = 1;; ++c) - { - int d; /* Active diagonal. */ - boolean big_snake = false; - - /* Extend the top-down search by an edit step in each diagonal. */ - if (fmin > dmin) - fd[fdiagoff + --fmin - 1] = -1; - else - ++fmin; - if (fmax < dmax) - fd[fdiagoff + ++fmax + 1] = -1; - else - --fmax; - for (d = fmax; d >= fmin; d -= 2) - { - int x, y, oldx, tlo = fd[fdiagoff + d - 1], thi = fd[fdiagoff + d + 1]; - - if (tlo >= thi) - x = tlo + 1; - else - x = thi; - oldx = x; - y = x - d; - while (x < xlim && y < ylim && xv[x] == yv[y]) { - ++x; ++y; - } - if (x - oldx > 20) - big_snake = true; - fd[fdiagoff + d] = x; - if (odd && bmin <= d && d <= bmax && bd[bdiagoff + d] <= fd[fdiagoff + d]) - { - cost = 2 * c - 1; - return d; - } - } - - /* Similar extend the bottom-up search. */ - if (bmin > dmin) - bd[bdiagoff + --bmin - 1] = Integer.MAX_VALUE; - else - ++bmin; - if (bmax < dmax) - bd[bdiagoff + ++bmax + 1] = Integer.MAX_VALUE; - else - --bmax; - for (d = bmax; d >= bmin; d -= 2) - { - int x, y, oldx, tlo = bd[bdiagoff + d - 1], thi = bd[bdiagoff + d + 1]; - - if (tlo < thi) - x = tlo; - else - x = thi - 1; - oldx = x; - y = x - d; - while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) { - --x; --y; - } - if (oldx - x > 20) - big_snake = true; - bd[bdiagoff + d] = x; - if (!odd && fmin <= d && d <= fmax && bd[bdiagoff + d] <= fd[fdiagoff + d]) - { - cost = 2 * c; - return d; - } - } - - /* Heuristic: check occasionally for a diagonal that has made - lots of progress compared with the edit distance. - If we have any such, find the one that has made the most - progress and return it as if it had succeeded. - - With this heuristic, for files with a constant small density - of changes, the algorithm is linear in the file size. */ - - if (c > 200 && big_snake && heuristic) - { - int best = 0; - int bestpos = -1; - - for (d = fmax; d >= fmin; d -= 2) - { - int dd = d - fmid; - if ((fd[fdiagoff + d] - xoff)*2 - dd > 12 * (c + (dd > 0 ? dd : -dd))) - { - if (fd[fdiagoff + d] * 2 - dd > best - && fd[fdiagoff + d] - xoff > 20 - && fd[fdiagoff + d] - d - yoff > 20) - { - int k; - int x = fd[fdiagoff + d]; - - /* We have a good enough best diagonal; - now insist that it end with a significant snake. */ - for (k = 1; k <= 20; k++) - if (xvec[x - k] != yvec[x - d - k]) - break; - - if (k == 21) - { - best = fd[fdiagoff + d] * 2 - dd; - bestpos = d; - } - } - } - } - if (best > 0) - { - cost = 2 * c - 1; - return bestpos; - } - - best = 0; - for (d = bmax; d >= bmin; d -= 2) - { - int dd = d - bmid; - if ((xlim - bd[bdiagoff + d])*2 + dd > 12 * (c + (dd > 0 ? dd : -dd))) - { - if ((xlim - bd[bdiagoff + d]) * 2 + dd > best - && xlim - bd[bdiagoff + d] > 20 - && ylim - (bd[bdiagoff + d] - d) > 20) - { - /* We have a good enough best diagonal; - now insist that it end with a significant snake. */ - int k; - int x = bd[bdiagoff + d]; - - for (k = 0; k < 20; k++) - if (xvec[x + k] != yvec[x - d + k]) - break; - if (k == 20) - { - best = (xlim - bd[bdiagoff + d]) * 2 + dd; - bestpos = d; - } - } - } - } - if (best > 0) - { - cost = 2 * c - 1; - return bestpos; - } - } - } - } - - /** Compare in detail contiguous subsequences of the two files - which are known, as a whole, to match each other. - - The results are recorded in the IndexedSeqs filevec[N].changed_flag, by - storing a 1 in the element for each line that is an insertion or deletion. - - The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1. - - Note that XLIM, YLIM are exclusive bounds. - All line numbers are origin-0 and discarded lines are not counted. */ - - private void compareseq (int xoff, int xlim, int yoff, int ylim) { - /* Slide down the bottom initial diagonal. */ - while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) { - ++xoff; ++yoff; - } - /* Slide up the top initial diagonal. */ - while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) { - --xlim; --ylim; - } - - /* Handle simple cases. */ - if (xoff == xlim) - while (yoff < ylim) - filevec[1].changed_flag[1+filevec[1].realindexes[yoff++]] = true; - else if (yoff == ylim) - while (xoff < xlim) - filevec[0].changed_flag[1+filevec[0].realindexes[xoff++]] = true; - else - { - /* Find a point of correspondence in the middle of the files. */ - - int d = diag (xoff, xlim, yoff, ylim); - int c = cost; - int f = fdiag[fdiagoff + d]; - int b = bdiag[bdiagoff + d]; - - if (c == 1) - { - /* This should be impossible, because it implies that - one of the two subsequences is empty, - and that case was handled above without calling `diag'. - Let's verify that this is true. */ - throw new IllegalArgumentException("Empty subsequence"); - } - else - { - /* Use that point to split this problem into two subproblems. */ - compareseq (xoff, b, yoff, b - d); - /* This used to use f instead of b, - but that is incorrect! - It is not necessarily the case that diagonal d - has a snake from b to f. */ - compareseq (b, xlim, b - d, ylim); - } - } - } - - /** Discard lines from one file that have no matches in the other file. - */ - - private void discard_confusing_lines() { - filevec[0].discard_confusing_lines(filevec[1]); - filevec[1].discard_confusing_lines(filevec[0]); - } - - private boolean inhibit = false; - - /** Adjust inserts/deletes of blank lines to join changes - as much as possible. - */ - - private void shift_boundaries() { - if (inhibit) - return; - filevec[0].shift_boundaries(filevec[1]); - filevec[1].shift_boundaries(filevec[0]); - } - - public interface ScriptBuilder { - /** Scan the tables of which lines are inserted and deleted, - producing an edit script. - @param changed0 true for lines in first file which do not match 2nd - @param len0 number of lines in first file - @param changed1 true for lines in 2nd file which do not match 1st - @param len1 number of lines in 2nd file - @return a linked list of changes - or null - */ - public change build_script( - boolean[] changed0,int len0, - boolean[] changed1,int len1 - ); - } - - /** Scan the tables of which lines are inserted and deleted, - producing an edit script in reverse order. */ - - static class ReverseScript implements ScriptBuilder { - public change build_script( - final boolean[] changed0,int len0, - final boolean[] changed1,int len1) - { - change script = null; - int i0 = 0, i1 = 0; - while (i0 < len0 || i1 < len1) { - if (changed0[1+i0] || changed1[1+i1]) { - int line0 = i0, line1 = i1; - - /* Find # lines changed here in each file. */ - while (changed0[1+i0]) ++i0; - while (changed1[1+i1]) ++i1; - - /* Record this change. */ - script = new change(line0, line1, i0 - line0, i1 - line1, script); - } - - /* We have reached lines in the two files that match each other. */ - i0++; i1++; - } - - return script; - } - } - - static class ForwardScript implements ScriptBuilder { - /** Scan the tables of which lines are inserted and deleted, - producing an edit script in forward order. */ - public change build_script( - final boolean[] changed0,int len0, - final boolean[] changed1,int len1) - { - change script = null; - int i0 = len0, i1 = len1; - - while (i0 >= 0 || i1 >= 0) - { - if (changed0[i0] || changed1[i1]) - { - int line0 = i0, line1 = i1; - - /* Find # lines changed here in each file. */ - while (changed0[i0]) --i0; - while (changed1[i1]) --i1; - - /* Record this change. */ - script = new change(i0, i1, line0 - i0, line1 - i1, script); - } - - /* We have reached lines in the two files that match each other. */ - i0--; i1--; - } - - return script; - } - } - - /** Standard ScriptBuilders. */ - public final static ScriptBuilder - forwardScript = new ForwardScript(), - reverseScript = new ReverseScript(); - - /* Report the differences of two files. DEPTH is the current directory - depth. */ - public final change diff_2(final boolean reverse) { - return diff(reverse ? reverseScript : forwardScript); - } - - /** Get the results of comparison as an edit script. The script - is described by a list of changes. The standard ScriptBuilder - implementations provide for forward and reverse edit scripts. - Alternate implementations could, for instance, list common elements - instead of differences. - @param bld an object to build the script from change flags - @return the head of a list of changes - */ - public change diff(final ScriptBuilder bld) { - - /* Some lines are obviously insertions or deletions - because they don't match anything. Detect them now, - and avoid even thinking about them in the main comparison algorithm. */ - - discard_confusing_lines (); - - /* Now do the main comparison algorithm, considering just the - undiscarded lines. */ - - xvec = filevec[0].undiscarded; - yvec = filevec[1].undiscarded; - - int diags = - filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines + 3; - fdiag = new int[diags]; - fdiagoff = filevec[1].nondiscarded_lines + 1; - bdiag = new int[diags]; - bdiagoff = filevec[1].nondiscarded_lines + 1; - - compareseq (0, filevec[0].nondiscarded_lines, - 0, filevec[1].nondiscarded_lines); - fdiag = null; - bdiag = null; - - /* Modify the results slightly to make them prettier - in cases where that can validly be done. */ - - shift_boundaries (); - - /* Get the results of comparison in the form of a chain - of `struct change's -- an edit script. */ - return bld.build_script( - filevec[0].changed_flag, - filevec[0].buffered_lines, - filevec[1].changed_flag, - filevec[1].buffered_lines - ); - - } - - /** The result of comparison is an "edit script": a chain of change objects. - Each change represents one place where some lines are deleted - and some are inserted. - - LINE0 and LINE1 are the first affected lines in the two files (origin 0). - DELETED is the number of lines deleted here from file 0. - INSERTED is the number of lines inserted here in file 1. - - If DELETED is 0 then LINE0 is the number of the line before - which the insertion was done; vice versa for INSERTED and LINE1. */ - - public static class change { - /** Previous or next edit command. */ - public change link; - /** # lines of file 1 changed here. */ - public final int inserted; - /** # lines of file 0 changed here. */ - public final int deleted; - /** Line number of 1st deleted line. */ - public final int line0; - /** Line number of 1st inserted line. */ - public final int line1; - - /** Cons an additional entry onto the front of an edit script OLD. - LINE0 and LINE1 are the first affected lines in the two files (origin 0). - DELETED is the number of lines deleted here from file 0. - INSERTED is the number of lines inserted here in file 1. - - If DELETED is 0 then LINE0 is the number of the line before - which the insertion was done; vice versa for INSERTED and LINE1. */ - public change(int line0, int line1, int deleted, int inserted, change old) { - this.line0 = line0; - this.line1 = line1; - this.inserted = inserted; - this.deleted = deleted; - this.link = old; - //System.err.println(line0+","+line1+","+inserted+","+deleted); - } - } - - /** Data on one input file being compared. - */ - - class file_data { - - /** Allocate changed array for the results of comparison. */ - void clear() { - /* Allocate a flag for each line of each file, saying whether that line - is an insertion or deletion. - Allocate an extra element, always zero, at each end of each IndexedSeq. - */ - changed_flag = new boolean[buffered_lines + 2]; - } - - /** Return equiv_count[I] as the number of lines in this file - that fall in equivalence class I. - @return the array of equivalence class counts. - */ - int[] equivCount() { - int[] equiv_count = new int[equiv_max]; - for (int i = 0; i < buffered_lines; ++i) - ++equiv_count[equivs[i]]; - return equiv_count; - } - - /** Discard lines that have no matches in another file. - - A line which is discarded will not be considered by the actual - comparison algorithm; it will be as if that line were not in the file. - The file's `realindexes' table maps virtual line numbers - (which don't count the discarded lines) into real line numbers; - this is how the actual comparison algorithm produces results - that are comprehensible when the discarded lines are counted. -<p> - When we discard a line, we also mark it as a deletion or insertion - so that it will be printed in the output. - @param f the other file - */ - void discard_confusing_lines(file_data f) { - clear(); - /* Set up table of which lines are going to be discarded. */ - final byte[] discarded = discardable(f.equivCount()); - - /* Don't really discard the provisional lines except when they occur - in a run of discardables, with nonprovisionals at the beginning - and end. */ - filterDiscards(discarded); - - /* Actually discard the lines. */ - discard(discarded); - } - - /** Mark to be discarded each line that matches no line of another file. - If a line matches many lines, mark it as provisionally discardable. - @see equivCount() - @param counts The count of each equivalence number for the other file. - @return 0=nondiscardable, 1=discardable or 2=provisionally discardable - for each line - */ - - private byte[] discardable(final int[] counts) { - final int end = buffered_lines; - final byte[] discards = new byte[end]; - final int[] equivs = this.equivs; - int many = 5; - int tem = end / 64; - - /* Multiply MANY by approximate square root of number of lines. - That is the threshold for provisionally discardable lines. */ - while ((tem = tem >> 2) > 0) - many *= 2; - - for (int i = 0; i < end; i++) - { - int nmatch; - if (equivs[i] == 0) - continue; - nmatch = counts[equivs[i]]; - if (nmatch == 0) - discards[i] = 1; - else if (nmatch > many) - discards[i] = 2; - } - return discards; - } - - /** Don't really discard the provisional lines except when they occur - in a run of discardables, with nonprovisionals at the beginning - and end. */ - - private void filterDiscards(final byte[] discards) { - final int end = buffered_lines; - - for (int i = 0; i < end; i++) - { - /* Cancel provisional discards not in middle of run of discards. */ - if (discards[i] == 2) - discards[i] = 0; - else if (discards[i] != 0) - { - /* We have found a nonprovisional discard. */ - int j; - int length; - int provisional = 0; - - /* Find end of this run of discardable lines. - Count how many are provisionally discardable. */ - for (j = i; j < end; j++) - { - if (discards[j] == 0) - break; - if (discards[j] == 2) - ++provisional; - } - - /* Cancel provisional discards at end, and shrink the run. */ - while (j > i && discards[j - 1] == 2) { - discards[--j] = 0; --provisional; - } - - /* Now we have the length of a run of discardable lines - whose first and last are not provisional. */ - length = j - i; - - /* If 1/4 of the lines in the run are provisional, - cancel discarding of all provisional lines in the run. */ - if (provisional * 4 > length) - { - while (j > i) - if (discards[--j] == 2) - discards[j] = 0; - } - else - { - int consec; - int minimum = 1; - int tem = length / 4; - - /* MINIMUM is approximate square root of LENGTH/4. - A subrun of two or more provisionals can stand - when LENGTH is at least 16. - A subrun of 4 or more can stand when LENGTH >= 64. */ - while ((tem = tem >> 2) > 0) - minimum *= 2; - minimum++; - - /* Cancel any subrun of MINIMUM or more provisionals - within the larger run. */ - for (j = 0, consec = 0; j < length; j++) - if (discards[i + j] != 2) - consec = 0; - else if (minimum == ++consec) - /* Back up to start of subrun, to cancel it all. */ - j -= consec; - else if (minimum < consec) - discards[i + j] = 0; - - /* Scan from beginning of run - until we find 3 or more nonprovisionals in a row - or until the first nonprovisional at least 8 lines in. - Until that point, cancel any provisionals. */ - for (j = 0, consec = 0; j < length; j++) - { - if (j >= 8 && discards[i + j] == 1) - break; - if (discards[i + j] == 2) { - consec = 0; discards[i + j] = 0; - } - else if (discards[i + j] == 0) - consec = 0; - else - consec++; - if (consec == 3) - break; - } - - /* I advances to the last line of the run. */ - i += length - 1; - - /* Same thing, from end. */ - for (j = 0, consec = 0; j < length; j++) - { - if (j >= 8 && discards[i - j] == 1) - break; - if (discards[i - j] == 2) { - consec = 0; discards[i - j] = 0; - } - else if (discards[i - j] == 0) - consec = 0; - else - consec++; - if (consec == 3) - break; - } - } - } - } - } - - /** Actually discard the lines. - @param discards flags lines to be discarded - */ - private void discard(final byte[] discards) { - final int end = buffered_lines; - int j = 0; - for (int i = 0; i < end; ++i) - if (no_discards || discards[i] == 0) - { - undiscarded[j] = equivs[i]; - realindexes[j++] = i; - } - else - changed_flag[1+i] = true; - nondiscarded_lines = j; - } - - file_data(Object[] data, Hashtable<Object, Integer> h) { - buffered_lines = data.length; - - equivs = new int[buffered_lines]; - undiscarded = new int[buffered_lines]; - realindexes = new int[buffered_lines]; - - for (int i = 0; i < data.length; ++i) { - Integer ir = h.get(data[i]); - if (ir == null) - h.put(data[i], new Integer(equivs[i] = equiv_max++)); - else - equivs[i] = ir.intValue(); - } - } - - /** Adjust inserts/deletes of blank lines to join changes - as much as possible. - - We do something when a run of changed lines include a blank - line at one end and have an excluded blank line at the other. - We are free to choose which blank line is included. - `compareseq' always chooses the one at the beginning, - but usually it is cleaner to consider the following blank line - to be the "change". The only exception is if the preceding blank line - would join this change to other changes. - @param f the file being compared against - */ - - void shift_boundaries(file_data f) { - final boolean[] changed = changed_flag; - final boolean[] other_changed = f.changed_flag; - int i = 0; - int j = 0; - int i_end = buffered_lines; - int preceding = -1; - int other_preceding = -1; - - for (;;) - { - int start, end, other_start; - - /* Scan forwards to find beginning of another run of changes. - Also keep track of the corresponding point in the other file. */ - - while (i < i_end && !changed[1+i]) - { - while (other_changed[1+j++]) - /* Non-corresponding lines in the other file - will count as the preceding batch of changes. */ - other_preceding = j; - i++; - } - - if (i == i_end) - break; - - start = i; - other_start = j; - - for (;;) - { - /* Now find the end of this run of changes. */ - - while (i < i_end && changed[1+i]) i++; - end = i; - - /* If the first changed line matches the following unchanged one, - and this run does not follow right after a previous run, - and there are no lines deleted from the other file here, - then classify the first changed line as unchanged - and the following line as changed in its place. */ - - /* You might ask, how could this run follow right after another? - Only because the previous run was shifted here. */ - - if (end != i_end - && equivs[start] == equivs[end] - && !other_changed[1+j] - && end != i_end - && !((preceding >= 0 && start == preceding) - || (other_preceding >= 0 - && other_start == other_preceding))) - { - changed[1+end++] = true; - changed[1+start++] = false; - ++i; - /* Since one line-that-matches is now before this run - instead of after, we must advance in the other file - to keep in synch. */ - ++j; - } - else - break; - } - - preceding = i; - other_preceding = j; - } - } - - /** Number of elements (lines) in this file. */ - final int buffered_lines; - - /** IndexedSeq, indexed by line number, containing an equivalence code for - each line. It is this IndexedSeq that is actually compared with that - of another file to generate differences. */ - private final int[] equivs; - - /** IndexedSeq, like the previous one except that - the elements for discarded lines have been squeezed out. */ - final int[] undiscarded; - - /** IndexedSeq mapping virtual line numbers (not counting discarded lines) - to real ones (counting those lines). Both are origin-0. */ - final int[] realindexes; - - /** Total number of nondiscarded lines. */ - int nondiscarded_lines; - - /** Array, indexed by real origin-1 line number, - containing true for a line that is an insertion or a deletion. - The results of comparison are stored here. */ - boolean[] changed_flag; - - } -} diff --git a/src/partest/scala/tools/partest/nest/DiffPrint.java b/src/partest/scala/tools/partest/nest/DiffPrint.java deleted file mode 100644 index 31f9a1bc79..0000000000 --- a/src/partest/scala/tools/partest/nest/DiffPrint.java +++ /dev/null @@ -1,606 +0,0 @@ - -package scala.tools.partest.nest; - -import java.io.*; -import java.util.Vector; -import java.util.Date; -//import com.objectspace.jgl.predicates.UnaryPredicate; - -interface UnaryPredicate { - boolean execute(Object obj); -} - -/** A simple framework for printing change lists produced by <code>Diff</code>. - @see bmsi.util.Diff - @author Stuart D. Gathman - Copyright (C) 2000 Business Management Systems, Inc. -<p> - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. -<p> - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -<p> - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -public class DiffPrint { - /** A Base class for printing edit scripts produced by Diff. - This class divides the change list into "hunks", and calls - <code>print_hunk</code> for each hunk. Various utility methods - are provided as well. - */ - public static abstract class Base { - protected Base(Object[] a,Object[] b, Writer w) { - outfile = new PrintWriter(w); - file0 = a; - file1 = b; - } - /** Set to ignore certain kinds of lines when printing - an edit script. For example, ignoring blank lines or comments. - */ - protected UnaryPredicate ignore = null; - - /** Set to the lines of the files being compared. - */ - protected Object[] file0, file1; - - /** Divide SCRIPT into pieces by calling HUNKFUN and - print each piece with PRINTFUN. - Both functions take one arg, an edit script. - - PRINTFUN takes a subscript which belongs together (with a null - link at the end) and prints it. */ - public void print_script(Diff.change script) { - Diff.change next = script; - - while (next != null) - { - Diff.change t, end; - - /* Find a set of changes that belong together. */ - t = next; - end = hunkfun(next); - - /* Disconnect them from the rest of the changes, - making them a hunk, and remember the rest for next iteration. */ - next = end.link; - end.link = null; - //if (DEBUG) - // debug_script(t); - - /* Print this hunk. */ - print_hunk(t); - - /* Reconnect the script so it will all be freed properly. */ - end.link = next; - } - outfile.flush(); - } - - /** Called with the tail of the script - and returns the last link that belongs together with the start - of the tail. */ - - protected Diff.change hunkfun(Diff.change hunk) { - return hunk; - } - - protected int first0, last0, first1, last1, deletes, inserts; - protected PrintWriter outfile; - - /** Look at a hunk of edit script and report the range of lines in each file - that it applies to. HUNK is the start of the hunk, which is a chain - of `struct change'. The first and last line numbers of file 0 are stored - in *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1. - Note that these are internal line numbers that count from 0. - - If no lines from file 0 are deleted, then FIRST0 is LAST0+1. - - Also set *DELETES nonzero if any lines of file 0 are deleted - and set *INSERTS nonzero if any lines of file 1 are inserted. - If only ignorable lines are inserted or deleted, both are - set to 0. */ - - protected void analyze_hunk(Diff.change hunk) { - int f0, l0 = 0, f1, l1 = 0, show_from = 0, show_to = 0; - int i; - Diff.change next; - boolean nontrivial = (ignore == null); - - show_from = show_to = 0; - - f0 = hunk.line0; - f1 = hunk.line1; - - for (next = hunk; next != null; next = next.link) - { - l0 = next.line0 + next.deleted - 1; - l1 = next.line1 + next.inserted - 1; - show_from += next.deleted; - show_to += next.inserted; - for (i = next.line0; i <= l0 && ! nontrivial; i++) - if (!ignore.execute(file0[i])) - nontrivial = true; - for (i = next.line1; i <= l1 && ! nontrivial; i++) - if (!ignore.execute(file1[i])) - nontrivial = true; - } - - first0 = f0; - last0 = l0; - first1 = f1; - last1 = l1; - - /* If all inserted or deleted lines are ignorable, - tell the caller to ignore this hunk. */ - - if (!nontrivial) - show_from = show_to = 0; - - deletes = show_from; - inserts = show_to; - } - - /** Print the script header which identifies the files compared. */ - protected void print_header(String filea, String fileb) { } - - protected abstract void print_hunk(Diff.change hunk); - - protected void print_1_line(String pre,Object linbuf) { - outfile.println(pre + linbuf.toString()); - } - - /** Print a pair of line numbers with SEPCHAR, translated for file FILE. - If the two numbers are identical, print just one number. - - Args A and B are internal line numbers. - We print the translated (real) line numbers. */ - - protected void print_number_range (char sepchar, int a, int b) { - /* Note: we can have B < A in the case of a range of no lines. - In this case, we should print the line number before the range, - which is B. */ - if (++b > ++a) - outfile.print("" + a + sepchar + b); - else - outfile.print(b); - } - - public static char change_letter(int inserts, int deletes) { - if (inserts == 0) - return 'd'; - else if (deletes == 0) - return 'a'; - else - return 'c'; - } - } - - /** Print a change list in the standard diff format. - */ - public static class NormalPrint extends Base { - - public NormalPrint(Object[] a,Object[] b, Writer w) { - super(a,b,w); - } - - /** Print a hunk of a normal diff. - This is a contiguous portion of a complete edit script, - describing changes in consecutive lines. */ - - protected void print_hunk (Diff.change hunk) { - - /* Determine range of line numbers involved in each file. */ - analyze_hunk(hunk); - if (deletes == 0 && inserts == 0) - return; - - /* Print out the line number header for this hunk */ - print_number_range (',', first0, last0); - outfile.print(change_letter(inserts, deletes)); - print_number_range (',', first1, last1); - outfile.println(); - - /* Print the lines that the first file has. */ - if (deletes != 0) - for (int i = first0; i <= last0; i++) - print_1_line ("< ", file0[i]); - - if (inserts != 0 && deletes != 0) - outfile.println("---"); - - /* Print the lines that the second file has. */ - if (inserts != 0) - for (int i = first1; i <= last1; i++) - print_1_line ("> ", file1[i]); - } - } - - /** Prints an edit script in a format suitable for input to <code>ed</code>. - The edit script must be generated with the reverse option to - be useful as actual <code>ed</code> input. - */ - public static class EdPrint extends Base { - - public EdPrint(Object[] a,Object[] b, Writer w) { - super(a,b,w); - } - - /** Print a hunk of an ed diff */ - protected void print_hunk(Diff.change hunk) { - - /* Determine range of line numbers involved in each file. */ - analyze_hunk (hunk); - if (deletes == 0 && inserts == 0) - return; - - /* Print out the line number header for this hunk */ - print_number_range (',', first0, last0); - outfile.println(change_letter(inserts, deletes)); - - /* Print new/changed lines from second file, if needed */ - if (inserts != 0) - { - boolean inserting = true; - for (int i = first1; i <= last1; i++) - { - /* Resume the insert, if we stopped. */ - if (! inserting) - outfile.println(i - first1 + first0 + "a"); - inserting = true; - - /* If the file's line is just a dot, it would confuse `ed'. - So output it with a double dot, and set the flag LEADING_DOT - so that we will output another ed-command later - to change the double dot into a single dot. */ - - if (".".equals(file1[i])) - { - outfile.println(".."); - outfile.println("."); - /* Now change that double dot to the desired single dot. */ - outfile.println(i - first1 + first0 + 1 + "s/^\\.\\././"); - inserting = false; - } - else - /* Line is not `.', so output it unmodified. */ - print_1_line ("", file1[i]); - } - - /* End insert mode, if we are still in it. */ - if (inserting) - outfile.println("."); - } - } - } - - /** Prints an edit script in context diff format. This and its - 'unified' variation is used for source code patches. - */ - public static class ContextPrint extends Base { - - protected int context = 3; - - public ContextPrint(Object[] a,Object[] b, Writer w) { - super(a,b,w); - } - - protected void print_context_label (String mark, File inf, String label) { - if (label != null) - outfile.println(mark + ' ' + label); - else if (inf.lastModified() > 0) - // FIXME: use DateFormat to get precise format needed. - outfile.println( - mark + ' ' + inf.getPath() + '\t' + new Date(inf.lastModified()) - ); - else - /* Don't pretend that standard input is ancient. */ - outfile.println(mark + ' ' + inf.getPath()); - } - - public void print_header(String filea,String fileb) { - print_context_label ("***", new File(filea), filea); - print_context_label ("---", new File(fileb), fileb); - } - - /** If function_regexp defined, search for start of function. */ - private String find_function(Object[] lines, int start) { - return null; - } - - protected void print_function(Object[] file,int start) { - String function = find_function (file0, first0); - if (function != null) { - outfile.print(" "); - outfile.print( - (function.length() < 40) ? function : function.substring(0,40) - ); - } - } - - protected void print_hunk(Diff.change hunk) { - - /* Determine range of line numbers involved in each file. */ - - analyze_hunk (hunk); - - if (deletes == 0 && inserts == 0) - return; - - /* Include a context's width before and after. */ - - first0 = Math.max(first0 - context, 0); - first1 = Math.max(first1 - context, 0); - last0 = Math.min(last0 + context, file0.length - 1); - last1 = Math.min(last1 + context, file1.length - 1); - - - outfile.print("***************"); - - /* If we looked for and found a function this is part of, - include its name in the header of the diff section. */ - print_function (file0, first0); - - outfile.println(); - outfile.print("*** "); - print_number_range (',', first0, last0); - outfile.println(" ****"); - - if (deletes != 0) { - Diff.change next = hunk; - - for (int i = first0; i <= last0; i++) { - /* Skip past changes that apply (in file 0) - only to lines before line I. */ - - while (next != null && next.line0 + next.deleted <= i) - next = next.link; - - /* Compute the marking for line I. */ - - String prefix = " "; - if (next != null && next.line0 <= i) - /* The change NEXT covers this line. - If lines were inserted here in file 1, this is "changed". - Otherwise it is "deleted". */ - prefix = (next.inserted > 0) ? "!" : "-"; - - print_1_line (prefix, file0[i]); - } - } - - outfile.print("--- "); - print_number_range (',', first1, last1); - outfile.println(" ----"); - - if (inserts != 0) { - Diff.change next = hunk; - - for (int i = first1; i <= last1; i++) { - /* Skip past changes that apply (in file 1) - only to lines before line I. */ - - while (next != null && next.line1 + next.inserted <= i) - next = next.link; - - /* Compute the marking for line I. */ - - String prefix = " "; - if (next != null && next.line1 <= i) - /* The change NEXT covers this line. - If lines were deleted here in file 0, this is "changed". - Otherwise it is "inserted". */ - prefix = (next.deleted > 0) ? "!" : "+"; - - print_1_line (prefix, file1[i]); - } - } - } - } - - /** Prints an edit script in context diff format. This and its - 'unified' variation is used for source code patches. - */ - public static class UnifiedPrint extends ContextPrint { - - public UnifiedPrint(Object[] a,Object[] b, Writer w) { - super(a,b,w); - } - - public void print_header(String filea,String fileb) { - print_context_label ("---", new File(filea), filea); - print_context_label ("+++", new File(fileb), fileb); - } - - private void print_number_range (int a, int b) { - //translate_range (file, a, b, &trans_a, &trans_b); - - /* Note: we can have B < A in the case of a range of no lines. - In this case, we should print the line number before the range, - which is B. */ - if (b < a) - outfile.print(b + ",0"); - else - super.print_number_range(',',a,b); - } - - protected void print_hunk(Diff.change hunk) { - /* Determine range of line numbers involved in each file. */ - analyze_hunk (hunk); - - if (deletes == 0 && inserts == 0) - return; - - /* Include a context's width before and after. */ - - first0 = Math.max(first0 - context, 0); - first1 = Math.max(first1 - context, 0); - last0 = Math.min(last0 + context, file0.length - 1); - last1 = Math.min(last1 + context, file1.length - 1); - - - - outfile.print("@@ -"); - print_number_range (first0, last0); - outfile.print(" +"); - print_number_range (first1, last1); - outfile.print(" @@"); - - /* If we looked for and found a function this is part of, - include its name in the header of the diff section. */ - print_function(file0,first0); - - outfile.println(); - - Diff.change next = hunk; - int i = first0; - int j = first1; - - while (i <= last0 || j <= last1) { - - /* If the line isn't a difference, output the context from file 0. */ - - if (next == null || i < next.line0) { - outfile.print(' '); - print_1_line ("", file0[i++]); - j++; - } - else { - /* For each difference, first output the deleted part. */ - - int k = next.deleted; - while (k-- > 0) { - outfile.print('-'); - print_1_line ("", file0[i++]); - } - - /* Then output the inserted part. */ - - k = next.inserted; - while (k-- > 0) { - outfile.print('+'); - print_1_line ("", file1[j++]); - } - - /* We're done with this hunk, so on to the next! */ - - next = next.link; - } - } - } - } - - - /** Read a text file into an array of String. This provides basic diff - functionality. A more advanced diff utility will use specialized - objects to represent the text lines, with options to, for example, - convert sequences of whitespace to a single space for comparison - purposes. - */ - static String[] slurp(String file) throws IOException { - BufferedReader rdr = new BufferedReader(new FileReader(file)); - Vector<String> s = new Vector<String>(); - for (;;) { - String line = rdr.readLine(); - if (line == null) break; - s.addElement(line); - } - String[] a = new String[s.size()]; - s.copyInto(a); - return a; - } - - public static void main(String[] argv) throws IOException { - String filea = argv[argv.length - 2]; - String fileb = argv[argv.length - 1]; - String[] a = slurp(filea); - String[] b = slurp(fileb); - Diff d = new Diff(a,b); - char style = 'n'; - for (int i = 0; i < argv.length - 2; ++i) { - String f = argv[i]; - if (f.startsWith("-")) { - for (int j = 1; j < f.length(); ++j) { - switch (f.charAt(j)) { - case 'e': // Ed style - style = 'e'; break; - case 'c': // Context diff - style = 'c'; break; - case 'u': - style = 'u'; break; - } - } - } - } - boolean reverse = style == 'e'; - Diff.change script = d.diff_2(reverse); - if (script == null) - System.err.println("No differences"); - else { - Base p; - Writer w = new OutputStreamWriter(System.out); - switch (style) { - case 'e': - p = new EdPrint(a,b,w); break; - case 'c': - p = new ContextPrint(a,b,w); break; - case 'u': - p = new UnifiedPrint(a,b,w); break; - default: - p = new NormalPrint(a,b,w); - } - p.print_header(filea,fileb); - p.print_script(script); - } - } - - public static void doDiff(String[] argv, Writer w) throws IOException { - String filea = argv[argv.length - 2]; - String fileb = argv[argv.length - 1]; - String[] a = slurp(filea); - String[] b = slurp(fileb); - Diff d = new Diff(a,b); - char style = 'n'; - for (int i = 0; i < argv.length - 2; ++i) { - String f = argv[i]; - if (f.startsWith("-")) { - for (int j = 1; j < f.length(); ++j) { - switch (f.charAt(j)) { - case 'e': // Ed style - style = 'e'; break; - case 'c': // Context diff - style = 'c'; break; - case 'u': - style = 'u'; break; - } - } - } - } - boolean reverse = style == 'e'; - Diff.change script = d.diff_2(reverse); - if (script == null) - w.write("No differences\n"); - else { - Base p; - switch (style) { - case 'e': - p = new EdPrint(a,b,w); break; - case 'c': - p = new ContextPrint(a,b,w); break; - case 'u': - p = new UnifiedPrint(a,b,w); break; - default: - p = new NormalPrint(a,b,w); - } - p.print_header(filea,fileb); - p.print_script(script); - } - } - -} diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala index 2823967ecf..70fdb33c6a 100644 --- a/src/partest/scala/tools/partest/nest/FileManager.scala +++ b/src/partest/scala/tools/partest/nest/FileManager.scala @@ -18,34 +18,31 @@ import scala.collection.mutable trait FileUtil { /** - * Compares two files using a Java implementation of the GNU diff - * available at http://www.bmsi.com/java/#diff. + * Compares two files using difflib to produce a unified diff. * * @param f1 the first file to be compared * @param f2 the second file to be compared - * @return the text difference between the compared files + * @return the unified diff of the compared files or the empty string if they're equal */ def compareFiles(f1: File, f2: File): String = { - val diffWriter = new StringWriter - val args = Array(f1.getAbsolutePath(), f2.getAbsolutePath()) - - DiffPrint.doDiff(args, diffWriter) - val res = diffWriter.toString - if (res startsWith "No") "" else res + compareContents(io.Source.fromFile(f1).getLines.toSeq, io.Source.fromFile(f2).getLines.toSeq, f1.getName, f2.getName) } - def compareContents(lines1: Seq[String], lines2: Seq[String]): String = { - val xs1 = lines1.toArray[AnyRef] - val xs2 = lines2.toArray[AnyRef] - - val diff = new Diff(xs1, xs2) - val change = diff.diff_2(false) - val writer = new StringWriter - val p = new DiffPrint.NormalPrint(xs1, xs2, writer) - - p.print_script(change) - val res = writer.toString - if (res startsWith "No ") "" - else res + + /** + * Compares two lists of lines using difflib to produce a unified diff. + * + * @param origLines the first seq of lines to be compared + * @param newLines the second seq of lines to be compared + * @param origName file name to be used in unified diff for `origLines` + * @param newName file name to be used in unified diff for `newLines` + * @return the unified diff of the `origLines` and `newLines` or the empty string if they're equal + */ + def compareContents(origLines: Seq[String], newLines: Seq[String], origName: String = "a", newName: String = "b"): String = { + import collection.JavaConverters._ + + val diff = difflib.DiffUtils.diff(origLines.asJava, newLines.asJava) + if (diff.getDeltas.isEmpty) "" + else difflib.DiffUtils.generateUnifiedDiff(origName, newName, origLines.asJava, diff, 1).asScala.mkString("\n") } } object FileUtil extends FileUtil { } diff --git a/src/partest/scala/tools/partest/nest/PathSettings.scala b/src/partest/scala/tools/partest/nest/PathSettings.scala index a42c2219b1..0ba34777a0 100644 --- a/src/partest/scala/tools/partest/nest/PathSettings.scala +++ b/src/partest/scala/tools/partest/nest/PathSettings.scala @@ -72,6 +72,9 @@ object PathSettings { findJar(buildPackLibDir.files ++ srcLibDir.files, "scalacheck") getOrElse { sys.error("No scalacheck jar found in '%s' or '%s'".format(buildPackLibDir, srcLibDir)) } + + lazy val diffUtils: File = + findJar(buildPackLibDir.files, "diffutils") getOrElse sys.error(s"No diffutils.jar found in '$buildPackLibDir'.") } class PathSettings() { diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala index 5cb8589d66..700667afcf 100644 --- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala +++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala @@ -53,13 +53,14 @@ class ReflectiveRunner { Array(latestCompFile, latestReflectFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile) map (x => io.File(x)) val sepUrls = files map (_.toURL) + // this seems to be the core classloader that determines which classes can be found when running partest from the test/partest script var sepLoader = new URLClassLoader(sepUrls, null) // this is a workaround for https://issues.scala-lang.org/browse/SI-5433 - // when that bug is fixed, this paragraph of code can be safely removed // we hack into the classloader that will become parent classloader for scalac // this way we ensure that reflective macro lookup will pick correct Code.lift - sepLoader = new URLClassLoader((PathSettings.srcCodeLib +: files) map (_.toURL), null) + // it's also used to inject diffutils into the classpath when running partest from the test/partest script + sepLoader = new URLClassLoader((PathSettings.srcCodeLib +: (PathSettings.diffUtils +: files)) map (_.toURL), null) if (isPartestDebug) println("Loading classes from:\n" + sepUrls.mkString("\n")) diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala index 0d979d2692..f80f6f38fd 100644 --- a/src/partest/scala/tools/partest/nest/RunnerManager.scala +++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala @@ -79,6 +79,7 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP val compileMgr = new CompileManager(fileManager) fileManager.CLASSPATH += File.pathSeparator + PathSettings.scalaCheck + fileManager.CLASSPATH += File.pathSeparator + PathSettings.diffUtils // needed to put diffutils on test/partest's classpath private def compareFiles(f1: File, f2: File): String = try fileManager.compareFiles(f1, f2) diff --git a/test/files/run/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check index f2f0b60687..50a9d87557 100644 --- a/test/files/run/inline-ex-handlers.check +++ b/test/files/run/inline-ex-handlers.check @@ -1,425 +1,490 @@ -172c172 -< locals: value x$1, value x1 ---- -> locals: value x$1, value x1, variable boxed1 -174c174 -< blocks: [1,2,3,4] ---- -> blocks: [1,3,4] -186a187,188 -> 92 STORE_LOCAL(variable boxed1) -> 92 LOAD_LOCAL(variable boxed1) -195,197d196 -< 92 JUMP 2 -< -< 2: -247c246 -< blocks: [1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18] ---- -> blocks: [1,2,3,4,5,6,8,10,11,12,13,14,15,16,17,18] -258,260d256 -< 92 JUMP 7 -< -< 7: -391c387 -< locals: value args, variable result, value ex6, value x4, value x5, value message, value x ---- -> locals: value args, variable result, value ex6, value x4, value x5, value x -393c389 -< blocks: [1,2,3,4,5,8,10,11,13] ---- -> blocks: [1,2,3,5,8,10,11,13,14] -417c413,422 -< 103 THROW(MyException) ---- -> ? STORE_LOCAL(value ex6) -> ? JUMP 14 -> -> 14: -> 101 LOAD_LOCAL(value ex6) -> 101 STORE_LOCAL(value x4) -> 101 SCOPE_ENTER value x4 -> 106 LOAD_LOCAL(value x4) -> 106 IS_INSTANCE REF(class MyException) -> 106 CZJUMP (BOOL)NE ? 5 : 8 -430,432d434 -< 101 JUMP 4 -< -< 4: -442,445d443 -< 106 LOAD_LOCAL(value x5) -< 106 CALL_METHOD MyException.message (dynamic) -< 106 STORE_LOCAL(value message) -< 106 SCOPE_ENTER value message -447c445,446 -< 106 LOAD_LOCAL(value message) ---- -> ? LOAD_LOCAL(value x5) -> 106 CALL_METHOD MyException.message (dynamic) -519c518 -< blocks: [1,2,3,4,6,7,8,9,10] ---- -> blocks: [1,2,3,4,6,7,8,9,10,11,12,13] -548c547 -< 306 THROW(MyException) ---- -> ? JUMP 11 -549a549,553 -> 11: -> ? LOAD_LOCAL(variable monitor4) -> 305 MONITOR_EXIT -> ? JUMP 12 -> -554c558 -< ? THROW(Throwable) ---- -> ? JUMP 12 -560c564,571 -< ? THROW(Throwable) ---- -> ? STORE_LOCAL(value t) -> ? JUMP 13 -> -> 12: -> ? LOAD_LOCAL(variable monitor3) -> 304 MONITOR_EXIT -> ? STORE_LOCAL(value t) -> ? JUMP 13 -575a587,598 -> 13: -> 310 LOAD_MODULE object Predef -> 310 CALL_PRIMITIVE(StartConcat) -> 310 CONSTANT("Caught crash: ") -> 310 CALL_PRIMITIVE(StringConcat(REF(class String))) -> 310 LOAD_LOCAL(value t) -> 310 CALL_METHOD java.lang.Throwable.toString (dynamic) -> 310 CALL_PRIMITIVE(StringConcat(REF(class String))) -> 310 CALL_PRIMITIVE(EndConcat) -> 310 CALL_METHOD scala.Predef.println (dynamic) -> 310 JUMP 2 -> -584c607 -< catch (Throwable) in ArrayBuffer(7, 8, 9, 10) starting at: 6 ---- -> catch (Throwable) in ArrayBuffer(7, 8, 9, 10, 11) starting at: 6 -587c610 -< catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10) starting at: 3 ---- -> catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10, 11, 12) starting at: 3 -619c642 -< blocks: [1,2,3,4,5,6,7,9,10] ---- -> blocks: [1,2,3,4,5,6,7,9,10,11,12] -643c666,667 -< 78 THROW(IllegalArgumentException) ---- -> ? STORE_LOCAL(value e) -> ? JUMP 11 -644a669,673 -> 11: -> 81 LOAD_LOCAL(value e) -> ? STORE_LOCAL(variable exc1) -> ? JUMP 12 -> -672c701,702 -< 81 THROW(Exception) ---- -> ? STORE_LOCAL(variable exc1) -> ? JUMP 12 -688a719,731 -> 12: -> 83 LOAD_MODULE object Predef -> 83 CONSTANT("finally") -> 83 CALL_METHOD scala.Predef.println (dynamic) -> 84 LOAD_LOCAL(variable result) -> 84 CONSTANT(1) -> 84 CALL_PRIMITIVE(Arithmetic(SUB,INT)) -> 84 CONSTANT(2) -> 84 CALL_PRIMITIVE(Arithmetic(DIV,INT)) -> 84 STORE_LOCAL(variable result) -> 84 LOAD_LOCAL(variable exc1) -> 84 THROW(Throwable) -> -694c737 -< catch (<none>) in ArrayBuffer(4, 6, 7, 9) starting at: 3 ---- -> catch (<none>) in ArrayBuffer(4, 6, 7, 9, 11) starting at: 3 -718c761 -< locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value message, value x, value ex6, value x4, value x5, value message, value x ---- -> locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value x, value ex6, value x4, value x5, value x -720c763 -< blocks: [1,2,3,4,5,6,9,11,14,15,16,19,21,22,24,25] ---- -> blocks: [1,2,3,4,5,6,9,11,14,15,16,19,21,22,24,25,26,27,28] -744c787,794 -< 172 THROW(MyException) ---- -> ? STORE_LOCAL(value ex6) -> ? JUMP 26 -> -> 26: -> 170 LOAD_LOCAL(value ex6) -> 170 STORE_LOCAL(value x4) -> 170 SCOPE_ENTER value x4 -> 170 JUMP 15 -787,790d836 -< 175 LOAD_LOCAL(value x5) -< 175 CALL_METHOD MyException.message (dynamic) -< 175 STORE_LOCAL(value message) -< 175 SCOPE_ENTER value message -792c838,839 -< 176 LOAD_LOCAL(value message) ---- -> ? LOAD_LOCAL(value x5) -> 176 CALL_METHOD MyException.message (dynamic) -796c843,844 -< 177 LOAD_LOCAL(value message) ---- -> ? LOAD_LOCAL(value x5) -> 177 CALL_METHOD MyException.message (dynamic) -798c846,847 -< 177 THROW(MyException) ---- -> ? STORE_LOCAL(value ex6) -> ? JUMP 27 -802c851,852 -< 170 THROW(Throwable) ---- -> ? STORE_LOCAL(value ex6) -> ? JUMP 27 -811a862,867 -> 27: -> 169 LOAD_LOCAL(value ex6) -> 169 STORE_LOCAL(value x4) -> 169 SCOPE_ENTER value x4 -> 169 JUMP 5 -> -822,825d877 -< 180 LOAD_LOCAL(value x5) -< 180 CALL_METHOD MyException.message (dynamic) -< 180 STORE_LOCAL(value message) -< 180 SCOPE_ENTER value message -827c879,880 -< 181 LOAD_LOCAL(value message) ---- -> ? LOAD_LOCAL(value x5) -> 181 CALL_METHOD MyException.message (dynamic) -831c884,885 -< 182 LOAD_LOCAL(value message) ---- -> ? LOAD_LOCAL(value x5) -> 182 CALL_METHOD MyException.message (dynamic) -833c887,888 -< 182 THROW(MyException) ---- -> ? STORE_LOCAL(variable exc2) -> ? JUMP 28 -837c892,893 -< 169 THROW(Throwable) ---- -> ? STORE_LOCAL(variable exc2) -> ? JUMP 28 -853a910,922 -> 28: -> 184 LOAD_MODULE object Predef -> 184 CONSTANT("finally") -> 184 CALL_METHOD scala.Predef.println (dynamic) -> 185 LOAD_LOCAL(variable result) -> 185 CONSTANT(1) -> 185 CALL_PRIMITIVE(Arithmetic(SUB,INT)) -> 185 CONSTANT(2) -> 185 CALL_PRIMITIVE(Arithmetic(DIV,INT)) -> 185 STORE_LOCAL(variable result) -> 185 LOAD_LOCAL(variable exc2) -> 185 THROW(Throwable) -> -859c928 -< catch (Throwable) in ArrayBuffer(14, 15, 16, 19, 21, 22, 24) starting at: 4 ---- -> catch (Throwable) in ArrayBuffer(14, 15, 16, 19, 21, 22, 24, 26) starting at: 4 -862c931 -< catch (<none>) in ArrayBuffer(4, 5, 6, 9, 14, 15, 16, 19, 21, 22, 24) starting at: 3 ---- -> catch (<none>) in ArrayBuffer(4, 5, 6, 9, 14, 15, 16, 19, 21, 22, 24, 26, 27) starting at: 3 -886c955 -< locals: value args, variable result, value e, value ex6, value x4, value x5, value message, value x ---- -> locals: value args, variable result, value e, value ex6, value x4, value x5, value x -888c957 -< blocks: [1,2,3,6,7,8,11,13,14,16] ---- -> blocks: [1,2,3,6,7,8,11,13,14,16,17] -912c981,988 -< 124 THROW(MyException) ---- -> ? STORE_LOCAL(value ex6) -> ? JUMP 17 -> -> 17: -> 122 LOAD_LOCAL(value ex6) -> 122 STORE_LOCAL(value x4) -> 122 SCOPE_ENTER value x4 -> 122 JUMP 7 -937,940d1012 -< 127 LOAD_LOCAL(value x5) -< 127 CALL_METHOD MyException.message (dynamic) -< 127 STORE_LOCAL(value message) -< 127 SCOPE_ENTER value message -942c1014,1015 -< 127 LOAD_LOCAL(value message) ---- -> ? LOAD_LOCAL(value x5) -> 127 CALL_METHOD MyException.message (dynamic) -971c1044 -< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16) starting at: 3 ---- -> catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16, 17) starting at: 3 -995c1068 -< locals: value args, variable result, value ex6, value x4, value x5, value message, value x, value e ---- -> locals: value args, variable result, value ex6, value x4, value x5, value x, value e -997c1070 -< blocks: [1,2,3,4,5,8,12,13,14,16] ---- -> blocks: [1,2,3,5,8,12,13,14,16,17] -1021c1094,1103 -< 148 THROW(MyException) ---- -> ? STORE_LOCAL(value ex6) -> ? JUMP 17 -> -> 17: -> 145 LOAD_LOCAL(value ex6) -> 145 STORE_LOCAL(value x4) -> 145 SCOPE_ENTER value x4 -> 154 LOAD_LOCAL(value x4) -> 154 IS_INSTANCE REF(class MyException) -> 154 CZJUMP (BOOL)NE ? 5 : 8 -1042,1044d1123 -< 145 JUMP 4 -< -< 4: -1054,1057d1132 -< 154 LOAD_LOCAL(value x5) -< 154 CALL_METHOD MyException.message (dynamic) -< 154 STORE_LOCAL(value message) -< 154 SCOPE_ENTER value message -1059c1134,1135 -< 154 LOAD_LOCAL(value message) ---- -> ? LOAD_LOCAL(value x5) -> 154 CALL_METHOD MyException.message (dynamic) -1276c1352 -< blocks: [1,2,3,4,5,7] ---- -> blocks: [1,2,3,4,5,7,8] -1300c1376,1383 -< 38 THROW(IllegalArgumentException) ---- -> ? STORE_LOCAL(value e) -> ? JUMP 8 -> -> 8: -> 42 LOAD_MODULE object Predef -> 42 CONSTANT("IllegalArgumentException") -> 42 CALL_METHOD scala.Predef.println (dynamic) -> 42 JUMP 2 -1347c1430 -< locals: value args, variable result, value ex6, value x4, value x5, value message, value x ---- -> locals: value args, variable result, value ex6, value x4, value x5, value x -1349c1432 -< blocks: [1,2,3,4,5,8,10,11,13,14,16] ---- -> blocks: [1,2,3,5,8,10,11,13,14,16,17] -1373c1456,1457 -< 203 THROW(MyException) ---- -> ? STORE_LOCAL(value ex6) -> ? JUMP 17 -1393c1477,1486 -< 209 THROW(MyException) ---- -> ? STORE_LOCAL(value ex6) -> ? JUMP 17 -> -> 17: -> 200 LOAD_LOCAL(value ex6) -> 200 STORE_LOCAL(value x4) -> 200 SCOPE_ENTER value x4 -> 212 LOAD_LOCAL(value x4) -> 212 IS_INSTANCE REF(class MyException) -> 212 CZJUMP (BOOL)NE ? 5 : 8 -1406,1408d1498 -< 200 JUMP 4 -< -< 4: -1418,1421d1507 -< 212 LOAD_LOCAL(value x5) -< 212 CALL_METHOD MyException.message (dynamic) -< 212 STORE_LOCAL(value message) -< 212 SCOPE_ENTER value message -1423c1509,1510 -< 213 LOAD_LOCAL(value message) ---- -> ? LOAD_LOCAL(value x5) -> 213 CALL_METHOD MyException.message (dynamic) -1467c1554 -< blocks: [1,2,3,4,5,7] ---- -> blocks: [1,2,3,4,5,7,8] -1491c1578,1579 -< 58 THROW(IllegalArgumentException) ---- -> ? STORE_LOCAL(value e) -> ? JUMP 8 -1492a1581,1586 -> 8: -> 62 LOAD_MODULE object Predef -> 62 CONSTANT("RuntimeException") -> 62 CALL_METHOD scala.Predef.println (dynamic) -> 62 JUMP 2 -> -1540c1634 -< blocks: [1,2,3,4] ---- -> blocks: [1,2,3,4,5] -1560c1654,1659 -< 229 THROW(MyException) ---- -> ? JUMP 5 -> -> 5: -> ? LOAD_LOCAL(variable monitor1) -> 228 MONITOR_EXIT -> 228 THROW(Throwable) -1566c1665 -< ? THROW(Throwable) ---- -> 228 THROW(Throwable) -1594c1693 -< locals: value args, variable result, variable monitor2, variable monitorResult1 ---- -> locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1 -1596c1695 -< blocks: [1,2,3,4] ---- -> blocks: [1,2,3,4,5] -1619c1718,1726 -< 245 THROW(MyException) ---- -> ? STORE_LOCAL(value exception$1) -> ? DROP ConcatClass -> ? LOAD_LOCAL(value exception$1) -> ? JUMP 5 -> -> 5: -> ? LOAD_LOCAL(variable monitor2) -> 244 MONITOR_EXIT -> 244 THROW(Throwable) -1625c1732 -< ? THROW(Throwable) ---- -> 244 THROW(Throwable) - +--- a ++++ b +@@ -171,5 +171,5 @@ + def productElement(x$1: Int (INT)): Object { +- locals: value x$1, value x1 ++ locals: value x$1, value x1, variable boxed1 + startBlock: 1 +- blocks: [1,2,3,4] ++ blocks: [1,3,4] + +@@ -186,2 +186,4 @@ + 92 LOAD_LOCAL(value x$1) ++ 92 STORE_LOCAL(variable boxed1) ++ 92 LOAD_LOCAL(variable boxed1) + 92 BOX INT +@@ -194,5 +196,2 @@ + 92 CALL_METHOD MyException.message (dynamic) +- 92 JUMP 2 +- +- 2: + 92 RETURN(REF(class Object)) +@@ -246,3 +245,3 @@ + startBlock: 1 +- blocks: [1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18] ++ blocks: [1,2,3,4,5,6,8,10,11,12,13,14,15,16,17,18] + +@@ -257,5 +256,2 @@ + 92 SCOPE_ENTER value x1 +- 92 JUMP 7 +- +- 7: + 92 LOAD_LOCAL(value x1) +@@ -390,5 +386,5 @@ + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { +- locals: value args, variable result, value ex6, value x4, value x5, value message, value x ++ locals: value args, variable result, value ex6, value x4, value x5, value x + startBlock: 1 +- blocks: [1,2,3,4,5,8,10,11,13] ++ blocks: [1,2,3,5,8,10,11,13,14] + +@@ -416,4 +412,13 @@ + 103 CALL_METHOD MyException.<init> (static-instance) +- 103 THROW(MyException) ++ ? STORE_LOCAL(value ex6) ++ ? JUMP 14 + ++ 14: ++ 101 LOAD_LOCAL(value ex6) ++ 101 STORE_LOCAL(value x4) ++ 101 SCOPE_ENTER value x4 ++ 106 LOAD_LOCAL(value x4) ++ 106 IS_INSTANCE REF(class MyException) ++ 106 CZJUMP (BOOL)NE ? 5 : 8 ++ + 13: +@@ -429,5 +434,2 @@ + 101 SCOPE_ENTER value x4 +- 101 JUMP 4 +- +- 4: + 106 LOAD_LOCAL(value x4) +@@ -441,8 +443,5 @@ + 106 SCOPE_ENTER value x5 +- 106 LOAD_LOCAL(value x5) +- 106 CALL_METHOD MyException.message (dynamic) +- 106 STORE_LOCAL(value message) +- 106 SCOPE_ENTER value message + 106 LOAD_MODULE object Predef +- 106 LOAD_LOCAL(value message) ++ ? LOAD_LOCAL(value x5) ++ 106 CALL_METHOD MyException.message (dynamic) + 106 CALL_METHOD scala.Predef.println (dynamic) +@@ -518,3 +517,3 @@ + startBlock: 1 +- blocks: [1,2,3,4,6,7,8,9,10] ++ blocks: [1,2,3,4,6,7,8,9,10,11,12,13] + +@@ -547,4 +546,9 @@ + 306 CALL_METHOD MyException.<init> (static-instance) +- 306 THROW(MyException) ++ ? JUMP 11 + ++ 11: ++ ? LOAD_LOCAL(variable monitor4) ++ 305 MONITOR_EXIT ++ ? JUMP 12 ++ + 9: +@@ -553,3 +557,3 @@ + 305 MONITOR_EXIT +- ? THROW(Throwable) ++ ? JUMP 12 + +@@ -559,4 +563,11 @@ + 304 MONITOR_EXIT +- ? THROW(Throwable) ++ ? STORE_LOCAL(value t) ++ ? JUMP 13 + ++ 12: ++ ? LOAD_LOCAL(variable monitor3) ++ 304 MONITOR_EXIT ++ ? STORE_LOCAL(value t) ++ ? JUMP 13 ++ + 3: +@@ -575,2 +586,14 @@ + ++ 13: ++ 310 LOAD_MODULE object Predef ++ 310 CALL_PRIMITIVE(StartConcat) ++ 310 CONSTANT("Caught crash: ") ++ 310 CALL_PRIMITIVE(StringConcat(REF(class String))) ++ 310 LOAD_LOCAL(value t) ++ 310 CALL_METHOD java.lang.Throwable.toString (dynamic) ++ 310 CALL_PRIMITIVE(StringConcat(REF(class String))) ++ 310 CALL_PRIMITIVE(EndConcat) ++ 310 CALL_METHOD scala.Predef.println (dynamic) ++ 310 JUMP 2 ++ + 2: +@@ -583,6 +606,6 @@ + with finalizer: null +- catch (Throwable) in ArrayBuffer(7, 8, 9, 10) starting at: 6 ++ catch (Throwable) in ArrayBuffer(7, 8, 9, 10, 11) starting at: 6 + consisting of blocks: List(6) + with finalizer: null +- catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10) starting at: 3 ++ catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10, 11, 12) starting at: 3 + consisting of blocks: List(3) +@@ -618,3 +641,3 @@ + startBlock: 1 +- blocks: [1,2,3,4,5,6,7,9,10] ++ blocks: [1,2,3,4,5,6,7,9,10,11,12] + +@@ -642,4 +665,10 @@ + 78 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance) +- 78 THROW(IllegalArgumentException) ++ ? STORE_LOCAL(value e) ++ ? JUMP 11 + ++ 11: ++ 81 LOAD_LOCAL(value e) ++ ? STORE_LOCAL(variable exc1) ++ ? JUMP 12 ++ + 9: +@@ -671,3 +700,4 @@ + 81 LOAD_LOCAL(value e) +- 81 THROW(Exception) ++ ? STORE_LOCAL(variable exc1) ++ ? JUMP 12 + +@@ -688,2 +718,15 @@ + ++ 12: ++ 83 LOAD_MODULE object Predef ++ 83 CONSTANT("finally") ++ 83 CALL_METHOD scala.Predef.println (dynamic) ++ 84 LOAD_LOCAL(variable result) ++ 84 CONSTANT(1) ++ 84 CALL_PRIMITIVE(Arithmetic(SUB,INT)) ++ 84 CONSTANT(2) ++ 84 CALL_PRIMITIVE(Arithmetic(DIV,INT)) ++ 84 STORE_LOCAL(variable result) ++ 84 LOAD_LOCAL(variable exc1) ++ 84 THROW(Throwable) ++ + } +@@ -693,3 +736,3 @@ + with finalizer: null +- catch (<none>) in ArrayBuffer(4, 6, 7, 9) starting at: 3 ++ catch (<none>) in ArrayBuffer(4, 6, 7, 9, 11) starting at: 3 + consisting of blocks: List(3) +@@ -717,5 +760,5 @@ + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { +- locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value message, value x, value ex6, value x4, value x5, value message, value x ++ locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value x, value ex6, value x4, value x5, value x + startBlock: 1 +- blocks: [1,2,3,4,5,6,9,11,14,15,16,19,21,22,24,25] ++ blocks: [1,2,3,4,5,6,9,11,14,15,16,19,21,22,24,25,26,27,28] + +@@ -743,4 +786,11 @@ + 172 CALL_METHOD MyException.<init> (static-instance) +- 172 THROW(MyException) ++ ? STORE_LOCAL(value ex6) ++ ? JUMP 26 + ++ 26: ++ 170 LOAD_LOCAL(value ex6) ++ 170 STORE_LOCAL(value x4) ++ 170 SCOPE_ENTER value x4 ++ 170 JUMP 15 ++ + 24: +@@ -786,8 +836,5 @@ + 175 SCOPE_ENTER value x5 +- 175 LOAD_LOCAL(value x5) +- 175 CALL_METHOD MyException.message (dynamic) +- 175 STORE_LOCAL(value message) +- 175 SCOPE_ENTER value message + 176 LOAD_MODULE object Predef +- 176 LOAD_LOCAL(value message) ++ ? LOAD_LOCAL(value x5) ++ 176 CALL_METHOD MyException.message (dynamic) + 176 CALL_METHOD scala.Predef.println (dynamic) +@@ -795,5 +842,7 @@ + 177 DUP(REF(class MyException)) +- 177 LOAD_LOCAL(value message) ++ ? LOAD_LOCAL(value x5) ++ 177 CALL_METHOD MyException.message (dynamic) + 177 CALL_METHOD MyException.<init> (static-instance) +- 177 THROW(MyException) ++ ? STORE_LOCAL(value ex6) ++ ? JUMP 27 + +@@ -801,3 +850,4 @@ + 170 LOAD_LOCAL(value ex6) +- 170 THROW(Throwable) ++ ? STORE_LOCAL(value ex6) ++ ? JUMP 27 + +@@ -811,2 +861,8 @@ + ++ 27: ++ 169 LOAD_LOCAL(value ex6) ++ 169 STORE_LOCAL(value x4) ++ 169 SCOPE_ENTER value x4 ++ 169 JUMP 5 ++ + 5: +@@ -821,8 +877,5 @@ + 180 SCOPE_ENTER value x5 +- 180 LOAD_LOCAL(value x5) +- 180 CALL_METHOD MyException.message (dynamic) +- 180 STORE_LOCAL(value message) +- 180 SCOPE_ENTER value message + 181 LOAD_MODULE object Predef +- 181 LOAD_LOCAL(value message) ++ ? LOAD_LOCAL(value x5) ++ 181 CALL_METHOD MyException.message (dynamic) + 181 CALL_METHOD scala.Predef.println (dynamic) +@@ -830,5 +883,7 @@ + 182 DUP(REF(class MyException)) +- 182 LOAD_LOCAL(value message) ++ ? LOAD_LOCAL(value x5) ++ 182 CALL_METHOD MyException.message (dynamic) + 182 CALL_METHOD MyException.<init> (static-instance) +- 182 THROW(MyException) ++ ? STORE_LOCAL(variable exc2) ++ ? JUMP 28 + +@@ -836,3 +891,4 @@ + 169 LOAD_LOCAL(value ex6) +- 169 THROW(Throwable) ++ ? STORE_LOCAL(variable exc2) ++ ? JUMP 28 + +@@ -853,2 +909,15 @@ + ++ 28: ++ 184 LOAD_MODULE object Predef ++ 184 CONSTANT("finally") ++ 184 CALL_METHOD scala.Predef.println (dynamic) ++ 185 LOAD_LOCAL(variable result) ++ 185 CONSTANT(1) ++ 185 CALL_PRIMITIVE(Arithmetic(SUB,INT)) ++ 185 CONSTANT(2) ++ 185 CALL_PRIMITIVE(Arithmetic(DIV,INT)) ++ 185 STORE_LOCAL(variable result) ++ 185 LOAD_LOCAL(variable exc2) ++ 185 THROW(Throwable) ++ + } +@@ -858,6 +927,6 @@ + with finalizer: null +- catch (Throwable) in ArrayBuffer(14, 15, 16, 19, 21, 22, 24) starting at: 4 ++ catch (Throwable) in ArrayBuffer(14, 15, 16, 19, 21, 22, 24, 26) starting at: 4 + consisting of blocks: List(9, 6, 5, 4) + with finalizer: null +- catch (<none>) in ArrayBuffer(4, 5, 6, 9, 14, 15, 16, 19, 21, 22, 24) starting at: 3 ++ catch (<none>) in ArrayBuffer(4, 5, 6, 9, 14, 15, 16, 19, 21, 22, 24, 26, 27) starting at: 3 + consisting of blocks: List(3) +@@ -885,5 +954,5 @@ + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { +- locals: value args, variable result, value e, value ex6, value x4, value x5, value message, value x ++ locals: value args, variable result, value e, value ex6, value x4, value x5, value x + startBlock: 1 +- blocks: [1,2,3,6,7,8,11,13,14,16] ++ blocks: [1,2,3,6,7,8,11,13,14,16,17] + +@@ -911,4 +980,11 @@ + 124 CALL_METHOD MyException.<init> (static-instance) +- 124 THROW(MyException) ++ ? STORE_LOCAL(value ex6) ++ ? JUMP 17 + ++ 17: ++ 122 LOAD_LOCAL(value ex6) ++ 122 STORE_LOCAL(value x4) ++ 122 SCOPE_ENTER value x4 ++ 122 JUMP 7 ++ + 16: +@@ -936,8 +1012,5 @@ + 127 SCOPE_ENTER value x5 +- 127 LOAD_LOCAL(value x5) +- 127 CALL_METHOD MyException.message (dynamic) +- 127 STORE_LOCAL(value message) +- 127 SCOPE_ENTER value message + 127 LOAD_MODULE object Predef +- 127 LOAD_LOCAL(value message) ++ ? LOAD_LOCAL(value x5) ++ 127 CALL_METHOD MyException.message (dynamic) + 127 CALL_METHOD scala.Predef.println (dynamic) +@@ -970,3 +1043,3 @@ + with finalizer: null +- catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16) starting at: 3 ++ catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16, 17) starting at: 3 + consisting of blocks: List(3) +@@ -994,5 +1067,5 @@ + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { +- locals: value args, variable result, value ex6, value x4, value x5, value message, value x, value e ++ locals: value args, variable result, value ex6, value x4, value x5, value x, value e + startBlock: 1 +- blocks: [1,2,3,4,5,8,12,13,14,16] ++ blocks: [1,2,3,5,8,12,13,14,16,17] + +@@ -1020,4 +1093,13 @@ + 148 CALL_METHOD MyException.<init> (static-instance) +- 148 THROW(MyException) ++ ? STORE_LOCAL(value ex6) ++ ? JUMP 17 + ++ 17: ++ 145 LOAD_LOCAL(value ex6) ++ 145 STORE_LOCAL(value x4) ++ 145 SCOPE_ENTER value x4 ++ 154 LOAD_LOCAL(value x4) ++ 154 IS_INSTANCE REF(class MyException) ++ 154 CZJUMP (BOOL)NE ? 5 : 8 ++ + 16: +@@ -1041,5 +1123,2 @@ + 145 SCOPE_ENTER value x4 +- 145 JUMP 4 +- +- 4: + 154 LOAD_LOCAL(value x4) +@@ -1053,8 +1132,5 @@ + 154 SCOPE_ENTER value x5 +- 154 LOAD_LOCAL(value x5) +- 154 CALL_METHOD MyException.message (dynamic) +- 154 STORE_LOCAL(value message) +- 154 SCOPE_ENTER value message + 154 LOAD_MODULE object Predef +- 154 LOAD_LOCAL(value message) ++ ? LOAD_LOCAL(value x5) ++ 154 CALL_METHOD MyException.message (dynamic) + 154 CALL_METHOD scala.Predef.println (dynamic) +@@ -1275,3 +1351,3 @@ + startBlock: 1 +- blocks: [1,2,3,4,5,7] ++ blocks: [1,2,3,4,5,7,8] + +@@ -1299,4 +1375,11 @@ + 38 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance) +- 38 THROW(IllegalArgumentException) ++ ? STORE_LOCAL(value e) ++ ? JUMP 8 + ++ 8: ++ 42 LOAD_MODULE object Predef ++ 42 CONSTANT("IllegalArgumentException") ++ 42 CALL_METHOD scala.Predef.println (dynamic) ++ 42 JUMP 2 ++ + 7: +@@ -1346,5 +1429,5 @@ + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { +- locals: value args, variable result, value ex6, value x4, value x5, value message, value x ++ locals: value args, variable result, value ex6, value x4, value x5, value x + startBlock: 1 +- blocks: [1,2,3,4,5,8,10,11,13,14,16] ++ blocks: [1,2,3,5,8,10,11,13,14,16,17] + +@@ -1372,3 +1455,4 @@ + 203 CALL_METHOD MyException.<init> (static-instance) +- 203 THROW(MyException) ++ ? STORE_LOCAL(value ex6) ++ ? JUMP 17 + +@@ -1392,4 +1476,13 @@ + 209 CALL_METHOD MyException.<init> (static-instance) +- 209 THROW(MyException) ++ ? STORE_LOCAL(value ex6) ++ ? JUMP 17 + ++ 17: ++ 200 LOAD_LOCAL(value ex6) ++ 200 STORE_LOCAL(value x4) ++ 200 SCOPE_ENTER value x4 ++ 212 LOAD_LOCAL(value x4) ++ 212 IS_INSTANCE REF(class MyException) ++ 212 CZJUMP (BOOL)NE ? 5 : 8 ++ + 16: +@@ -1405,5 +1498,2 @@ + 200 SCOPE_ENTER value x4 +- 200 JUMP 4 +- +- 4: + 212 LOAD_LOCAL(value x4) +@@ -1417,8 +1507,5 @@ + 212 SCOPE_ENTER value x5 +- 212 LOAD_LOCAL(value x5) +- 212 CALL_METHOD MyException.message (dynamic) +- 212 STORE_LOCAL(value message) +- 212 SCOPE_ENTER value message + 213 LOAD_MODULE object Predef +- 213 LOAD_LOCAL(value message) ++ ? LOAD_LOCAL(value x5) ++ 213 CALL_METHOD MyException.message (dynamic) + 213 CALL_METHOD scala.Predef.println (dynamic) +@@ -1466,3 +1553,3 @@ + startBlock: 1 +- blocks: [1,2,3,4,5,7] ++ blocks: [1,2,3,4,5,7,8] + +@@ -1490,4 +1577,11 @@ + 58 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance) +- 58 THROW(IllegalArgumentException) ++ ? STORE_LOCAL(value e) ++ ? JUMP 8 + ++ 8: ++ 62 LOAD_MODULE object Predef ++ 62 CONSTANT("RuntimeException") ++ 62 CALL_METHOD scala.Predef.println (dynamic) ++ 62 JUMP 2 ++ + 7: +@@ -1539,3 +1633,3 @@ + startBlock: 1 +- blocks: [1,2,3,4] ++ blocks: [1,2,3,4,5] + +@@ -1559,4 +1653,9 @@ + 229 CALL_METHOD MyException.<init> (static-instance) +- 229 THROW(MyException) ++ ? JUMP 5 + ++ 5: ++ ? LOAD_LOCAL(variable monitor1) ++ 228 MONITOR_EXIT ++ 228 THROW(Throwable) ++ + 3: +@@ -1565,3 +1664,3 @@ + 228 MONITOR_EXIT +- ? THROW(Throwable) ++ 228 THROW(Throwable) + +@@ -1593,5 +1692,5 @@ + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { +- locals: value args, variable result, variable monitor2, variable monitorResult1 ++ locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1 + startBlock: 1 +- blocks: [1,2,3,4] ++ blocks: [1,2,3,4,5] + +@@ -1618,4 +1717,12 @@ + 245 CALL_METHOD MyException.<init> (static-instance) +- 245 THROW(MyException) ++ ? STORE_LOCAL(value exception$1) ++ ? DROP ConcatClass ++ ? LOAD_LOCAL(value exception$1) ++ ? JUMP 5 + ++ 5: ++ ? LOAD_LOCAL(variable monitor2) ++ 244 MONITOR_EXIT ++ 244 THROW(Throwable) ++ + 3: +@@ -1624,3 +1731,3 @@ + 244 MONITOR_EXIT +- ? THROW(Throwable) ++ 244 THROW(Throwable) + diff --git a/test/files/run/test-cpp.check b/test/files/run/test-cpp.check index bfea438c60..13f4c64be3 100644 --- a/test/files/run/test-cpp.check +++ b/test/files/run/test-cpp.check @@ -1,65 +1,81 @@ -37c37 -< locals: value args, value x, value y ---- -> locals: value args -42,43d41 -< 52 CONSTANT(2) -< 52 STORE_LOCAL(value x) -45,46d42 -< 53 LOAD_LOCAL(value x) -< 53 STORE_LOCAL(value y) -49c45 -< 54 LOAD_LOCAL(value y) ---- -> 54 CONSTANT(2) -92c88 -< locals: value args, value x, value y ---- -> locals: value args, value x -101,102d96 -< 82 LOAD_LOCAL(value x) -< 82 STORE_LOCAL(value y) -105c99 -< 83 LOAD_LOCAL(value y) ---- -> 83 LOAD_LOCAL(value x) -135c129 -< locals: value args, value x, value y ---- -> locals: value args -140,141d133 -< 66 THIS(TestAliasChainDerefThis) -< 66 STORE_LOCAL(value x) -143,144d134 -< 67 LOAD_LOCAL(value x) -< 67 STORE_LOCAL(value y) -147c137 -< 68 LOAD_LOCAL(value y) ---- -> 68 THIS(Object) -176c166 -< locals: value x, value y ---- -> locals: value x -181,182d170 -< 29 LOAD_LOCAL(value x) -< 29 STORE_LOCAL(value y) -185c173 -< 30 LOAD_LOCAL(value y) ---- -> 30 LOAD_LOCAL(value x) -223,224d210 -< 97 LOAD_LOCAL(variable x) -< 97 STORE_LOCAL(variable y) -227c213 -< 98 LOAD_LOCAL(variable y) ---- -> 98 LOAD_LOCAL(variable x) -233,234d218 -< 101 LOAD_LOCAL(variable y) -< 101 STORE_LOCAL(variable x) -236c220 -< 102 LOAD_LOCAL(variable x) ---- -> 102 LOAD_LOCAL(variable y) - +--- a ++++ b +@@ -36,3 +36,3 @@ + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { +- locals: value args, value x, value y ++ locals: value args + startBlock: 1 +@@ -41,10 +41,6 @@ + 1: +- 52 CONSTANT(2) +- 52 STORE_LOCAL(value x) + 52 SCOPE_ENTER value x +- 53 LOAD_LOCAL(value x) +- 53 STORE_LOCAL(value y) + 53 SCOPE_ENTER value y + 54 LOAD_MODULE object Predef +- 54 LOAD_LOCAL(value y) ++ 54 CONSTANT(2) + 54 BOX INT +@@ -91,3 +87,3 @@ + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { +- locals: value args, value x, value y ++ locals: value args, value x + startBlock: 1 +@@ -100,7 +96,5 @@ + 81 SCOPE_ENTER value x +- 82 LOAD_LOCAL(value x) +- 82 STORE_LOCAL(value y) + 82 SCOPE_ENTER value y + 83 LOAD_MODULE object Predef +- 83 LOAD_LOCAL(value y) ++ 83 LOAD_LOCAL(value x) + 83 BOX INT +@@ -134,3 +128,3 @@ + def main(args: Array[String] (ARRAY[REF(class String)])): Unit { +- locals: value args, value x, value y ++ locals: value args + startBlock: 1 +@@ -139,10 +133,6 @@ + 1: +- 66 THIS(TestAliasChainDerefThis) +- 66 STORE_LOCAL(value x) + 66 SCOPE_ENTER value x +- 67 LOAD_LOCAL(value x) +- 67 STORE_LOCAL(value y) + 67 SCOPE_ENTER value y + 68 LOAD_MODULE object Predef +- 68 LOAD_LOCAL(value y) ++ 68 THIS(Object) + 68 CALL_METHOD scala.Predef.println (dynamic) +@@ -175,3 +165,3 @@ + def test(x: Int (INT)): Unit { +- locals: value x, value y ++ locals: value x + startBlock: 1 +@@ -180,7 +170,5 @@ + 1: +- 29 LOAD_LOCAL(value x) +- 29 STORE_LOCAL(value y) + 29 SCOPE_ENTER value y + 30 LOAD_MODULE object Predef +- 30 LOAD_LOCAL(value y) ++ 30 LOAD_LOCAL(value x) + 30 BOX INT +@@ -222,7 +210,5 @@ + 96 SCOPE_ENTER variable x +- 97 LOAD_LOCAL(variable x) +- 97 STORE_LOCAL(variable y) + 97 SCOPE_ENTER variable y + 98 LOAD_MODULE object Predef +- 98 LOAD_LOCAL(variable y) ++ 98 LOAD_LOCAL(variable x) + 98 BOX INT +@@ -232,6 +218,4 @@ + 100 STORE_LOCAL(variable y) +- 101 LOAD_LOCAL(variable y) +- 101 STORE_LOCAL(variable x) + 102 LOAD_MODULE object Predef +- 102 LOAD_LOCAL(variable x) ++ 102 LOAD_LOCAL(variable y) + 102 BOX INT diff --git a/test/partest b/test/partest index dd57137b21..842d2903b7 100755 --- a/test/partest +++ b/test/partest @@ -53,8 +53,8 @@ if [ -z "$EXT_CLASSPATH" ] ; then fi done elif [ -f "$SCALA_HOME/build/pack/lib/scala-partest.jar" ] ; then - for lib in `echo "partest library reflect compiler"`; do - ext="$SCALA_HOME/build/pack/lib/scala-$lib.jar" + for lib in `echo "scala-partest scala-library scala-reflect scala-compiler diffutils"`; do + ext="$SCALA_HOME/build/pack/lib/$lib.jar" if [ -z "$EXT_CLASSPATH" ] ; then EXT_CLASSPATH="$ext" else |