merge all into single repo

This commit is contained in:
fixminer
2020-04-06 20:40:32 +02:00
parent 9dcdb6aafc
commit 3c91dd7ea3
524 changed files with 1272301 additions and 1531 deletions
+14
View File
@@ -0,0 +1,14 @@
target/
samples/
.settings/
.project
.classpath
.recommenders/
.metadata/
.idea/
*.iml
.DS_Store
OUTPUT/
Dataset/
logs/
gen.jdt/src/main/java/edu/lu/uni/serval/gumtree/GumTreeTester.java
+5
View File
@@ -0,0 +1,5 @@
language: java
jdk:
- oraclejdk8
after_success:
- mvn clean test jacoco:report coveralls:report
+165
View File
@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+40
View File
@@ -0,0 +1,40 @@
# GumTree ![Build Status](https://travis-ci.org/GumTreeDiff/gumtree.svg?branch=master) [![Coverage Status](https://coveralls.io/repos/GumTreeDiff/gumtree/badge.svg?branch=master)](https://coveralls.io/r/GumTreeDiff/gumtree?branch=master)
GumTree is a complete framework to deal with source code as trees and compute differences between them. It includes possibilities such as:
* converting a source file into a language-agnostic tree format
* export the produced trees in various formats
* compute the differences between the trees
* export these differences in various formats
* visualize these differences graphically
Compared to classical code differencing tools, it has two important particularities:
* it works on a tree structure rather than a text structure,
* it can detect moved or renamed elements in addition of deleted and inserted elements.
We already deal with a wide range of languages: Java, C, JavaScript and Ruby. More languages are coming soon, if you want to help contact [me](www.labri.fr/perso/falleri).
## Citing GumTree
We are researchers, therefore if you use GumTree in an academic work we would be really glad if you cite our seminal paper using the following bibtex:
```
@inproceedings{DBLP:conf/kbse/FalleriMBMM14,
author = {Jean{-}R{\'{e}}my Falleri and
Flor{\'{e}}al Morandat and
Xavier Blanc and
Matias Martinez and
Martin Monperrus},
title = {Fine-grained and accurate source code differencing},
booktitle = {{ACM/IEEE} International Conference on Automated Software Engineering,
{ASE} '14, Vasteras, Sweden - September 15 - 19, 2014},
pages = {313--324},
year = {2014},
url = {http://doi.acm.org/10.1145/2642937.2642982},
doi = {10.1145/2642937.2642982}
}
```
## Documentation
Please consult our [wiki](https://github.com/GumTreeDiff/gumtree/wiki)
+76
View File
@@ -0,0 +1,76 @@
plugins {
id 'me.champeau.gradle.jmh' version '0.2.0'
}
apply plugin: 'me.champeau.gradle.jmh'
uploadArchives.enabled = false
jar.enabled = false
task checkActions(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'com.github.gumtree.dist.ActionsCollector'
args 'check'
}
task collectActions(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'com.github.gumtree.dist.ActionsCollector'
args 'collect'
}
if (project.hasProperty('trees')) {
task collectTrees(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'com.github.gumtree.dist.BenchmarkCollector'
args trees
}
}
def getGitHash = { ->
try {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--dirty=+', '--tags'
standardOutput = stdout
}
return stdout.toString().trim()
} catch (all) {
return '0000000'
}
}
jmh {
fork = 0
warmupIterations = 3
iterations = 3
benchmarkMode = 'avgt'
benchmarkParameters = [
'refPath' : new File("${project.projectDir}/src/jmh/resources/").listFiles()
.collect { it.getAbsolutePath() }
.findAll { it.matches(".*_v0_.*") }
.join(",")
]
humanOutputFile = project.file("${project.buildDir}/reports/jmh/human_${new Date().getTime()}_${getGitHash()}.txt")
resultsFile = project.file("${project.buildDir}/reports/jmh/results_${new Date().getTime()}_${getGitHash()}.csv")
resultFormat = 'CSV'
}
task jmhPlot(type: Exec, dependsOn: 'jmh') {
commandLine "R", "-f", "${project.projectDir}/src/main/r/plotBenchmark.R", "${project.buildDir}/reports/jmh/"
}
dependencies {
compile project(':client')
compile project(':client.diff')
compile project(':gen.antlr3')
compile project(':gen.antlr3-antlr')
compile project(':gen.antlr3-json')
compile project(':gen.antlr3-php')
compile project(':gen.antlr3-r')
compile project(':gen.antlr3-xml')
compile project(':gen.c')
compile project(':gen.jdt')
compile project(':gen.js')
compile project(':gen.ruby')
}
@@ -0,0 +1,58 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2016 Jean-Rémy Falleri <jr.falleri@gmail.com>
*/
package com.github.gumtree.dist;
import com.github.gumtreediff.io.TreeIoUtils;
import com.github.gumtreediff.matchers.CompositeMatchers;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.tree.ITree;
import org.openjdk.jmh.annotations.*;
public class MatcherAnalyzer {
@State(Scope.Benchmark)
public static class TreeData {
@Setup
public void load() {
try {
String otherPath = refPath.replace("_v0_", "_v1_");
src = TreeIoUtils.fromXml().generateFromFile(refPath).getRoot();
dst = TreeIoUtils.fromXml().generateFromFile(otherPath).getRoot();
} catch (Exception e) {
e.printStackTrace();
}
}
@Param({})
public String refPath;
public ITree src;
public ITree dst;
}
@Benchmark
public void testClassicGumtree(TreeData d) {
Matcher m = new CompositeMatchers.ClassicGumtree(d.src, d.dst, new MappingStore());
m.match();
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,145 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2016 Jean-Rémy Falleri <jr.falleri@gmail.com>
*/
package com.github.gumtree.dist;
import com.github.gumtreediff.actions.ActionGenerator;
import com.github.gumtreediff.actions.model.Action;
import com.github.gumtreediff.client.Run;
import com.github.gumtreediff.gen.Generators;
import com.github.gumtreediff.io.ActionsIoUtils;
import com.github.gumtreediff.io.TreeIoUtils;
import com.github.gumtreediff.matchers.CompositeMatchers;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeContext;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
public class ActionsCollector {
private static final String OUTPUT_DIR = "build/tmp/actions/";
private static final String RES_DIR = "src/jmh/resources/";
private static final String REF_DIR = "src/main/resources/";
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Wrong number of arguments.");
System.exit(-1);
}
if (args[0].equals("collect"))
collectActions();
else if (args[0].equals("check"))
checkActions();
else {
System.err.println("Unknown argument: use collect or test.");
System.exit(-1);
}
}
public static void collectActions() throws Exception {
Run.initGenerators();
List<Path> paths = Files.walk(Paths.get(RES_DIR)).filter(
p -> p.getFileName().toString().matches(".*_v0_.*\\.xml")).collect(Collectors.toList());
Files.createDirectories(Paths.get(OUTPUT_DIR));
for (Path path : paths) {
Path otherPath = Paths.get(path.toString().replace("_v0_","_v1_"));
Path outputPath = Paths.get(path.toString().replace("_v0_","_actions_"));
TreeContext src = TreeIoUtils.fromXml().generateFromFile(path.toString());
TreeContext dst = TreeIoUtils.fromXml().generateFromFile(otherPath.toString());
CompositeMatchers.ClassicGumtree matcher = new CompositeMatchers.ClassicGumtree(
src.getRoot(), dst.getRoot(), new MappingStore());
matcher.match();
ActionGenerator g = new ActionGenerator(src.getRoot(), dst.getRoot(), matcher.getMappings());
List<Action> actions = g.generate();
String res = Paths.get(OUTPUT_DIR, outputPath.getFileName().toString()).toString();
ActionsIoUtils.toText(src, actions, matcher.getMappings()).writeTo(new FileWriter(res));
}
}
public static void checkActions() throws Exception {
Run.initGenerators();
List<Path> paths = Files.walk(Paths.get(RES_DIR)).filter(
p -> p.getFileName().toString().matches(".*_v0_.*\\.xml")).collect(Collectors.toList());
boolean dirty = false;
StringBuffer b = new StringBuffer();
for (Path path : paths) {
Path otherPath = Paths.get(path.toString().replace("_v0_","_v1_"));
TreeContext src = TreeIoUtils.fromXml().generateFromFile(path.toString());
TreeContext dst = TreeIoUtils.fromXml().generateFromFile(otherPath.toString());
CompositeMatchers.ClassicGumtree matcher = new CompositeMatchers.ClassicGumtree(
src.getRoot(), dst.getRoot(), new MappingStore());
matcher.match();
ActionGenerator g = new ActionGenerator(src.getRoot(), dst.getRoot(), matcher.getMappings());
List<Action> actions = g.generate();
StringWriter w = new StringWriter();
ActionsIoUtils.toText(src, actions, matcher.getMappings()).writeTo(w);
Path refPath = Paths.get(path.toString().replace("_v0_","_actions_"));
String ref = Paths.get(REF_DIR, refPath.getFileName().toString()).toString();
if (!contentEquals(new StringReader(w.toString()), new FileReader(ref))) {
dirty = true;
b.append(String.format("Content not equals for: %s. Now: %d Was: %d\n",
ref, countLines(new StringReader(w.toString())), countLines(new FileReader(ref))));
}
}
if (dirty) {
System.err.println(b.toString());
System.exit(-1);
}
}
public static boolean contentEquals(Reader cur, Reader ref) throws IOException {
try (Reader _cur = cur; Reader _ref = ref) {
int ch = _cur.read();
while (-1 != ch) {
int ch2 = _ref.read();
if (ch != ch2)
return false;
ch = _cur.read();
}
int ch2 = _ref.read();
return (ch2 == -1);
}
}
public static int countLines(Reader r) throws IOException {
try (Reader _r = r) {
char[] c = new char[1024];
int count = 0;
int readChars = 0;
boolean empty = true;
while ((readChars = _r.read(c)) != -1) {
empty = false;
for (int i = 0; i < readChars; ++i)
if (c[i] == '\n')
++count;
}
return (count == 0 && !empty) ? 1 : count;
}
}
}
@@ -0,0 +1,72 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2016 Jean-Rémy Falleri <jr.falleri@gmail.com>
*/
package com.github.gumtree.dist;
import com.github.gumtreediff.client.Run;
import com.github.gumtreediff.gen.Generators;
import com.github.gumtreediff.io.TreeIoUtils;
import com.github.gumtreediff.tree.TreeContext;
import java.io.File;
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.Collectors;
public class BenchmarkCollector {
private static final String OUTPUT_DIR = "build/tmp/trees/";
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Wrong number of arguments");
System.exit(-1);
}
collectTrees(args[0]);
}
public static void collectTrees(String dir) throws Exception {
Run.initGenerators();
List<Path> paths = Files.walk(Paths.get(dir)).filter(
p -> p.getFileName().toString().matches(".*_v0\\.(java|js|rb|c)")).collect(Collectors.toList());
Files.createDirectories(Paths.get(OUTPUT_DIR));
for (Path path : paths) {
Path otherPath = Paths.get(path.toString().replace("_v0.","_v1."));
String oldName = path.toString().replaceAll("[^a-zA-Z0-9_]", "_");
String newName = otherPath.toString().replaceAll("[^a-zA-Z0-9_]", "_");
TreeContext ctx = getTreeContext(path.toAbsolutePath().toString());
TreeIoUtils.toXml(ctx).writeTo(new File(OUTPUT_DIR + oldName + ".xml"));
ctx = getTreeContext(otherPath.toAbsolutePath().toString());
TreeIoUtils.toXml(ctx).writeTo(new File(OUTPUT_DIR + newName + ".xml"));
}
}
private static TreeContext getTreeContext(String file) {
try {
TreeContext t = Generators.getInstance().getTree(file);
return t;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
@@ -0,0 +1,42 @@
# This file is part of GumTree.
#
# GumTree is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GumTree 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with GumTree. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright 2016 Jean-Rémy Falleri <jr.falleri@gmail.com>
# Copyright 2016 Floréal Morandat <florealm@gmail.com>
library(ggplot2)
library(plyr)
folder <- commandArgs()[length(commandArgs())]
pdf(file = file.path(folder, "all_results.pdf"))
files <- list.files(path = folder, pattern = "*.csv", full.names = T)
d <- ldply(files, function (filename) {
fname = strsplit(gsub("^.*results_(\\d*)(_([^_]*))?.csv", "\\1 \\3 ???????", filename), " ")[[1]]
cbind(read.csv(filename), timestamp =
paste(as.POSIXct(as.numeric(fname[[1]])/1000, origin="1970-01-01"),
fname[[2]], sep='\n'))
})
d$name <- gsub('^.*perfs_(.*)_v0_(.*).xml$', '\\1_\\2', d$Param..refPath)
# according to my office mate we should change the size of each line from 0.5 to 0.1
# but I don't know how to do this (size=seq(0.5, 0.1) does not work)
ggplot(d, aes(timestamp, Score, group=d$name, colour=name)) +
geom_point() +
geom_line() +
ylab('Time (s)') +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
axis.title.x=element_blank())
@@ -0,0 +1,54 @@
Insert ExprStatement(8983) into Compound(8987) at 1
Insert Some(8982) into ExprStatement(8983) at 0
Insert Ident(8985) into ReturnExpr(8986) at 0
Move ReturnExpr(37550) into If(37562) at 2
Move ReturnExpr(37572) into If(37582) at 2
Move ArrayAccess(42344) into Binary(42359) at 2
Insert FunCall(8980) into Some(8982) at 0
Insert GenericString: ;(8981) into Some(8982) at 1
Update GenericString: ENETDOWN(8972) to NETDEV_TX_OK
Move GenericString: ENETDOWN(8972) into Ident(8985) at 0
Move Ident(37555) into Binary(37576) at 0
Update GenericString: <(37556) to >=
Move GenericString: <(37556) into Binary(37576) at 1
Insert FunCall(37575) into Binary(37576) at 2
Move Binary(42350) into Binary(42359) at 0
Insert Ident(7105) into ReturnExpr(7106) at 0
Insert Ident(8524) into ReturnExpr(8525) at 0
Insert Ident(8975) into FunCall(8980) at 0
Insert GenericList(8979) into FunCall(8980) at 1
Insert Ident(9137) into ReturnExpr(9138) at 0
Insert Ident(37568) into FunCall(37575) at 0
Insert GenericList(37574) into FunCall(37575) at 1
Insert GenericString: NETDEV_TX_BUSY(7104) into Ident(7105) at 0
Insert GenericString: NETDEV_TX_BUSY(8523) into Ident(8524) at 0
Insert GenericString: dev_kfree_skb_any(8974) into Ident(8975) at 0
Insert Left(8978) into GenericList(8979) at 0
Insert GenericString: NETDEV_TX_BUSY(9136) into Ident(9137) at 0
Insert GenericString: ARRAY_SIZE(37567) into Ident(37568) at 0
Insert Left(37573) into GenericList(37574) at 0
Insert Ident(8977) into Left(8978) at 0
Insert RecordAccess(37572) into Left(37573) at 0
Insert GenericString: skb(8976) into Ident(8977) at 0
Insert Ident(37570) into RecordAccess(37572) at 0
Insert GenericString: ssids(37571) into RecordAccess(37572) at 1
Update GenericString: index(37561) to SSID_rid
Move GenericString: index(37561) into Ident(37570) at 0
Delete Constant: 1(7104)
Delete Constant: 1(8522)
Delete Ident(8973)
Delete GenericString: -(8974)
Delete Unary(8975)
Delete Constant: 1(9126)
Delete Compound(37551)
Delete Constant: 0(37557)
Delete Binary(37558)
Delete ParenExpr(37559)
Delete GenericString: ||(37560)
Delete Ident(37562)
Delete GenericString: >=(37563)
Delete Constant: 4(37564)
Delete Binary(37565)
Delete ParenExpr(37566)
Delete Compound(37573)
Delete ParenExpr(42351)
@@ -0,0 +1,864 @@
Insert Definition(17794) into Program(73177) at 275
Insert Declaration(18390) into Program(73177) at 282
Insert Definition(19619) into Program(73177) at 284
Insert Definition(17793) into Definition(17794) at 0
Insert DeclList(18389) into Declaration(18390) at 0
Insert Definition(19618) into Definition(19619) at 0
Move Storage(17552) into Definition(17793) at 0
Move ParamList(17561) into Definition(17793) at 1
Move GenericString: ipw_fw_dma_add_buffer(17562) into Definition(17793) at 2
Insert Compound(17792) into Definition(17793) at 3
Insert Storage(19068) into Definition(19618) at 0
Move ParamList(19068) into Definition(19618) at 1
Insert GenericString: ipw_load_firmware(19076) into Definition(19618) at 2
Insert Compound(19617) into Definition(19618) at 3
Insert DeclList(9708) into Compound(9729) at 0
Insert ParameterType(17626) into ParamList(17631) at 2
Move DeclList(17567) into Compound(17792) at 0
Move DeclList(17579) into Compound(17792) at 1
Move ExprStatement(17588) into Compound(17792) at 2
Move ExprStatement(17606) into Compound(17792) at 3
Insert For(17780) into Compound(17792) at 4
Move ExprStatement(17782) into Compound(17792) at 5
Insert ReturnExpr(17791) into Compound(17792) at 6
Insert GenericString: static(19067) into Storage(19068) at 0
Move DeclList(19075) into Compound(19617) at 0
Move DeclList(19079) into Compound(19617) at 1
Insert DeclList(19088) into Compound(19617) at 2
Insert DeclList(19092) into Compound(19617) at 3
Insert DeclList(19094) into Compound(19617) at 4
Insert DeclList(19096) into Compound(19617) at 5
Insert DeclList(19098) into Compound(19617) at 6
Insert DeclList(19100) into Compound(19617) at 7
Move ExprStatement(19094) into Compound(19617) at 8
Move ExprStatement(17683) into Compound(19617) at 9
Insert If(19155) into Compound(19617) at 10
Move ExprStatement(19159) into Compound(19617) at 11
Move ExprStatement(17701) into Compound(19617) at 12
Insert DoWhile(19495) into Compound(19617) at 13
Move ExprStatement(19298) into Compound(19617) at 14
Move If(19314) into Compound(19617) at 15
Move ExprStatement(19328) into Compound(19617) at 16
Move If(19344) into Compound(19617) at 17
Move Label(19367) into Compound(19617) at 18
Insert ExprStatement(19613) into Compound(19617) at 19
Move ReturnExpr(19370) into Compound(19617) at 20
Insert ExprStatement(70100) into Compound(70104) at 1
Insert ReturnExpr(70103) into Compound(70104) at 2
Insert GenericString: p(9699) into DeclList(9708) at 0
Insert InitExpr(9707) into DeclList(9708) at 1
Update GenericString: src_phys(17555) to src_address
Insert GenericString: nr(17625) into ParameterType(17626) at 0
Update GenericString: length(17559) to len
Update GenericString: bytes_left(17563) to ret
Insert GenericString: i(17634) into DeclList(17635) at 1
Update GenericString: status(17576) to size
Insert ExprStatement(17672) into For(17780) at 0
Insert ExprStatement(17681) into For(17780) at 1
Insert ExprStatement(17687) into For(17780) at 2
Insert Compound(17779) into For(17780) at 3
Insert Constant: 0(17790) into ReturnExpr(17791) at 0
Update GenericString: rc(19070) to ret
Insert GenericString: chunk(19087) into DeclList(19088) at 0
Insert GenericString: total_nr(19089) into DeclList(19092) at 0
Insert InitExpr(19091) into DeclList(19092) at 1
Insert GenericString: i(19093) into DeclList(19094) at 0
Insert GenericString: pool(19095) into DeclList(19096) at 0
Insert GenericString: virts(19097) into DeclList(19098) at 0
Insert GenericString: phys(19099) into DeclList(19100) at 0
Insert IfToken(19135) into If(19155) at 0
Insert Unary(19139) into If(19155) at 1
Insert Compound(19154) into If(19155) at 2
Insert Compound(19488) into DoWhile(19495) at 0
Move Binary(19283) into DoWhile(19495) at 1
Insert For(19602) into Label(19603) at 1
Insert Some(19612) into ExprStatement(19613) at 0
Insert Some(70099) into ExprStatement(70100) at 0
Insert Ident(70102) into ReturnExpr(70103) at 0
Insert FunCall(9368) into InitExpr(9369) at 0
Insert FunCall(9423) into InitExpr(9424) at 0
Insert FunCall(9478) into InitExpr(9479) at 0
Insert FunCall(9539) into InitExpr(9540) at 0
Insert FunCall(9626) into InitExpr(9627) at 0
Insert FunCall(9706) into InitExpr(9707) at 0
Insert FunCall(9751) into InitExpr(9752) at 0
Insert FunCall(9828) into InitExpr(9829) at 0
Insert FunCall(9885) into InitExpr(9886) at 0
Insert FunCall(9976) into InitExpr(9977) at 0
Insert FunCall(10032) into InitExpr(10033) at 0
Insert FunCall(10122) into InitExpr(10123) at 0
Insert FunCall(10197) into InitExpr(10198) at 0
Insert FunCall(10285) into InitExpr(10286) at 0
Insert FunCall(10360) into InitExpr(10361) at 0
Insert FunCall(10448) into InitExpr(10449) at 0
Insert FunCall(10523) into InitExpr(10524) at 0
Insert FunCall(10671) into InitExpr(10672) at 0
Insert FunCall(10985) into InitExpr(10986) at 0
Insert FunCall(11049) into InitExpr(11050) at 0
Insert FunCall(11163) into InitExpr(11164) at 0
Insert FunCall(11395) into InitExpr(11396) at 0
Insert FunCall(11443) into InitExpr(11444) at 0
Insert Some(17671) into ExprStatement(17672) at 0
Insert Some(17680) into ExprStatement(17681) at 0
Insert Some(17686) into ExprStatement(17687) at 0
Insert ExprStatement(17713) into Compound(17779) at 0
Move ExprStatement(17647) into Compound(17779) at 1
Move If(17674) into Compound(17779) at 2
Insert Constant: 0(19090) into InitExpr(19091) at 0
Insert Ident(19137) into Unary(19139) at 0
Insert GenericString: !(19138) into Unary(19139) at 1
Insert ExprStatement(19148) into Compound(19154) at 0
Move ReturnExpr(19128) into Compound(19154) at 1
Insert FunCall(19183) into Some(19185) at 0
Insert DeclList(19188) into Compound(19488) at 0
Insert DeclList(19190) into Compound(19488) at 1
Insert DeclList(19192) into Compound(19488) at 2
Insert DeclList(19196) into Compound(19488) at 3
Move ExprStatement(19195) into Compound(19488) at 4
Move ExprStatement(19203) into Compound(19488) at 5
Move ExprStatement(19276) into Compound(19488) at 6
Insert ExprStatement(19248) into Compound(19488) at 7
Insert ExprStatement(19269) into Compound(19488) at 8
Insert For(19420) into Compound(19488) at 9
Move ExprStatement(19244) into Compound(19488) at 10
Move If(19260) into Compound(19488) at 11
Insert ExprStatement(19487) into Compound(19488) at 12
Update GenericString: rc(19300) to ret
Update GenericString: rc(19330) to ret
Insert ExprStatement(19564) into For(19602) at 0
Insert ExprStatement(19573) into For(19602) at 1
Insert ExprStatement(19579) into For(19602) at 2
Insert ExprStatement(19601) into For(19602) at 3
Insert FunCall(19610) into Some(19612) at 0
Insert GenericString: ;(19611) into Some(19612) at 1
Update GenericString: rc(19368) to ret
Insert FunCall(70097) into Some(70099) at 0
Insert GenericString: ;(70098) into Some(70099) at 1
Insert GenericString: NETDEV_TX_OK(70101) into Ident(70102) at 0
Insert Ident(9363) into FunCall(9368) at 0
Insert GenericList(9367) into FunCall(9368) at 1
Insert Ident(9418) into FunCall(9423) at 0
Insert GenericList(9422) into FunCall(9423) at 1
Insert Ident(9473) into FunCall(9478) at 0
Insert GenericList(9477) into FunCall(9478) at 1
Insert Ident(9534) into FunCall(9539) at 0
Insert GenericList(9538) into FunCall(9539) at 1
Insert Ident(9621) into FunCall(9626) at 0
Insert GenericList(9625) into FunCall(9626) at 1
Insert Ident(9701) into FunCall(9706) at 0
Insert GenericList(9705) into FunCall(9706) at 1
Move Ident(9686) into RecordPtAccess(9713) at 0
Insert Ident(9746) into FunCall(9751) at 0
Insert GenericList(9750) into FunCall(9751) at 1
Insert Ident(9823) into FunCall(9828) at 0
Insert GenericList(9827) into FunCall(9828) at 1
Insert Ident(9880) into FunCall(9885) at 0
Insert GenericList(9884) into FunCall(9885) at 1
Insert Ident(9971) into FunCall(9976) at 0
Insert GenericList(9975) into FunCall(9976) at 1
Insert Ident(10027) into FunCall(10032) at 0
Insert GenericList(10031) into FunCall(10032) at 1
Insert Ident(10117) into FunCall(10122) at 0
Insert GenericList(10121) into FunCall(10122) at 1
Insert Ident(10192) into FunCall(10197) at 0
Insert GenericList(10196) into FunCall(10197) at 1
Insert Ident(10280) into FunCall(10285) at 0
Insert GenericList(10284) into FunCall(10285) at 1
Insert Ident(10355) into FunCall(10360) at 0
Insert GenericList(10359) into FunCall(10360) at 1
Insert Ident(10443) into FunCall(10448) at 0
Insert GenericList(10447) into FunCall(10448) at 1
Insert Ident(10518) into FunCall(10523) at 0
Insert GenericList(10522) into FunCall(10523) at 1
Insert Ident(10666) into FunCall(10671) at 0
Insert GenericList(10670) into FunCall(10671) at 1
Insert Ident(10980) into FunCall(10985) at 0
Insert GenericList(10984) into FunCall(10985) at 1
Insert Ident(11044) into FunCall(11049) at 0
Insert GenericList(11048) into FunCall(11049) at 1
Insert Ident(11158) into FunCall(11163) at 0
Insert GenericList(11162) into FunCall(11163) at 1
Insert Ident(11390) into FunCall(11395) at 0
Insert GenericList(11394) into FunCall(11395) at 1
Insert Ident(11438) into FunCall(11443) at 0
Insert GenericList(11442) into FunCall(11443) at 1
Insert Assignment(17669) into Some(17671) at 0
Insert GenericString: ;(17670) into Some(17671) at 1
Insert Binary(17678) into Some(17680) at 0
Insert GenericString: ;(17679) into Some(17680) at 1
Insert Postfix(17685) into Some(17686) at 0
Insert Some(17712) into ExprStatement(17713) at 0
Update GenericString: +=(17677) to =
Insert FunCall(19130) into Assignment(19131) at 2
Update GenericString: dest_offset(17684) to pool
Move GenericString: dest_offset(17684) into Ident(19137) at 0
Insert Some(19147) into ExprStatement(19148) at 0
Insert Ident(19171) into FunCall(19183) at 0
Insert GenericList(19182) into FunCall(19183) at 1
Insert GenericString: chunk_len(19187) into DeclList(19188) at 0
Insert GenericString: start(19189) into DeclList(19190) at 0
Insert GenericString: size(19191) into DeclList(19192) at 0
Insert GenericString: nr(19193) into DeclList(19196) at 0
Insert InitExpr(19195) into DeclList(19196) at 1
Insert Some(19247) into ExprStatement(19248) at 0
Insert Some(19268) into ExprStatement(19269) at 0
Insert ExprStatement(19277) into For(19420) at 0
Insert ExprStatement(19286) into For(19420) at 1
Insert ExprStatement(19292) into For(19420) at 2
Insert Compound(19419) into For(19420) at 3
Insert Some(19486) into ExprStatement(19487) at 0
Insert Some(19563) into ExprStatement(19564) at 0
Insert Some(19572) into ExprStatement(19573) at 0
Insert Some(19578) into ExprStatement(19579) at 0
Move Some(19365) into ExprStatement(19601) at 0
Insert Ident(19605) into FunCall(19610) at 0
Insert GenericList(19609) into FunCall(19610) at 1
Insert Ident(70092) into FunCall(70097) at 0
Insert GenericList(70096) into FunCall(70097) at 1
Update GenericString: d(9362) to dev_get_drvdata
Move GenericString: d(9362) into Ident(9363) at 0
Insert Left(9366) into GenericList(9367) at 0
Update GenericString: d(9414) to dev_get_drvdata
Move GenericString: d(9414) into Ident(9418) at 0
Insert Left(9421) into GenericList(9422) at 0
Update GenericString: d(9466) to dev_get_drvdata
Move GenericString: d(9466) into Ident(9473) at 0
Insert Left(9476) into GenericList(9477) at 0
Update GenericString: d(9524) to dev_get_drvdata
Move GenericString: d(9524) into Ident(9534) at 0
Insert Left(9537) into GenericList(9538) at 0
Update GenericString: d(9608) to dev_get_drvdata
Move GenericString: d(9608) into Ident(9621) at 0
Insert Left(9624) into GenericList(9625) at 0
Insert GenericString: dev_get_drvdata(9700) into Ident(9701) at 0
Insert Left(9704) into GenericList(9705) at 0
Update GenericString: d(9685) to p
Update GenericString: d(9724) to dev_get_drvdata
Move GenericString: d(9724) into Ident(9746) at 0
Insert Left(9749) into GenericList(9750) at 0
Update GenericString: d(9798) to dev_get_drvdata
Move GenericString: d(9798) into Ident(9823) at 0
Insert Left(9826) into GenericList(9827) at 0
Update GenericString: d(9852) to dev_get_drvdata
Move GenericString: d(9852) into Ident(9880) at 0
Insert Left(9883) into GenericList(9884) at 0
Update GenericString: d(9940) to dev_get_drvdata
Move GenericString: d(9940) into Ident(9971) at 0
Insert Left(9974) into GenericList(9975) at 0
Update GenericString: d(9993) to dev_get_drvdata
Move GenericString: d(9993) into Ident(10027) at 0
Insert Left(10030) into GenericList(10031) at 0
Update GenericString: d(10080) to dev_get_drvdata
Move GenericString: d(10080) into Ident(10117) at 0
Insert Left(10120) into GenericList(10121) at 0
Update GenericString: d(10152) to dev_get_drvdata
Move GenericString: d(10152) into Ident(10192) at 0
Insert Left(10195) into GenericList(10196) at 0
Update GenericString: d(10237) to dev_get_drvdata
Move GenericString: d(10237) into Ident(10280) at 0
Insert Left(10283) into GenericList(10284) at 0
Update GenericString: d(10309) to dev_get_drvdata
Move GenericString: d(10309) into Ident(10355) at 0
Insert Left(10358) into GenericList(10359) at 0
Update GenericString: d(10394) to dev_get_drvdata
Move GenericString: d(10394) into Ident(10443) at 0
Insert Left(10446) into GenericList(10447) at 0
Update GenericString: d(10466) to dev_get_drvdata
Move GenericString: d(10466) into Ident(10518) at 0
Insert Left(10521) into GenericList(10522) at 0
Update GenericString: d(10611) to dev_get_drvdata
Move GenericString: d(10611) into Ident(10666) at 0
Insert Left(10669) into GenericList(10670) at 0
Update GenericString: d(10922) to dev_get_drvdata
Move GenericString: d(10922) into Ident(10980) at 0
Insert Left(10983) into GenericList(10984) at 0
Update GenericString: d(10983) to dev_get_drvdata
Move GenericString: d(10983) into Ident(11044) at 0
Insert Left(11047) into GenericList(11048) at 0
Update GenericString: d(11095) to dev_get_drvdata
Move GenericString: d(11095) into Ident(11158) at 0
Insert Left(11161) into GenericList(11162) at 0
Update GenericString: d(11325) to dev_get_drvdata
Move GenericString: d(11325) into Ident(11390) at 0
Insert Left(11393) into GenericList(11394) at 0
Update GenericString: d(11371) to dev_get_drvdata
Move GenericString: d(11371) into Ident(11438) at 0
Insert Left(11441) into GenericList(11442) at 0
Move Left(19140) into GenericList(17660) at 3
Insert Ident(17666) into Assignment(17669) at 0
Insert GenericString: =(17667) into Assignment(17669) at 1
Insert Constant: 0(17668) into Assignment(17669) at 2
Insert Ident(17674) into Binary(17678) at 0
Insert GenericString: <(17675) into Binary(17678) at 1
Insert Ident(17677) into Binary(17678) at 2
Insert Ident(17683) into Postfix(17685) at 0
Insert GenericString: ++(17684) into Postfix(17685) at 1
Insert Assignment(17710) into Some(17712) at 0
Insert GenericString: ;(17711) into Some(17712) at 1
Update GenericString: status(17649) to ret
Update GenericString: src_offset(17675) to pool
Insert Ident(19114) into FunCall(19130) at 0
Insert GenericList(19129) into FunCall(19130) at 1
Insert FunCall(19145) into Some(19147) at 0
Move GenericString: ;(17690) into Some(19147) at 1
Update GenericString: rc(19146) to ret
Update GenericString: bytes_left(17693) to BUG_ON
Move GenericString: bytes_left(17693) into Ident(19171) at 0
Insert Left(19181) into GenericList(19182) at 0
Insert Constant: 0(19194) into InitExpr(19195) at 0
Insert Assignment(19245) into Some(19247) at 0
Insert GenericString: ;(19246) into Some(19247) at 1
Insert Assignment(19266) into Some(19268) at 0
Insert GenericString: ;(19267) into Some(19268) at 1
Move Some(17755) into ExprStatement(19277) at 0
Move Some(17769) into ExprStatement(19286) at 0
Insert Some(19291) into ExprStatement(19292) at 0
Move ExprStatement(19118) into Compound(19419) at 0
Move If(19129) into Compound(19419) at 1
Move ExprStatement(19145) into Compound(19419) at 2
Move ExprStatement(19176) into Compound(19419) at 3
Insert ExprStatement(19397) into Compound(19419) at 4
Insert ExprStatement(19404) into Compound(19419) at 5
Insert ExprStatement(19418) into Compound(19419) at 6
Update GenericString: rc(19246) to ret
Insert Assignment(19484) into Some(19486) at 0
Insert GenericString: ;(19485) into Some(19486) at 1
Update GenericString: rc(19285) to ret
Update GenericString: rc(19315) to ret
Insert Assignment(19561) into Some(19563) at 0
Insert GenericString: ;(19562) into Some(19563) at 1
Insert Binary(19570) into Some(19572) at 0
Insert GenericString: ;(19571) into Some(19572) at 1
Insert Postfix(19577) into Some(19578) at 0
Insert GenericString: pci_pool_destroy(19604) into Ident(19605) at 0
Insert Left(19608) into GenericList(19609) at 0
Update GenericString: EOPNOTSUPP(69842) to dev_kfree_skb
Move GenericString: EOPNOTSUPP(69842) into Ident(70092) at 0
Insert Left(70095) into GenericList(70096) at 0
Insert Ident(9365) into Left(9366) at 0
Insert Ident(9420) into Left(9421) at 0
Insert Ident(9475) into Left(9476) at 0
Insert Ident(9536) into Left(9537) at 0
Insert Ident(9623) into Left(9624) at 0
Insert Ident(9703) into Left(9704) at 0
Insert Ident(9748) into Left(9749) at 0
Insert Ident(9825) into Left(9826) at 0
Insert Ident(9882) into Left(9883) at 0
Insert Ident(9973) into Left(9974) at 0
Insert Ident(10029) into Left(10030) at 0
Insert Ident(10119) into Left(10120) at 0
Insert Ident(10194) into Left(10195) at 0
Insert Ident(10282) into Left(10283) at 0
Insert Ident(10357) into Left(10358) at 0
Insert Ident(10445) into Left(10446) at 0
Insert Ident(10520) into Left(10521) at 0
Insert Ident(10668) into Left(10669) at 0
Insert Ident(10982) into Left(10983) at 0
Insert Ident(11046) into Left(11047) at 0
Insert Ident(11160) into Left(11161) at 0
Insert Ident(11392) into Left(11393) at 0
Insert Ident(11440) into Left(11441) at 0
Update Constant: "src_phys=0x%x dest_address=0x%x length=0x%x\n"(17591) to "nr=%d dest_address=0x%x len=0x%x\n"
Insert GenericString: i(17665) into Ident(17666) at 0
Insert GenericString: i(17673) into Ident(17674) at 0
Insert GenericString: nr(17676) into Ident(17677) at 0
Insert GenericString: i(17682) into Ident(17683) at 0
Insert Ident(17689) into Assignment(17710) at 0
Insert GenericString: =(17690) into Assignment(17710) at 1
Insert FunCall(17709) into Assignment(17710) at 2
Insert GenericString: pci_pool_create(19113) into Ident(19114) at 0
Insert Left(19116) into GenericList(19129) at 0
Move Left(19104) into GenericList(19129) at 1
Insert Left(19124) into GenericList(19129) at 2
Insert Left(19126) into GenericList(19129) at 3
Insert Left(19128) into GenericList(19129) at 4
Insert Ident(19141) into FunCall(19145) at 0
Insert GenericList(19144) into FunCall(19145) at 1
Move Binary(19169) into Left(19181) at 0
Update GenericString: +=(19263) to =
Move Ident(17711) into Assignment(19245) at 0
Move GenericString: =(17712) into Assignment(19245) at 1
Insert Binary(19244) into Assignment(19245) at 2
Insert Ident(19250) into Assignment(19266) at 0
Insert GenericString: =(19251) into Assignment(19266) at 1
Insert Binary(19265) into Assignment(19266) at 2
Insert Assignment(19274) into Some(19276) at 0
Insert Binary(19283) into Some(19285) at 0
Insert Postfix(19290) into Some(19291) at 0
Insert Compound(19342) into If(19343) at 2
Insert Some(19396) into ExprStatement(19397) at 0
Insert Some(19403) into ExprStatement(19404) at 0
Insert Some(19417) into ExprStatement(19418) at 0
Insert Ident(19480) into Assignment(19484) at 0
Insert GenericString: +=(19481) into Assignment(19484) at 1
Insert Ident(19483) into Assignment(19484) at 2
Insert Ident(19558) into Assignment(19561) at 0
Insert GenericString: =(19559) into Assignment(19561) at 1
Insert Constant: 0(19560) into Assignment(19561) at 2
Insert Ident(19566) into Binary(19570) at 0
Insert GenericString: <(19567) into Binary(19570) at 1
Insert Ident(19569) into Binary(19570) at 2
Insert Ident(19575) into Postfix(19577) at 0
Insert GenericString: ++(19576) into Postfix(19577) at 1
Insert Ident(19607) into Left(19608) at 0
Insert Ident(70094) into Left(70095) at 0
Insert GenericString: d(9364) into Ident(9365) at 0
Insert GenericString: d(9419) into Ident(9420) at 0
Insert GenericString: d(9474) into Ident(9475) at 0
Insert GenericString: d(9535) into Ident(9536) at 0
Insert GenericString: d(9622) into Ident(9623) at 0
Insert GenericString: d(9702) into Ident(9703) at 0
Insert GenericString: d(9747) into Ident(9748) at 0
Insert GenericString: d(9824) into Ident(9825) at 0
Insert GenericString: d(9881) into Ident(9882) at 0
Insert GenericString: d(9972) into Ident(9973) at 0
Insert GenericString: d(10028) into Ident(10029) at 0
Insert GenericString: d(10118) into Ident(10119) at 0
Insert GenericString: d(10193) into Ident(10194) at 0
Insert GenericString: d(10281) into Ident(10282) at 0
Insert GenericString: d(10356) into Ident(10357) at 0
Insert GenericString: d(10444) into Ident(10445) at 0
Insert GenericString: d(10519) into Ident(10520) at 0
Insert GenericString: d(10667) into Ident(10668) at 0
Insert GenericString: d(10981) into Ident(10982) at 0
Insert GenericString: d(11045) into Ident(11046) at 0
Insert GenericString: d(11159) into Ident(11160) at 0
Insert GenericString: d(11391) into Ident(11392) at 0
Insert GenericString: d(11439) into Ident(11440) at 0
Update GenericString: src_phys(17593) to nr
Insert GenericString: size(17688) into Ident(17689) at 0
Insert Ident(17692) into FunCall(17709) at 0
Insert GenericList(17708) into FunCall(17709) at 1
Update GenericString: status(17613) to ret
Insert Constant: "ipw2200"(19115) into Left(19116) at 0
Insert Ident(19123) into Left(19124) at 0
Insert Constant: 0(19125) into Left(19126) at 0
Insert Constant: 0(19127) into Left(19128) at 0
Update GenericString: CB_MAX_LENGTH(17687) to IPW_ERROR
Move GenericString: CB_MAX_LENGTH(17687) into Ident(19141) at 0
Insert Left(19143) into GenericList(19144) at 0
Update GenericString: offset(19261) to chunk_len
Update GenericString: status(17710) to start
Move Ident(17719) into Binary(19244) at 0
Move GenericString: +(17720) into Binary(19244) at 1
Move Ident(17722) into Binary(19244) at 2
Insert GenericString: nr(19249) into Ident(19250) at 0
Insert ParenExpr(19261) into Binary(19265) at 0
Insert GenericString: /(19262) into Binary(19265) at 1
Insert Ident(19264) into Binary(19265) at 2
Insert Ident(19271) into Assignment(19274) at 0
Insert GenericString: =(19272) into Assignment(19274) at 1
Insert Constant: 0(19273) into Assignment(19274) at 2
Insert Ident(19279) into Binary(19283) at 0
Insert GenericString: <(19280) into Binary(19283) at 1
Insert Ident(19282) into Binary(19283) at 2
Insert Ident(19288) into Postfix(19290) at 0
Insert GenericString: ++(19289) into Postfix(19290) at 1
Insert ArrayAccess(19326) into Unary(19328) at 0
Insert ExprStatement(19339) into Compound(19342) at 0
Insert Goto(19341) into Compound(19342) at 1
Insert Assignment(19366) into Some(19368) at 0
Insert Assignment(19394) into Some(19396) at 0
Insert GenericString: ;(19395) into Some(19396) at 1
Insert Postfix(19401) into Some(19403) at 0
Insert GenericString: ;(19402) into Some(19403) at 1
Insert FunCall(19415) into Some(19417) at 0
Insert GenericString: ;(19416) into Some(19417) at 1
Update GenericString: rc(19204) to ret
Insert GenericString: offset(19479) into Ident(19480) at 0
Insert GenericString: chunk_len(19482) into Ident(19483) at 0
Insert GenericString: i(19557) into Ident(19558) at 0
Insert GenericString: i(19565) into Ident(19566) at 0
Insert GenericString: total_nr(19568) into Ident(19569) at 0
Insert GenericString: i(19574) into Ident(19575) at 0
Update GenericString: pci_free_consistent(19346) to pci_pool_free
Insert Left(19590) into GenericList(19597) at 1
Insert GenericString: pool(19606) into Ident(19607) at 0
Insert Binary(36133) into Binary(36134) at 2
Insert GenericString: skb(70093) into Ident(70094) at 0
Insert GenericString: min_t(17691) into Ident(17692) at 0
Insert ParameterType(17693) into GenericList(17708) at 0
Insert Left(17704) into GenericList(17708) at 1
Move Left(17637) into GenericList(17708) at 2
Move Left(17717) into GenericList(17746) at 0
Insert Left(17741) into GenericList(17746) at 3
Move GenericString: CB_MAX_LENGTH(17678) into Ident(19123) at 0
Insert Constant: "pci_pool_create failed\n"(19142) into Left(19143) at 0
Update GenericString: src_phys(17718) to data
Update GenericString: src_offset(17721) to offset
Insert Binary(19260) into ParenExpr(19261) at 0
Update GenericString: status(17746) to CB_MAX_LENGTH
Move GenericString: status(17746) into Ident(19264) at 0
Update GenericString: IPW_DEBUG_FW_INFO(17748) to i
Move GenericString: IPW_DEBUG_FW_INFO(17748) into Ident(19271) at 0
Update GenericString: IPW_DEBUG_FW_INFO(17762) to i
Move GenericString: IPW_DEBUG_FW_INFO(17762) into Ident(19279) at 0
Insert GenericString: nr(19281) into Ident(19282) at 0
Insert GenericString: i(19287) into Ident(19288) at 0
Insert ArrayAccess(19297) into Assignment(19317) at 0
Insert Ident(19323) into ArrayAccess(19326) at 0
Insert Ident(19325) into ArrayAccess(19326) at 1
Insert Some(19338) into ExprStatement(19339) at 0
Insert GenericString: out(19340) into Goto(19341) at 0
Insert Ident(19345) into Assignment(19366) at 0
Insert GenericString: =(19346) into Assignment(19366) at 1
Insert FunCall(19365) into Assignment(19366) at 2
Insert Ident(19390) into Assignment(19394) at 0
Insert GenericString: +=(19391) into Assignment(19394) at 1
Insert Ident(19393) into Assignment(19394) at 2
Insert Ident(19399) into Postfix(19401) at 0
Insert GenericString: ++(19400) into Postfix(19401) at 1
Insert Ident(19406) into FunCall(19415) at 0
Insert GenericList(19414) into FunCall(19415) at 1
Insert Left(19443) into GenericList(19457) at 2
Move Left(19235) into GenericList(19457) at 4
Insert Ident(19583) into Left(19584) at 0
Insert ArrayAccess(19589) into Left(19590) at 0
Insert ArrayAccess(19595) into Left(19596) at 0
Move Ident(35884) into Binary(36133) at 0
Insert GenericString: -(36131) into Binary(36133) at 1
Insert Constant: 1(36132) into Binary(36133) at 2
Insert Binary(17703) into Left(17704) at 0
Insert ArrayAccess(17726) into Left(17727) at 0
Insert Ident(17740) into Left(17741) at 0
Insert Binary(19257) into Binary(19260) at 0
Insert GenericString: -(19258) into Binary(19260) at 1
Insert Constant: 1(19259) into Binary(19260) at 2
Insert Ident(19294) into ArrayAccess(19297) at 0
Insert Ident(19296) into ArrayAccess(19297) at 1
Update GenericString: shared_virt(19120) to virts
Move GenericString: shared_virt(19120) into Ident(19323) at 0
Insert GenericString: total_nr(19324) into Ident(19325) at 0
Insert Assignment(19336) into Some(19338) at 0
Insert GenericString: ;(19337) into Some(19338) at 1
Insert GenericString: size(19344) into Ident(19345) at 0
Move Ident(19131) into FunCall(19365) at 0
Move GenericList(19141) into FunCall(19365) at 1
Update GenericString: BUG(19170) to memcpy
Insert Left(19377) into GenericList(19384) at 0
Insert Left(19380) into GenericList(19384) at 1
Insert Left(19383) into GenericList(19384) at 2
Insert GenericString: start(19389) into Ident(19390) at 0
Insert GenericString: size(19392) into Ident(19393) at 0
Insert GenericString: total_nr(19398) into Ident(19399) at 0
Insert GenericString: BUG_ON(19405) into Ident(19406) at 0
Insert Left(19413) into GenericList(19414) at 0
Insert Unary(19439) into Left(19440) at 0
Insert Ident(19442) into Left(19443) at 0
Insert Ident(19455) into Left(19456) at 0
Update GenericString: priv(19348) to pool
Move GenericString: priv(19348) into Ident(19583) at 0
Insert Ident(19586) into ArrayAccess(19589) at 0
Insert Ident(19588) into ArrayAccess(19589) at 1
Insert Ident(19592) into ArrayAccess(19595) at 0
Insert Ident(19594) into ArrayAccess(19595) at 1
Insert Ident(17695) into Binary(17703) at 0
Insert GenericString: -(17696) into Binary(17703) at 1
Insert Binary(17702) into Binary(17703) at 2
Insert Ident(17723) into ArrayAccess(17726) at 0
Insert Ident(17725) into ArrayAccess(17726) at 1
Insert Binary(17736) into Binary(17737) at 2
Insert GenericString: size(17739) into Ident(17740) at 0
Move Ident(17726) into Binary(19257) at 0
Move GenericString: +(17727) into Binary(19257) at 1
Move Ident(17729) into Binary(19257) at 2
Update GenericString: shared_virt(19095) to virts
Move GenericString: shared_virt(19095) into Ident(19294) at 0
Insert GenericString: total_nr(19295) into Ident(19296) at 0
Update GenericString: pci_alloc_consistent(19098) to pci_pool_alloc
Insert Left(19306) into GenericList(19315) at 1
Insert Ident(19330) into Assignment(19336) at 0
Insert GenericString: =(19331) into Assignment(19336) at 1
Insert Unary(19335) into Assignment(19336) at 2
Update GenericString: memmove(19130) to min_t
Insert ParameterType(19349) into GenericList(19364) at 0
Insert ArrayAccess(19376) into Left(19377) at 0
Insert Ident(19379) into Left(19380) at 0
Insert Ident(19382) into Left(19383) at 0
Insert Binary(19412) into Left(19413) at 0
Insert ArrayAccess(19437) into Unary(19439) at 0
Insert GenericString: &(19438) into Unary(19439) at 1
Update GenericString: le32_to_cpu(19229) to nr
Move GenericString: le32_to_cpu(19229) into Ident(19442) at 0
Update GenericString: chunk(19231) to chunk_len
Move GenericString: chunk(19231) into Ident(19455) at 0
Update GenericString: len(19353) to virts
Move GenericString: len(19353) into Ident(19586) at 0
Update GenericString: shared_virt(19356) to i
Move GenericString: shared_virt(19356) into Ident(19588) at 0
Update GenericString: shared_phys(19359) to phys
Move GenericString: shared_phys(19359) into Ident(19592) at 0
Insert GenericString: i(19593) into Ident(19594) at 0
Insert GenericString: len(17694) into Ident(17695) at 0
Move Ident(17608) into Binary(17702) at 0
Update GenericString: >(17609) to *
Move GenericString: >(17609) into Binary(17702) at 1
Move Ident(17611) into Binary(17702) at 2
Update GenericString: src_phys(17621) to src_address
Move GenericString: src_phys(17621) into Ident(17723) at 0
Update GenericString: src_offset(17624) to i
Move GenericString: src_offset(17624) into Ident(17725) at 0
Move Ident(17632) into Binary(17736) at 0
Insert GenericString: *(17733) into Binary(17736) at 1
Insert Ident(17735) into Binary(17736) at 2
Update GenericString: dest_address(17725) to chunk_len
Update GenericString: dest_offset(17728) to CB_MAX_LENGTH
Insert Ident(19305) into Left(19306) at 0
Insert GenericString: ret(19329) into Ident(19330) at 0
Insert Ident(19333) into Unary(19335) at 0
Insert GenericString: -(19334) into Unary(19335) at 1
Insert Binary(19359) into Left(19360) at 0
Insert Ident(19373) into ArrayAccess(19376) at 0
Insert Ident(19375) into ArrayAccess(19376) at 1
Insert GenericString: start(19378) into Ident(19379) at 0
Insert GenericString: size(19381) into Ident(19382) at 0
Insert Ident(19408) into Binary(19412) at 0
Insert GenericString: >(19409) into Binary(19412) at 1
Insert Ident(19411) into Binary(19412) at 2
Insert Ident(19430) into ArrayAccess(19437) at 0
Insert Binary(19436) into ArrayAccess(19437) at 1
Update GenericString: bytes_left(17607) to i
Update GenericString: dest_offset(17631) to i
Insert GenericString: CB_MAX_LENGTH(17734) into Ident(17735) at 0
Update GenericString: len(19105) to pool
Insert GenericString: GFP_KERNEL(19304) into Ident(19305) at 0
Insert ArrayAccess(19311) into Unary(19313) at 0
Insert GenericString: ENOMEM(19332) into Ident(19333) at 0
Insert Ident(19351) into Binary(19359) at 0
Insert GenericString: -(19352) into Binary(19359) at 1
Insert Binary(19358) into Binary(19359) at 2
Update GenericString: data(19135) to CB_MAX_LENGTH
Insert GenericString: virts(19372) into Ident(19373) at 0
Insert GenericString: total_nr(19374) into Ident(19375) at 0
Insert GenericString: total_nr(19407) into Ident(19408) at 0
Insert GenericString: CB_NUMBER_OF_ELEMENTS_SMALL(19410) into Ident(19411) at 0
Insert GenericString: phys(19429) into Ident(19430) at 0
Move Ident(19213) into Binary(19436) at 0
Update GenericString: +(19214) to -
Move GenericString: +(19214) into Binary(19436) at 1
Move Ident(19216) into Binary(19436) at 2
Insert Ident(19308) into ArrayAccess(19311) at 0
Insert Ident(19310) into ArrayAccess(19311) at 1
Update GenericString: shared_virt(19132) to chunk_len
Move GenericString: shared_virt(19132) into Ident(19351) at 0
Insert Ident(19354) into Binary(19358) at 0
Insert GenericString: *(19355) into Binary(19358) at 1
Insert Ident(19357) into Binary(19358) at 2
Update GenericString: shared_phys(19212) to total_nr
Update GenericString: offset(19215) to nr
Update GenericString: shared_phys(19108) to phys
Move GenericString: shared_phys(19108) into Ident(19308) at 0
Insert GenericString: total_nr(19309) into Ident(19310) at 0
Insert GenericString: i(19353) into Ident(19354) at 0
Insert GenericString: CB_MAX_LENGTH(19356) into Ident(19357) at 0
Delete Ident(9363)
Delete GenericString: driver_data(9364)
Delete RecordPtAccess(9365)
Delete Ident(9415)
Delete GenericString: driver_data(9416)
Delete RecordPtAccess(9417)
Delete Ident(9467)
Delete GenericString: driver_data(9468)
Delete RecordPtAccess(9469)
Delete Ident(9525)
Delete GenericString: driver_data(9526)
Delete RecordPtAccess(9527)
Delete Ident(9609)
Delete GenericString: driver_data(9610)
Delete RecordPtAccess(9611)
Delete GenericString: driver_data(9687)
Delete RecordPtAccess(9688)
Delete Cast(9689)
Delete ParenExpr(9690)
Delete Ident(9725)
Delete GenericString: driver_data(9726)
Delete RecordPtAccess(9727)
Delete Ident(9799)
Delete GenericString: driver_data(9800)
Delete RecordPtAccess(9801)
Delete Ident(9853)
Delete GenericString: driver_data(9854)
Delete RecordPtAccess(9855)
Delete Ident(9941)
Delete GenericString: driver_data(9942)
Delete RecordPtAccess(9943)
Delete Ident(9994)
Delete GenericString: driver_data(9995)
Delete RecordPtAccess(9996)
Delete Ident(10081)
Delete GenericString: driver_data(10082)
Delete RecordPtAccess(10083)
Delete Ident(10153)
Delete GenericString: driver_data(10154)
Delete RecordPtAccess(10155)
Delete Ident(10238)
Delete GenericString: driver_data(10239)
Delete RecordPtAccess(10240)
Delete Ident(10310)
Delete GenericString: driver_data(10311)
Delete RecordPtAccess(10312)
Delete Ident(10395)
Delete GenericString: driver_data(10396)
Delete RecordPtAccess(10397)
Delete Ident(10467)
Delete GenericString: driver_data(10468)
Delete RecordPtAccess(10469)
Delete Ident(10612)
Delete GenericString: driver_data(10613)
Delete RecordPtAccess(10614)
Delete Ident(10923)
Delete GenericString: driver_data(10924)
Delete RecordPtAccess(10925)
Delete Ident(10984)
Delete GenericString: driver_data(10985)
Delete RecordPtAccess(10986)
Delete Cast(10987)
Delete Ident(11096)
Delete GenericString: driver_data(11097)
Delete RecordPtAccess(11098)
Delete Cast(11099)
Delete Ident(11326)
Delete GenericString: driver_data(11327)
Delete RecordPtAccess(11328)
Delete Cast(11329)
Delete Ident(11372)
Delete GenericString: driver_data(11373)
Delete RecordPtAccess(11374)
Delete Cast(11375)
Delete GenericString: length(17564)
Delete Ident(17565)
Delete InitExpr(17566)
Delete Constant: 0(17577)
Delete InitExpr(17578)
Delete GenericString: length(17599)
Delete Ident(17600)
Delete Left(17601)
Delete GenericString: priv(17618)
Delete Ident(17619)
Delete Left(17620)
Delete Ident(17622)
Delete GenericString: +(17623)
Delete Ident(17625)
Delete Binary(17626)
Delete GenericString: src_offset(17568)
Delete Constant: 0(17569)
Delete InitExpr(17570)
Delete DeclList(17571)
Delete GenericString: dest_offset(17572)
Delete Constant: 0(17573)
Delete InitExpr(17574)
Delete DeclList(17575)
Delete Binary(17612)
Delete Ident(17685)
Delete GenericString: +=(17686)
Delete Ident(17688)
Delete Assignment(17689)
Delete Some(17691)
Delete ExprStatement(17692)
Delete Compound(17702)
Delete While(17703)
Delete IfToken(17704)
Delete GenericString: bytes_left(17705)
Delete Ident(17706)
Delete GenericString: >(17707)
Delete Constant: 0(17708)
Delete Binary(17709)
Delete GenericString: ipw_fw_dma_add_command_block(17713)
Delete Ident(17714)
Delete Binary(17723)
Delete Left(17724)
Delete Binary(17730)
Delete Left(17731)
Delete GenericString: bytes_left(17732)
Delete Ident(17733)
Delete Left(17734)
Delete Constant: 0(17735)
Delete Left(17736)
Delete Constant: 0(17737)
Delete Left(17738)
Delete GenericList(17739)
Delete FunCall(17740)
Delete Assignment(17741)
Delete GenericString: ;(17742)
Delete Some(17743)
Delete ExprStatement(17744)
Delete IfToken(17745)
Delete Ident(17747)
Delete ExprStatement(17756)
Delete Constant: 1(17757)
Delete GenericString: -(17758)
Delete Unary(17759)
Delete ReturnExpr(17760)
Delete Compound(17761)
Delete ExprStatement(17770)
Delete If(17771)
Delete Compound(17772)
Delete If(17773)
Delete Constant: 0(17783)
Delete ReturnExpr(17784)
Delete Compound(17785)
Delete Definition(17786)
Delete Definition(17787)
Delete DeclList(18382)
Delete Declaration(18383)
Delete Ident(17679)
Delete Ident(17694)
Delete GenericString: -=(17695)
Delete GenericString: CB_MAX_LENGTH(17696)
Delete Ident(17697)
Delete Assignment(17698)
Delete Ident(17749)
Delete Constant: ": Failed on the buffer tail\n"(17750)
Delete Left(17751)
Delete GenericList(17752)
Delete FunCall(17753)
Delete Ident(17763)
Delete Constant: ": Adding new cb - the buffer tail\n"(17764)
Delete Left(17765)
Delete GenericList(17766)
Delete FunCall(17767)
Delete Ident(19096)
Delete Ident(19109)
Delete Ident(19121)
Delete Ident(19133)
Delete FunCall(19142)
Delete Binary(19217)
Delete Ident(19232)
Delete GenericString: length(19233)
Delete RecordPtAccess(19234)
Delete Ident(19230)
Delete GenericList(19236)
Delete FunCall(19237)
Delete Left(19238)
Delete Ident(19349)
Delete GenericString: pci_dev(19350)
Delete RecordPtAccess(19351)
Delete Ident(19354)
Delete Left(19355)
Delete Ident(19357)
Delete Left(19358)
Delete Ident(19360)
Delete ExprStatement(19366)
Delete GenericString: static(19060)
Delete Storage(19061)
Delete GenericString: ipw_load_firmware(19069)
Delete GenericString: chunk(19080)
Delete DeclList(19081)
Delete GenericString: shared_phys(19082)
Delete DeclList(19083)
Delete GenericString: shared_virt(19084)
Delete DeclList(19085)
Delete IfToken(19160)
Delete GenericString: out(19177)
Delete Goto(19178)
Delete Compound(19179)
Delete If(19180)
Delete Compound(19277)
Delete DoWhile(19284)
Delete Compound(19371)
Delete Definition(19372)
Delete Definition(19373)
Delete Ident(69843)
Delete GenericString: -(69844)
Delete Unary(69845)
Delete ReturnExpr(69846)
@@ -0,0 +1,3 @@
Insert CppTop(40) into Program(79940) at 11
Insert Include(39) into CppTop(40) at 0
Insert GenericString: <linux/smp_lock.h>(38) into Include(39) at 0
@@ -0,0 +1,364 @@
Move CppTop(614) into Program(66952) at 53
Move Declaration(14152) into Program(66952) at 132
Insert CppTop(59) into Program(66952) at 19
Insert Declaration(14257) into Program(66952) at 137
Insert Declaration(14383) into Program(66952) at 143
Insert Include(58) into CppTop(59) at 0
Insert DeclList(14256) into Declaration(14257) at 0
Insert DeclList(14382) into Declaration(14383) at 0
Insert GenericString: <linux/list.h>(57) into Include(58) at 0
Insert Storage(14167) into DeclList(14189) at 0
Insert FullType(14171) into DeclList(14189) at 1
Insert GenericString: phy_ops_niu_10g_hotplug(14172) into DeclList(14189) at 2
Insert InitList(14188) into DeclList(14189) at 3
Insert Storage(14364) into DeclList(14382) at 0
Insert FullType(14368) into DeclList(14382) at 1
Insert GenericString: phy_template_niu_10g_hotplug(14369) into DeclList(14382) at 2
Insert InitList(14381) into DeclList(14382) at 3
Insert If(12686) into Compound(12927) at 3
Insert ReturnExpr(13827) into Compound(13828) at 7
Insert GenericString: static(14166) into Storage(14167) at 0
Insert TypeQualifier(14169) into FullType(14171) at 0
Insert StructUnionName: niu_phy_ops(14170) into FullType(14171) at 1
Insert InitDesignators(14177) into InitList(14188) at 0
Insert InitDesignators(14182) into InitList(14188) at 1
Insert InitDesignators(14187) into InitList(14188) at 2
Insert GenericString: static(14363) into Storage(14364) at 0
Insert TypeQualifier(14366) into FullType(14368) at 0
Insert StructUnionName: niu_phy_template(14367) into FullType(14368) at 1
Insert InitDesignators(14376) into InitList(14381) at 0
Insert InitDesignators(14380) into InitList(14381) at 1
Insert DeclList(40688) into Compound(41253) at 3
Insert If(61112) into Compound(61124) at 21
Insert Binary(8284) into If(8288) at 1
Move IfToken(12661) into If(12686) at 0
Insert Binary(12683) into If(12686) at 1
Insert Goto(12685) into If(12686) at 2
Insert Constant: 0(13826) into ReturnExpr(13827) at 0
Insert GenericString: const(14168) into TypeQualifier(14169) at 0
Insert DesignatorField: serdes_init(14173) into InitDesignators(14177) at 0
Insert InitExpr(14176) into InitDesignators(14177) at 1
Insert DesignatorField: xcvr_init(14178) into InitDesignators(14182) at 0
Insert InitExpr(14181) into InitDesignators(14182) at 1
Insert DesignatorField: link_status(14183) into InitDesignators(14187) at 0
Insert InitExpr(14186) into InitDesignators(14187) at 1
Insert GenericString: const(14365) into TypeQualifier(14366) at 0
Insert DesignatorField: ops(14370) into InitDesignators(14376) at 0
Insert InitExpr(14375) into InitDesignators(14376) at 1
Insert DesignatorField: phy_addr_base(14377) into InitDesignators(14380) at 0
Insert InitExpr(14379) into InitDesignators(14380) at 1
Insert Binary(15853) into If(15857) at 1
Move ReturnExpr(13747) into If(15857) at 2
Insert Binary(15896) into If(15912) at 1
Insert GenericString: ha(40687) into DeclList(40688) at 0
Insert IfToken(61076) into If(61112) at 0
Insert FunCall(61090) into If(61112) at 1
Insert Compound(61111) into If(61112) at 2
Move Binary(8274) into Binary(8284) at 0
Insert GenericString: ||(8278) into Binary(8284) at 1
Insert Binary(8283) into Binary(8284) at 2
Insert Binary(12676) into Binary(12683) at 0
Insert GenericString: ||(12677) into Binary(12683) at 1
Insert Binary(12682) into Binary(12683) at 2
Insert GenericString: out(12684) into Goto(12685) at 0
Insert Label(13806) into Compound(13807) at 3
Insert Ident(14175) into InitExpr(14176) at 0
Insert Ident(14180) into InitExpr(14181) at 0
Insert Ident(14185) into InitExpr(14186) at 0
Insert Unary(14374) into InitExpr(14375) at 0
Insert Constant: 8(14378) into InitExpr(14379) at 0
Insert Ident(15840) into Binary(15853) at 0
Insert GenericString: &&(15841) into Binary(15853) at 1
Insert Unary(15852) into Binary(15853) at 2
Move Unary(15689) into Binary(15896) at 0
Insert GenericString: ||(15886) into Binary(15896) at 1
Insert ParenExpr(15895) into Binary(15896) at 2
Insert MacroIteration(40962) into Compound(40963) at 1
Insert Ident(61078) into FunCall(61090) at 0
Insert GenericList(61089) into FunCall(61090) at 1
Insert ExprStatement(61110) into Compound(61111) at 0
Insert Ident(8280) into Binary(8283) at 0
Insert GenericString: ==(8281) into Binary(8283) at 1
Insert Constant: 0xffff(8282) into Binary(8283) at 2
Move Ident(12663) into Binary(12676) at 0
Move GenericString: <(12664) into Binary(12676) at 1
Move Constant: 0(12665) into Binary(12676) at 2
Insert Ident(12679) into Binary(12682) at 0
Insert GenericString: ==(12680) into Binary(12682) at 1
Insert Constant: 0xffff(12681) into Binary(12682) at 2
Insert GenericString: out(13733) into Label(13806) at 0
Move If(13725) into Label(13806) at 1
Insert GenericString: serdes_init_niu_10g_fiber(14174) into Ident(14175) at 0
Insert GenericString: xcvr_init_10g_bcm8706(14179) into Ident(14180) at 0
Insert GenericString: link_status_10g_hotplug(14184) into Ident(14185) at 0
Insert Ident(14372) into Unary(14374) at 0
Insert GenericString: &(14373) into Unary(14374) at 1
Move GenericString: err(15656) into Ident(15840) at 0
Insert ParenExpr(15850) into Unary(15852) at 0
Insert GenericString: !(15851) into Unary(15852) at 1
Insert Binary(15894) into ParenExpr(15895) at 0
Insert RecordAccess(40804) into Assignment(40805) at 2
Insert GenericString: list_for_each_entry(40849) into MacroIteration(40962) at 0
Insert Left(40852) into MacroIteration(40962) at 1
Insert Left(40861) into MacroIteration(40962) at 2
Insert Left(40864) into MacroIteration(40962) at 3
Move Compound(40760) into MacroIteration(40962) at 4
Insert GenericString: of_find_property(61077) into Ident(61078) at 0
Insert Left(61081) into GenericList(61089) at 0
Insert Left(61083) into GenericList(61089) at 1
Insert Left(61088) into GenericList(61089) at 2
Insert Some(61109) into ExprStatement(61110) at 0
Insert GenericString: err(8279) into Ident(8280) at 0
Move GenericString: err(12916) into Ident(12679) at 0
Insert IfToken(13734) into If(13805) at 0
Insert Compound(13804) into If(13805) at 2
Insert GenericString: phy_ops_niu_10g_hotplug(14371) into Ident(14372) at 0
Insert Binary(15849) into ParenExpr(15850) at 0
Insert RecordPtAccess(15890) into Binary(15894) at 0
Insert GenericString: &(15891) into Binary(15894) at 1
Insert Ident(15893) into Binary(15894) at 2
Insert RecordPtAccess(40802) into RecordAccess(40804) at 0
Insert GenericString: count(40803) into RecordAccess(40804) at 1
Insert Ident(40851) into Left(40852) at 0
Insert Unary(40860) into Left(40861) at 0
Insert Ident(40863) into Left(40864) at 0
Insert Ident(61080) into Left(61081) at 0
Insert Constant: "hot-swappable-phy"(61082) into Left(61083) at 0
Insert Unary(61087) into Left(61088) at 0
Insert Assignment(61107) into Some(61109) at 0
Insert GenericString: ;(61108) into Some(61109) at 1
Move ExprStatement(13724) into Compound(13804) at 0
Insert If(13803) into Compound(13804) at 1
Insert RecordPtAccess(15845) into Binary(15849) at 0
Insert GenericString: &(15846) into Binary(15849) at 1
Insert Ident(15848) into Binary(15849) at 2
Insert Ident(15888) into RecordPtAccess(15890) at 0
Insert GenericString: flags(15889) into RecordPtAccess(15890) at 1
Insert GenericString: NIU_FLAGS_HOTPLUG_PHY(15892) into Ident(15893) at 0
Move Ident(40591) into RecordPtAccess(40802) at 0
Update GenericString: uc_count(40592) to uc
Move GenericString: uc_count(40592) into RecordPtAccess(40802) at 1
Update GenericString: addr(40638) to ha
Move GenericString: addr(40638) into Ident(40851) at 0
Insert RecordAccess(40858) into Unary(40860) at 0
Insert GenericString: &(40859) into Unary(40860) at 1
Update GenericString: addr(40654) to list
Move GenericString: addr(40654) into Ident(40863) at 0
Insert GenericString: dp(61079) into Ident(61080) at 0
Insert Ident(61085) into Unary(61087) at 0
Insert GenericString: &(61086) into Unary(61087) at 1
Insert RecordPtAccess(61094) into Assignment(61107) at 0
Insert GenericString: |=(61095) into Assignment(61107) at 1
Insert ParenExpr(61106) into Assignment(61107) at 2
Insert If(13685) into Compound(13686) at 2
Move IfToken(13699) into If(13803) at 0
Insert Binary(13765) into If(13803) at 1
Insert Compound(13802) into If(13803) at 2
Insert If(15420) into Default(15421) at 0
Insert Ident(15843) into RecordPtAccess(15845) at 0
Insert GenericString: flags(15844) into RecordPtAccess(15845) at 1
Insert GenericString: NIU_FLAGS_HOTPLUG_PHY(15847) into Ident(15848) at 0
Insert GenericString: np(15887) into Ident(15888) at 0
Insert RecordPtAccess(40856) into RecordAccess(40858) at 0
Insert GenericString: list(40857) into RecordAccess(40858) at 1
Insert GenericString: prop_len(61084) into Ident(61085) at 0
Insert Ident(61092) into RecordPtAccess(61094) at 0
Insert GenericString: flags(61093) into RecordPtAccess(61094) at 1
Insert Binary(61105) into ParenExpr(61106) at 0
Insert IfToken(13633) into If(13685) at 0
Insert Ident(13635) into If(13685) at 1
Insert Compound(13684) into If(13685) at 2
Insert Ident(13762) into Binary(13765) at 0
Insert GenericString: ==(13763) into Binary(13765) at 1
Insert Constant: 0xffff(13764) into Binary(13765) at 2
Insert ExprStatement(13775) into Compound(13802) at 0
Insert ExprStatement(13788) into Compound(13802) at 1
Insert ExprStatement(13801) into Compound(13802) at 2
Insert IfToken(15342) into If(15420) at 0
Move Binary(12915) into If(15420) at 1
Insert Compound(15396) into If(15420) at 2
Insert Compound(15419) into If(15420) at 3
Update GenericString: err(15658) to np
Move GenericString: err(15658) into Ident(15843) at 0
Move Ident(40642) into RecordPtAccess(40856) at 0
Update GenericString: uc_list(40643) to uc
Move GenericString: uc_list(40643) into RecordPtAccess(40856) at 1
Insert GenericString: np(61091) into Ident(61092) at 0
Insert Binary(61101) into Binary(61105) at 0
Insert GenericString: |(61102) into Binary(61105) at 1
Insert Ident(61104) into Binary(61105) at 2
Insert GenericString: err(13634) into Ident(13635) at 0
Insert ExprStatement(13660) into Compound(13684) at 0
Move If(13651) into Compound(13684) at 1
Move ExprStatement(13649) into Compound(13684) at 2
Insert GenericString: err(13761) into Ident(13762) at 0
Insert Some(13774) into ExprStatement(13775) at 0
Insert Some(13787) into ExprStatement(13788) at 0
Insert Some(13800) into ExprStatement(13801) at 0
Insert ExprStatement(15361) into Compound(15396) at 0
Insert If(15378) into Compound(15396) at 1
Insert If(15395) into Compound(15396) at 2
Move ExprStatement(15226) into Compound(15419) at 0
Move ExprStatement(15239) into Compound(15419) at 1
Insert Ident(61097) into Binary(61101) at 0
Insert GenericString: |(61098) into Binary(61101) at 1
Insert Ident(61100) into Binary(61101) at 2
Insert GenericString: NIU_FLAGS_HOTPLUG_PHY(61103) into Ident(61104) at 0
Insert Some(13659) into ExprStatement(13660) at 0
Insert Binary(13666) into If(13670) at 1
Insert Assignment(13772) into Some(13774) at 0
Insert GenericString: ;(13773) into Some(13774) at 1
Insert Assignment(13785) into Some(13787) at 0
Insert GenericString: ;(13786) into Some(13787) at 1
Insert Assignment(13798) into Some(13800) at 0
Insert GenericString: ;(13799) into Some(13800) at 1
Insert Some(15360) into ExprStatement(15361) at 0
Insert IfToken(15362) into If(15378) at 0
Insert Binary(15369) into If(15378) at 1
Insert ExprStatement(15377) into If(15378) at 2
Insert IfToken(15379) into If(15395) at 0
Insert Binary(15386) into If(15395) at 1
Insert ExprStatement(15394) into If(15395) at 2
Insert GenericString: NIU_FLAGS_10G(61096) into Ident(61097) at 0
Insert GenericString: NIU_FLAGS_FIBER(61099) into Ident(61100) at 0
Insert Assignment(13657) into Some(13659) at 0
Insert GenericString: ;(13658) into Some(13659) at 1
Insert Ident(13663) into Binary(13666) at 0
Insert GenericString: ==(13664) into Binary(13666) at 1
Insert Constant: 0xffff(13665) into Binary(13666) at 2
Insert Goto(13668) into Compound(13669) at 0
Insert Unary(13769) into Assignment(13772) at 0
Insert GenericString: =(13770) into Assignment(13772) at 1
Insert Constant: 1(13771) into Assignment(13772) at 2
Insert RecordAccess(13781) into Assignment(13785) at 0
Insert GenericString: =(13782) into Assignment(13785) at 1
Insert Ident(13784) into Assignment(13785) at 2
Insert RecordAccess(13794) into Assignment(13798) at 0
Insert GenericString: =(13795) into Assignment(13798) at 1
Insert Ident(13797) into Assignment(13798) at 2
Insert Assignment(15358) into Some(15360) at 0
Insert GenericString: ;(15359) into Some(15360) at 1
Insert RecordPtAccess(15366) into Binary(15369) at 0
Insert GenericString: ==(15367) into Binary(15369) at 1
Insert Constant: 0(15368) into Binary(15369) at 2
Insert Some(15376) into ExprStatement(15377) at 0
Insert RecordPtAccess(15383) into Binary(15386) at 0
Insert GenericString: ==(15384) into Binary(15386) at 1
Insert Constant: 1(15385) into Binary(15386) at 2
Insert Some(15393) into ExprStatement(15394) at 0
Insert Ident(13637) into Assignment(13657) at 0
Insert GenericString: =(13638) into Assignment(13657) at 1
Insert FunCall(13656) into Assignment(13657) at 2
Move GenericString: err(13635) into Ident(13663) at 0
Insert GenericString: out(13667) into Goto(13668) at 0
Insert Ident(13767) into Unary(13769) at 0
Insert GenericString: *(13768) into Unary(13769) at 1
Insert RecordPtAccess(13779) into RecordAccess(13781) at 0
Insert GenericString: active_speed(13780) into RecordAccess(13781) at 1
Insert GenericString: SPEED_10000(13783) into Ident(13784) at 0
Insert RecordPtAccess(13792) into RecordAccess(13794) at 0
Insert GenericString: active_duplex(13793) into RecordAccess(13794) at 1
Insert GenericString: DUPLEX_FULL(13796) into Ident(13797) at 0
Insert Ident(15352) into Assignment(15358) at 0
Insert GenericString: =(15353) into Assignment(15358) at 1
Insert Unary(15357) into Assignment(15358) at 2
Insert Ident(15364) into RecordPtAccess(15366) at 0
Insert GenericString: port(15365) into RecordPtAccess(15366) at 1
Insert Assignment(15374) into Some(15376) at 0
Insert GenericString: ;(15375) into Some(15376) at 1
Insert Ident(15381) into RecordPtAccess(15383) at 0
Insert GenericString: port(15382) into RecordPtAccess(15383) at 1
Insert Assignment(15391) into Some(15393) at 0
Insert GenericString: ;(15392) into Some(15393) at 1
Update GenericString: da_addr(40677) to addr
Insert GenericString: err(13636) into Ident(13637) at 0
Insert Ident(13640) into FunCall(13656) at 0
Insert GenericList(13655) into FunCall(13656) at 1
Insert GenericString: link_up_p(13766) into Ident(13767) at 0
Insert Ident(13777) into RecordPtAccess(13779) at 0
Insert GenericString: link_config(13778) into RecordPtAccess(13779) at 1
Insert Ident(13790) into RecordPtAccess(13792) at 0
Insert GenericString: link_config(13791) into RecordPtAccess(13792) at 1
Insert GenericString: tp(15351) into Ident(15352) at 0
Insert Ident(15355) into Unary(15357) at 0
Insert GenericString: &(15356) into Unary(15357) at 1
Insert GenericString: np(15363) into Ident(15364) at 0
Insert Ident(15371) into Assignment(15374) at 0
Insert GenericString: =(15372) into Assignment(15374) at 1
Insert Constant: 8(15373) into Assignment(15374) at 2
Insert GenericString: np(15380) into Ident(15381) at 0
Insert Ident(15388) into Assignment(15391) at 0
Insert GenericString: =(15389) into Assignment(15391) at 1
Insert Constant: 12(15390) into Assignment(15391) at 2
Update GenericString: addr(40675) to ha
Insert GenericString: mdio_read(13639) into Ident(13640) at 0
Insert Left(13643) into GenericList(13655) at 0
Insert Left(13648) into GenericList(13655) at 1
Insert Left(13651) into GenericList(13655) at 2
Insert Left(13654) into GenericList(13655) at 3
Insert GenericString: np(13776) into Ident(13777) at 0
Insert GenericString: np(13789) into Ident(13790) at 0
Insert GenericString: phy_template_niu_10g_hotplug(15354) into Ident(15355) at 0
Insert GenericString: phy_addr_off(15370) into Ident(15371) at 0
Insert GenericString: phy_addr_off(15387) into Ident(15388) at 0
Insert Ident(13642) into Left(13643) at 0
Insert RecordPtAccess(13647) into Left(13648) at 0
Insert Ident(13650) into Left(13651) at 0
Insert Ident(13653) into Left(13654) at 0
Insert GenericString: np(13641) into Ident(13642) at 0
Insert Ident(13645) into RecordPtAccess(13647) at 0
Insert GenericString: phy_addr(13646) into RecordPtAccess(13647) at 1
Insert GenericString: BCM8704_PHYXS_DEV_ADDR(13649) into Ident(13650) at 0
Insert GenericString: MII_BMCR(13652) into Ident(13653) at 0
Insert GenericString: np(13644) into Ident(13645) at 0
Delete Binary(12666)
Delete GenericString: out(12667)
Delete Goto(12668)
Delete If(12669)
Delete IfToken(12907)
Delete Ident(12917)
Delete GenericString: =(12918)
Delete Constant: 0(12919)
Delete Assignment(12920)
Delete GenericString: ;(12921)
Delete Some(12922)
Delete ExprStatement(12923)
Delete If(12924)
Delete Ident(13636)
Delete Ident(15657)
Delete Ident(15659)
Delete ReturnExpr(15660)
Delete RecordPtAccess(40593)
Delete Ident(40639)
Delete GenericString: =(40640)
Delete RecordPtAccess(40644)
Delete Assignment(40645)
Delete GenericString: ;(40646)
Delete Some(40647)
Delete ExprStatement(40648)
Delete GenericString: addr(40649)
Delete Ident(40650)
Delete GenericString: ;(40651)
Delete Some(40652)
Delete ExprStatement(40653)
Delete Ident(40655)
Delete GenericString: =(40656)
Delete GenericString: addr(40657)
Delete Ident(40658)
Delete GenericString: next(40659)
Delete RecordPtAccess(40660)
Delete Assignment(40661)
Delete Some(40662)
Delete ExprStatement(40663)
Delete For(40761)
Delete GenericString: dev(43547)
Delete Ident(43548)
Delete GenericString: trans_start(43549)
Delete RecordPtAccess(43550)
Delete GenericString: =(43551)
Delete GenericString: jiffies(43552)
Delete Ident(43553)
Delete Assignment(43554)
Delete GenericString: ;(43555)
Delete Some(43556)
Delete ExprStatement(43557)
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
<suppress files=".*generated-sources.*" checks=".*"/>
<suppress files=".*IndentingXMLStreamWriter.java" checks=".*"/>
<suppress files=".*InfoTree.java" checks=".*"/>
<suppress files=".*LabelDictionary.java" checks=".*"/>
<suppress files=".*RtedAlgorithm.java" checks=".*"/>
<suppress files=".*StreamWriterDelegate.java" checks=".*"/>
</suppressions>
+37
View File
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>gumtree</artifactId>
<groupId>com.github.gumtreediff</groupId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>client.diff</artifactId>
<packaging>jar</packaging>
<name>GumTree Diff Client</name>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.sparkjava/spark-core -->
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>com.github.gumtreediff</groupId>
<artifactId>client</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.nanohttpd</groupId>
<artifactId>nanohttpd-webserver</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.rendersnake</groupId>
<artifactId>rendersnake</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,136 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff;
import com.github.gumtreediff.client.Option;
import com.github.gumtreediff.client.Client;
import com.github.gumtreediff.gen.Generators;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.matchers.Matchers;
import com.github.gumtreediff.tree.TreeContext;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
public abstract class AbstractDiffClient<O extends AbstractDiffClient.Options> extends Client {
protected final O opts;
public static final String SYNTAX = "Syntax: diff [options] baseFile destFile";
private TreeContext src;
private TreeContext dst;
public static class Options implements Option.Context {
public String matcher;
public ArrayList<String> generators = new ArrayList<>();
public String src;
public String dst;
@Override
public Option[] values() {
return new Option[] {
new Option("-m", "The qualified name of the class implementing the matcher.", 1) {
@Override
protected void process(String name, String[] args) {
matcher = args[0];
}
},
new Option("-g", "Preferred generator to use (can be used more than once).", 1) {
@Override
protected void process(String name, String[] args) {
generators.add(args[0]);
}
},
new Option.Help(this) {
@Override
public void process(String name, String[] args) {
System.out.println(SYNTAX);
super.process(name, args);
}
}
};
}
void dump(PrintStream out) {
out.printf("Current path: %s\n", System.getProperty("user.dir"));
out.printf("Diff: %s %s\n", src, dst);
}
}
protected abstract O newOptions();
public AbstractDiffClient(String[] args) {
super(args);
opts = newOptions();
args = Option.processCommandLine(args, opts);
if (args.length < 2)
throw new Option.OptionException("arguments required." + SYNTAX, opts);
opts.src = args[0];
opts.dst = args[1];
if (Option.Verbose.verbose) {
opts.dump(System.out);
}
}
///////////////////
// TODO after this line it should be rewrote in a better way
private Matcher matcher;
protected Matcher matchTrees() {
Matchers matchers = Matchers.getInstance();
if (matcher != null)
return matcher;
matcher = (opts.matcher == null)
? matchers.getMatcher(getSrcTreeContext().getRoot(), getDstTreeContext().getRoot())
: matchers.getMatcher(opts.matcher, getSrcTreeContext().getRoot(), getDstTreeContext().getRoot());
matcher.match();
return matcher;
}
protected TreeContext getSrcTreeContext() {
if (src == null)
src = getTreeContext(opts.src);
return src;
}
protected TreeContext getDstTreeContext() {
if (dst == null)
dst = getTreeContext(opts.dst);
return dst;
}
private TreeContext getTreeContext(String file) {
try {
TreeContext t;
if (opts.generators.isEmpty())
t = Generators.getInstance().getTree(file);
else
t = Generators.getInstance().getTree(opts.generators.get(0), file);
return t;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
@@ -0,0 +1,77 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff;
import com.github.gumtreediff.client.Option;
import com.github.gumtreediff.gen.Registry;
import com.github.gumtreediff.io.TreeIoUtils;
import com.github.gumtreediff.client.Register;
import com.github.gumtreediff.matchers.Matcher;
@Register(name = "axmldiff", description = "Dump annotated xml tree",
priority = Registry.Priority.LOW, options = AbstractDiffClient.Options.class)
public class AnnotatedXmlDiff extends AbstractDiffClient<AnnotatedXmlDiff.Options> {
public AnnotatedXmlDiff(String[] args) {
super(args);
}
static class Options extends AbstractDiffClient.Options {
protected boolean isSrc = true;
@Override
public Option[] values() {
return Option.Context.addValue(super.values(),
new Option("--src", String.format("Dump source tree (default: %s)", isSrc ? "yes" : "no"), 0) {
@Override
protected void process(String name, String[] args) {
isSrc = true;
}
},
new Option("--dst", String.format("Dump destination tree (default: %s)", !isSrc
? "yes" : "no"), 0) {
@Override
protected void process(String name, String[] args) {
isSrc = false;
}
}
);
}
}
@Override
protected Options newOptions() {
return new Options();
}
@Override
public void run() {
Matcher m = matchTrees();
try {
TreeIoUtils.toAnnotatedXml((opts.isSrc)
? getSrcTreeContext()
: getDstTreeContext(), opts.isSrc, m.getMappings()
).writeTo(System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,57 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff;
import com.github.gumtreediff.actions.ActionGenerator;
import com.github.gumtreediff.actions.model.Action;
import com.github.gumtreediff.client.Register;
import com.github.gumtreediff.io.ActionsIoUtils;
import com.github.gumtreediff.matchers.Matcher;
import java.util.List;
@Register(name = "jsondiff", description = "Dump actions in the JSON format",
options = AbstractDiffClient.Options.class)
public class JsonDiff extends AbstractDiffClient<AbstractDiffClient.Options> {
public JsonDiff(String[] args) {
super(args);
}
@Override
protected Options newOptions() {
return new Options();
}
@Override
public void run() {
Matcher m = matchTrees();
ActionGenerator g = new ActionGenerator(getSrcTreeContext().getRoot(),
getDstTreeContext().getRoot(), m.getMappings());
g.generate();
List<Action> actions = g.getActions();
try {
ActionsIoUtils.toJson(getSrcTreeContext(), actions, m.getMappings()).writeTo(System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,141 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff;
import com.github.gumtreediff.actions.ActionGenerator;
import com.github.gumtreediff.actions.model.Action;
import com.github.gumtreediff.client.Option;
import com.github.gumtreediff.client.Register;
import com.github.gumtreediff.io.ActionsIoUtils;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.tree.TreeContext;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
@Register(name = "diff", description = "Dump actions in our textual format",
options = AbstractDiffClient.Options.class)
public class TextDiff extends AbstractDiffClient<TextDiff.Options> {
public TextDiff(String[] args) {
super(args);
if (opts.format == null) {
opts.format = OutputFormat.TEXT;
if (opts.output != null) {
if (opts.output.endsWith(".json"))
opts.format = OutputFormat.JSON;
else if (opts.output.endsWith(".xml"))
opts.format = OutputFormat.XML;
}
}
}
public static class Options extends AbstractDiffClient.Options {
protected OutputFormat format;
protected String output;
@Override
public Option[] values() {
return Option.Context.addValue(super.values(),
new Option("-f", String.format("format: %s", Arrays.toString(OutputFormat.values())), 1) {
@Override
protected void process(String name, String[] args) {
try {
format = OutputFormat.valueOf(args[0].toUpperCase());
} catch (IllegalArgumentException e) {
System.err.printf("No such format '%s', available formats are: %s\n",
args[0].toUpperCase(), Arrays.toString(OutputFormat.values()));
System.exit(-1);
}
}
},
new Option("-o", "output file", 1) {
@Override
protected void process(String name, String[] args) {
output = args[0];
}
}
);
}
@Override
void dump(PrintStream out) {
super.dump(out);
out.printf("format: %s\n", format);
out.printf("output file: %s\n", output == null ? "<Stdout>" : output);
}
}
@Override
protected Options newOptions() {
return new Options();
}
@Override
public void run() {
Matcher m = matchTrees();
ActionGenerator g = new ActionGenerator(getSrcTreeContext().getRoot(),
getDstTreeContext().getRoot(), m.getMappings());
g.generate();
List<Action> actions = g.getActions();
try {
ActionsIoUtils.ActionSerializer serializer = opts.format.getSerializer(
getSrcTreeContext(), actions, m.getMappings());
if (opts.output == null)
serializer.writeTo(System.out);
else
serializer.writeTo(opts.output);
} catch (Exception e) {
e.printStackTrace();
}
}
enum OutputFormat { // TODO make a registry for that also ?
TEXT {
@Override
ActionsIoUtils.ActionSerializer getSerializer(TreeContext sctx, List<Action> actions, MappingStore mappings)
throws IOException {
return ActionsIoUtils.toText(sctx, actions, mappings);
}
},
XML {
@Override
ActionsIoUtils.ActionSerializer getSerializer(TreeContext sctx, List<Action> actions, MappingStore mappings)
throws IOException {
return ActionsIoUtils.toXml(sctx, actions, mappings);
}
},
JSON {
@Override
ActionsIoUtils.ActionSerializer getSerializer(TreeContext sctx, List<Action> actions, MappingStore mappings)
throws IOException {
return ActionsIoUtils.toJson(sctx, actions, mappings);
}
};
abstract ActionsIoUtils.ActionSerializer getSerializer(TreeContext sctx, List<Action> actions,
MappingStore mappings) throws IOException;
}
}
@@ -0,0 +1,204 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.swing;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath;
import com.github.gumtreediff.actions.TreeClassifier;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.actions.RootsClassifier;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeContext;
public class MappingsPanel extends JPanel implements TreeSelectionListener {
private static final long serialVersionUID = 1L;
private TreeContext src;
private TreeContext dst;
private TreeClassifier classifyTrees;
private MappingStore mappings;
private TreePanel panSrc;
private TreePanel panDst;
private JTextArea txtSrc;
private JTextArea txtDst;
private static final Color DEL_COLOR = new Color(190, 0, 0);
private static final Color ADD_COLOR = new Color(0, 158, 0);
private static final Color UPD_COLOR = new Color(189, 162, 0);
//private static final Color MIS_COLOR = new Color(0, 0, 128);
private static final Color MV_COLOR = new Color(128, 0, 128);
public MappingsPanel(String srcPath, String dstPath, TreeContext src, TreeContext dst, Matcher m) {
super(new GridLayout(1, 0));
this.src = src;
this.dst = dst;
this.classifyTrees = new RootsClassifier(src, dst, m);
this.mappings = new MappingStore(m.getMappingSet());
this.panSrc = new TreePanel(this.src, new MappingsCellRenderer(true));
this.panSrc.getJTree().addTreeSelectionListener(this);
this.panDst = new TreePanel(this.dst, new MappingsCellRenderer(false));
this.panDst.getJTree().addTreeSelectionListener(this);
this.txtSrc = new JTextArea();
this.txtDst = new JTextArea();
JPanel top = new JPanel();
top.setLayout(new GridLayout(1, 2));
top.add(panSrc);
top.add(panDst);
JPanel bottom = new JPanel();
bottom.setLayout(new GridLayout(1, 2));
bottom.add(new JScrollPane(txtSrc));
bottom.add(new JScrollPane(txtDst));
JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, top, bottom);
split.setDividerLocation(650);
add(split);
try {
txtSrc.getUI().getEditorKit(txtSrc).read(new FileReader(srcPath), txtSrc.getDocument(), 0);
txtDst.getUI().getEditorKit(txtDst).read(new FileReader(dstPath), txtDst.getDocument(), 0);
} catch (IOException | BadLocationException e) {
e.printStackTrace();
}
setPreferredSize(new Dimension(1024, 768));
openNodes();
}
private void openNodes() {
for (ITree t: classifyTrees.getSrcDelTrees()) openNode(panSrc, t);
for (ITree t: classifyTrees.getDstAddTrees()) openNode(panDst, t);
for (ITree t: classifyTrees.getSrcUpdTrees()) openNode(panSrc, t);
for (ITree t: classifyTrees.getDstUpdTrees()) openNode(panDst, t);
for (ITree t: classifyTrees.getSrcMvTrees()) openNode(panSrc, t);
for (ITree t: classifyTrees.getDstMvTrees()) openNode(panDst, t);
panSrc.getJTree().scrollPathToVisible(new TreePath(panSrc.getTrees().get(src.getRoot()).getPath()));
panDst.getJTree().scrollPathToVisible(new TreePath(panDst.getTrees().get(dst.getRoot()).getPath()));
}
private void openNode(TreePanel p, ITree t) {
DefaultMutableTreeNode n = p.getTrees().get(t);
p.getJTree().scrollPathToVisible(new TreePath(n.getPath()));
}
@Override
public void valueChanged(TreeSelectionEvent e) {
JTree jtree = (JTree) e.getSource();
if (jtree.getSelectionPath() == null) return;
ITree sel = (ITree) ((DefaultMutableTreeNode) jtree.getLastSelectedPathComponent()).getUserObject();
JTextArea selJTextArea = null;
boolean isMapped = false;
ITree match = null;
TreePanel matchTreePanel = null;
JTextArea matchJTextArea = null;
if (jtree == panSrc.getJTree()) {
selJTextArea = txtSrc;
matchTreePanel = panDst;
matchJTextArea = txtDst;
if (mappings.hasSrc(sel)) {
isMapped = true;
match = mappings.getDst(sel);
}
} else {
selJTextArea = txtDst;
matchTreePanel = panSrc;
matchJTextArea = txtSrc;
if (mappings.hasDst(sel)) {
isMapped = true;
match = mappings.getSrc(sel);
}
}
try {
updateJTreeAndJTextArea(sel, selJTextArea, isMapped, match, matchTreePanel, matchJTextArea);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
private void updateJTreeAndJTextArea(ITree sel, JTextArea selJTextArea, boolean isMapped,
ITree match, TreePanel matchTreePanel,
JTextArea matchJTextArea) throws BadLocationException {
selJTextArea.getHighlighter().removeAllHighlights();
selJTextArea.getHighlighter().addHighlight(sel.getPos(), sel.getEndPos(), DefaultHighlighter.DefaultPainter);
selJTextArea.setCaretPosition(sel.getPos());
if (isMapped) {
DefaultMutableTreeNode node = matchTreePanel.getTrees().get(match);
matchTreePanel.getJTree().scrollPathToVisible(new TreePath(node.getPath()));
matchTreePanel.getJTree().setSelectionPath(new TreePath(node.getPath()));
matchJTextArea.getHighlighter().removeAllHighlights();
matchJTextArea.getHighlighter().addHighlight(
match.getPos(), match.getEndPos(), DefaultHighlighter.DefaultPainter);
matchJTextArea.setCaretPosition(match.getPos());
} else {
matchTreePanel.getJTree().clearSelection();
matchJTextArea.getHighlighter().removeAllHighlights();
}
}
private class MappingsCellRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 1L;
private boolean isSrc;
public MappingsCellRenderer(boolean left) {
this.isSrc = left;
}
@Override
public Component getTreeCellRendererComponent(JTree jtree, Object value,
boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(jtree, value, selected, expanded, leaf, row, hasFocus);
ITree tree = (ITree) ((DefaultMutableTreeNode) value).getUserObject();
if (isSrc && classifyTrees.getSrcDelTrees().contains(tree)) setForeground(DEL_COLOR);
else if (!isSrc && classifyTrees.getDstAddTrees().contains(tree)) setForeground(ADD_COLOR);
else if (isSrc && classifyTrees.getSrcUpdTrees().contains(tree)) setForeground(UPD_COLOR);
else if (!isSrc && classifyTrees.getDstUpdTrees().contains(tree)) setForeground(UPD_COLOR);
else if (isSrc && classifyTrees.getSrcMvTrees().contains(tree)) setForeground(MV_COLOR);
else if (!isSrc && classifyTrees.getDstMvTrees().contains(tree)) setForeground(MV_COLOR);
return this;
}
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.swing;
import com.github.gumtreediff.client.Register;
import com.github.gumtreediff.client.diff.AbstractDiffClient;
import com.github.gumtreediff.client.diff.swing.MappingsPanel;
import com.github.gumtreediff.matchers.Matcher;
import javax.swing.*;
@Register(description = "A swing diff client", options = AbstractDiffClient.Options.class)
public final class SwingDiff extends AbstractDiffClient<AbstractDiffClient.Options> {
public SwingDiff(String[] args) {
super(args);
}
@Override
public void run() {
final Matcher matcher = matchTrees();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("GumTree");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MappingsPanel(opts.src, opts.dst, getSrcTreeContext(), getDstTreeContext(), matcher));
frame.pack();
frame.setVisible(true);
}
});
}
@Override
protected AbstractDiffClient.Options newOptions() {
return new AbstractDiffClient.Options();
}
}
@@ -0,0 +1,50 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.swing;
import com.github.gumtreediff.gen.Generators;
import com.github.gumtreediff.tree.TreeContext;
import javax.swing.*;
import java.io.IOException;
public final class SwingTree {
public static void main(String[] args) throws IOException {
final TreeContext t = Generators.getInstance().getTree(args[0]);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShow(t);
}
});
}
private SwingTree() {
}
private static void createAndShow(TreeContext tree) {
JFrame frame = new JFrame("Tree Viewer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TreePanel(tree));
frame.pack();
frame.setVisible(true);
}
}
@@ -0,0 +1,105 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.swing;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeContext;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
public class TreePanel extends JPanel {
private static final long serialVersionUID = 1L;
private JTree jtree;
private TreeContext tree;
private Map<ITree, DefaultMutableTreeNode> trees;
public TreePanel(final TreeContext tree, TreeCellRenderer renderer) {
super(new GridLayout(1, 0));
trees = new HashMap<>();
this.tree = tree;
ITree root = tree.getRoot();
DefaultMutableTreeNode top = new DefaultMutableTreeNode(root);
trees.put(root, top);
for (ITree child: root.getChildren())
createNodes(top, child);
jtree = new JTree(top) {
private static final long serialVersionUID = 1L;
public String convertValueToText(Object value, boolean selected,
boolean expanded, boolean leaf, int row,
boolean hasFocus) {
if (value != null) {
ITree node = ((ITree) ((DefaultMutableTreeNode) value).getUserObject());
return node.toPrettyString(tree);
}
return "";
}
};
jtree.setCellRenderer(renderer);
jtree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
JScrollPane treeView = new JScrollPane(jtree);
Dimension minimumSize = new Dimension(100, 50);
treeView.setMinimumSize(minimumSize);
add(treeView);
}
public TreePanel(TreeContext tree) {
this(tree, new DefaultTreeCellRenderer());
}
public JTree getJTree() {
return jtree;
}
public Map<ITree, DefaultMutableTreeNode> getTrees() {
return trees;
}
public TreeContext getTree() {
return this.tree;
}
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) jtree.getLastSelectedPathComponent();
if (node == null) return;
Object nodeInfo = node.getUserObject();
System.out.println(nodeInfo);
}
private void createNodes(DefaultMutableTreeNode parent, ITree tree) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(tree);
trees.put(tree, node);
parent.add(node);
for (ITree child: tree.getChildren()) createNodes(node, child);
}
}
@@ -0,0 +1,37 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.web;
import org.rendersnake.HtmlCanvas;
import org.rendersnake.Renderable;
import java.io.IOException;
public class BootstrapFooterView implements Renderable {
@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.macros().javascript("/dist/jquery.min.js")
.macros().javascript("/dist/bootstrap.min.js");
}
}
@@ -0,0 +1,44 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.web;
import static org.rendersnake.HtmlAttributesFactory.*;
import java.io.IOException;
import org.rendersnake.HtmlCanvas;
import org.rendersnake.Renderable;
public class BootstrapHeaderView implements Renderable {
@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.head()
.meta(charset("utf8"))
.meta(name("viewport").content("width=device-width, initial-scale=1.0"))
.title().content("GumTree")
.macros().stylesheet("/dist/bootstrap.min.css")
.macros().stylesheet("/dist/gumtree.css")
._head();
}
}
@@ -0,0 +1,102 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.web;
import com.github.gumtreediff.gen.Generators;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.matchers.Matchers;
import com.github.gumtreediff.tree.TreeContext;
import org.rendersnake.DocType;
import org.rendersnake.HtmlCanvas;
import org.rendersnake.Renderable;
import java.io.File;
import java.io.IOException;
import static org.rendersnake.HtmlAttributesFactory.class_;
import static org.rendersnake.HtmlAttributesFactory.lang;
public class DiffView implements Renderable {
private HtmlDiffs diffs;
private File fSrc;
private File fDst;
public DiffView(File fSrc, File fDst) throws IOException {
this.fSrc = fSrc;
this.fDst = fDst;
TreeContext src = Generators.getInstance().getTree(fSrc.getAbsolutePath());
TreeContext dst = Generators.getInstance().getTree(fDst.getAbsolutePath());
Matcher matcher = Matchers.getInstance().getMatcher(src.getRoot(), dst.getRoot());
matcher.match();
diffs = new HtmlDiffs(fSrc, fDst, src, dst, matcher);
diffs.produce();
}
@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.render(DocType.HTML5)
.html(lang("en"))
.render(new BootstrapHeaderView())
.body()
.div(class_("container-fluid"))
.div(class_("row"))
.render(new MenuBar())
._div()
.div(class_("row"))
.div(class_("col-lg-6 max-height"))
.h5().content(fSrc.getName())
.pre(class_("pre max-height")).content(diffs.getSrcDiff(), false)
._div()
.div(class_("col-lg-6 max-height"))
.h5().content(fDst.getName())
.pre(class_("pre max-height")).content(diffs.getDstDiff(), false)
._div()
._div()
._div()
.render(new BootstrapFooterView())
.macros().javascript("/dist/diff.js")
._body()
._html();
}
private static class MenuBar implements Renderable {
@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.div(class_("col-lg-12"))
.div(class_("btn-toolbar pull-right"))
.div(class_("btn-group"))
.a(class_("btn btn-default btn-xs").id("legend").href("#").add("data-toggle", "popover").add("data-html", "true").add("data-placement", "bottom").add("data-content", "<span class=&quot;del&quot;>&nbsp;&nbsp;</span> deleted<br><span class=&quot;add&quot;>&nbsp;&nbsp;</span> added<br><span class=&quot;mv&quot;>&nbsp;&nbsp;</span> moved<br><span class=&quot;upd&quot;>&nbsp;&nbsp;</span> updated<br>", false).add("data-original-title", "Legend").title("Legend").role("button")).content("Legend")
.a(class_("btn btn-default btn-xs").id("shortcuts").href("#").add("data-toggle", "popover").add("data-html", "true").add("data-placement", "bottom").add("data-content", "<b>q</b> quit<br><b>l</b> list<br><b>n</b> next<br><b>t</b> top<br><b>b</b> bottom", false).add("data-original-title", "Shortcuts").title("Shortcuts").role("button")).content("Shortcuts")
._div()
.div(class_("btn-group"))
.a(class_("btn btn-default btn-xs btn-danger").href("/quit")).content("Quit")
._div()
._div()
._div();
}
}
}
@@ -0,0 +1,174 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.web;
import com.github.gumtreediff.utils.Pair;
import com.github.gumtreediff.io.DirectoryComparator;
import org.rendersnake.DocType;
import org.rendersnake.HtmlCanvas;
import org.rendersnake.Renderable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;
import static org.rendersnake.HtmlAttributesFactory.*;
public class DirectoryComparatorView implements Renderable {
private DirectoryComparator comparator;
public DirectoryComparatorView(DirectoryComparator comparator) throws IOException {
this.comparator = comparator;
}
@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.render(DocType.HTML5)
.html(lang("en"))
.render(new BootstrapHeaderView())
.body()
.div(class_("container"))
.div(class_("row"))
.div(class_("col-lg-12"))
.div(class_("panel panel-default"))
.div(class_("panel-heading"))
.h4(class_("panel-title"))
.write("Modified files ")
.span(class_("badge")).content(comparator.getModifiedFiles().size())
._h4()
._div()
.div(class_("panel-body"))
.render_if(new ModifiedFiles(comparator.getModifiedFiles()), comparator.getModifiedFiles().size() > 0)
._div()
._div()
._div()
._div()
.div(class_("row"))
.div(class_("col-lg-6"))
.div(class_("panel panel-default"))
.div(class_("panel-heading"))
.h4(class_("panel-title"))
.write("Deleted files ")
.span(class_("badge")).content(comparator.getDeletedFiles().size())
._h4()
._div()
.div(class_("panel-body"))
.render_if(new AddedOrDeletedFiles(
comparator.getDeletedFiles(), comparator.getSrc(), "danger"),
comparator.getDeletedFiles().size() > 0)
._div()
._div()
._div()
.div(class_("col-lg-6"))
.div(class_("panel panel-default"))
.div(class_("panel-heading"))
.h4(class_("panel-title"))
.write("Added files ")
.span(class_("badge")).content(comparator.getAddedFiles().size())
._h4()
._div()
.div(class_("panel-body"))
.render_if(new AddedOrDeletedFiles(
comparator.getAddedFiles(), comparator.getDst(), "success"),
comparator.getAddedFiles().size() > 0)
._div()
._div()
._div()
._div()
._div()
.render(new BootstrapFooterView())
.macros().javascript("/dist/list.js")
._body()
._html();
}
private class ModifiedFiles implements Renderable {
private List<Pair<File, File>> files;
private ModifiedFiles(List<Pair<File, File>> files) {
this.files = files;
}
@Override
public void renderOn(HtmlCanvas html) throws IOException {
HtmlCanvas tbody = html
.table(class_("table table-striped table-condensed"))
.tbody();
int id = 0;
for (Pair<File, File> file : files) {
tbody
.tr()
.td(class_("col-md-10")).content(comparator.getSrc().relativize(file.getFirst().toPath()).toString())
.td(class_("col-md-2"))
.a(class_("btn btn-primary btn-xs").href("/diff/" + id)).content("diff")
.write(" ")
.a(class_("btn btn-primary btn-xs").href("/mergely/" + id)).content("mergely")
.write(" ")
.a(class_("btn btn-primary btn-xs").href("/script/" + id)).content("script")
._td()
._tr();
id++;
}
tbody
._tbody()
._table();
}
}
private class AddedOrDeletedFiles implements Renderable {
private Set<File> files;
private Path root;
private String tdClass;
private AddedOrDeletedFiles(Set<File> files, Path root, String tdClass) {
this.files = files;
this.root = root;
this.tdClass = tdClass;
}
@Override
public void renderOn(HtmlCanvas html) throws IOException {
HtmlCanvas tbody = html
.table(class_("table table-condensed"))
.tbody();
for (File file : files) {
tbody
.tr()
.td(class_(tdClass)).content(root.relativize(file.toPath()).toString())
._tr();
}
tbody
._tbody()
._table();
}
}
}
@@ -0,0 +1,177 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.web;
import com.github.gumtreediff.actions.RootAndLeavesClassifier;
import com.github.gumtreediff.actions.TreeClassifier;
import com.github.gumtreediff.utils.StringAlgorithms;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeContext;
import gnu.trove.map.TIntIntMap;
import gnu.trove.map.hash.TIntIntHashMap;
import java.io.*;
import java.util.List;
public final class HtmlDiffs {
private static final String SRC_MV_SPAN = "<span class=\"%s\" id=\"move-src-%d\" data-title=\"%s\">";
private static final String DST_MV_SPAN = "<span class=\"%s\" id=\"move-dst-%d\" data-title=\"%s\">";
private static final String ADD_DEL_SPAN = "<span class=\"%s\" data-title=\"%s\">";
private static final String UPD_SPAN = "<span class=\"cupd\">";
private static final String ID_SPAN = "<span class=\"marker\" id=\"mapping-%d\"></span>";
private static final String END_SPAN = "</span>";
private String srcDiff;
private String dstDiff;
private TreeContext src;
private TreeContext dst;
private File fSrc;
private File fDst;
private Matcher matcher;
private MappingStore mappings;
public HtmlDiffs(File fSrc, File fDst, TreeContext src, TreeContext dst, Matcher matcher) {
this.fSrc = fSrc;
this.fDst = fDst;
this.src = src;
this.dst = dst;
this.matcher = matcher;
this.mappings = matcher.getMappings();
}
public void produce() throws IOException {
TreeClassifier c = new RootAndLeavesClassifier(src, dst, matcher);
TIntIntMap mappingIds = new TIntIntHashMap();
int uId = 1;
int mId = 1;
TagIndex ltags = new TagIndex();
for (ITree t: src.getRoot().getTrees()) {
if (c.getSrcMvTrees().contains(t)) {
mappingIds.put(mappings.getDst(t).getId(), mId);
ltags.addStartTag(t.getPos(), String.format(ID_SPAN, uId++));
ltags.addTags(t.getPos(), String.format(
SRC_MV_SPAN, "token mv", mId++, tooltip(src, t)), t.getEndPos(), END_SPAN);
}
if (c.getSrcUpdTrees().contains(t)) {
mappingIds.put(mappings.getDst(t).getId(), mId);
ltags.addStartTag(t.getPos(), String.format(ID_SPAN, uId++));
ltags.addTags(t.getPos(), String.format(
SRC_MV_SPAN, "token upd", mId++, tooltip(src, t)), t.getEndPos(), END_SPAN);
List<int[]> hunks = StringAlgorithms.hunks(t.getLabel(), mappings.getDst(t).getLabel());
for (int[] hunk: hunks)
ltags.addTags(t.getPos() + hunk[0], UPD_SPAN, t.getPos() + hunk[1], END_SPAN);
}
if (c.getSrcDelTrees().contains(t)) {
ltags.addStartTag(t.getPos(), String.format(ID_SPAN, uId++));
ltags.addTags(t.getPos(), String.format(
ADD_DEL_SPAN, "token del", tooltip(src, t)), t.getEndPos(), END_SPAN);
}
}
TagIndex rtags = new TagIndex();
for (ITree t: dst.getRoot().getTrees()) {
if (c.getDstMvTrees().contains(t)) {
int dId = mappingIds.get(t.getId());
rtags.addStartTag(t.getPos(), String.format(ID_SPAN, uId++));
rtags.addTags(t.getPos(), String.format(
DST_MV_SPAN, "token mv", dId, tooltip(dst, t)), t.getEndPos(), END_SPAN);
}
if (c.getDstUpdTrees().contains(t)) {
int dId = mappingIds.get(t.getId());
rtags.addStartTag(t.getPos(), String.format(ID_SPAN, uId++));
rtags.addTags(t.getPos(), String.format(
DST_MV_SPAN, "token upd", dId, tooltip(dst, t)), t.getEndPos(), END_SPAN);
List<int[]> hunks = StringAlgorithms.hunks(mappings.getSrc(t).getLabel(), t.getLabel());
for (int[] hunk: hunks)
rtags.addTags(t.getPos() + hunk[2], UPD_SPAN, t.getPos() + hunk[3], END_SPAN);
}
if (c.getDstAddTrees().contains(t)) {
rtags.addStartTag(t.getPos(), String.format(ID_SPAN, uId++));
rtags.addTags(t.getPos(), String.format(
ADD_DEL_SPAN, "token add", tooltip(dst, t)), t.getEndPos(), END_SPAN);
}
}
StringWriter w1 = new StringWriter();
BufferedReader r = new BufferedReader(new FileReader(fSrc));
int cursor = 0;
while (r.ready()) {
char cr = (char) r.read();
w1.append(ltags.getEndTags(cursor));
w1.append(ltags.getStartTags(cursor));
append(cr, w1);
cursor++;
}
w1.append(ltags.getEndTags(cursor));
r.close();
srcDiff = w1.toString();
StringWriter w2 = new StringWriter();
r = new BufferedReader(new FileReader(fDst));
cursor = 0;
while (r.ready()) {
char cr = (char) r.read();
w2.append(rtags.getEndTags(cursor));
w2.append(rtags.getStartTags(cursor));
append(cr, w2);
cursor++;
}
w2.append(rtags.getEndTags(cursor));
r.close();
dstDiff = w2.toString();
}
public String getSrcDiff() {
return srcDiff;
}
public String getDstDiff() {
return dstDiff;
}
private static String tooltip(TreeContext ctx, ITree t) {
return (t.getParent() != null)
? ctx.getTypeLabel(t.getParent()) + "/" + ctx.getTypeLabel(t) : ctx.getTypeLabel(t);
}
private static void append(char cr, Writer w) throws IOException {
if (cr == '<') w.append("&lt;");
else if (cr == '>') w.append("&gt;");
else if (cr == '&') w.append("&amp;");
else w.append(cr);
}
}
@@ -0,0 +1,65 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.web;
import org.rendersnake.DocType;
import org.rendersnake.HtmlCanvas;
import org.rendersnake.Renderable;
import java.io.IOException;
import static org.rendersnake.HtmlAttributesFactory.*;
public class MergelyView implements Renderable {
private int id;
public MergelyView(int id) throws IOException {
this.id = id;
}
@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.render(DocType.HTML5)
.html(lang("en"))
.head()
.meta(charset("utf8"))
.meta(name("viewport").content("width=device-width, initial-scale=1.0"))
.title().content("GumTree")
.macros().javascript("/dist/jquery.min.js")
.macros().javascript("/dist/codemirror.min.js")
.macros().stylesheet("/dist/codemirror.css")
.macros().javascript("/dist/mergely.min.js")
.macros().javascript("/dist/mergely_shortcuts.js")
.macros().stylesheet("/dist/mergely.css")
.macros().stylesheet("/dist/mergely_custom.css")
._head()
.body()
.div(id("compare"))
._div()
.macros().script("lhs_url = \"/left/" + id + "\";")
.macros().script("rhs_url = \"/right/" + id + "\";")
.macros().javascript("/dist/mergely_ajax.js")
._body()
._html();
}
}
@@ -0,0 +1,93 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.web;
import com.github.gumtreediff.actions.ActionGenerator;
import com.github.gumtreediff.actions.model.Action;
import com.github.gumtreediff.gen.Generators;
import com.github.gumtreediff.io.ActionsIoUtils;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.matchers.Matchers;
import com.github.gumtreediff.tree.TreeContext;
import org.rendersnake.DocType;
import org.rendersnake.HtmlCanvas;
import org.rendersnake.Renderable;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.rendersnake.HtmlAttributesFactory.class_;
import static org.rendersnake.HtmlAttributesFactory.lang;
public class ScriptView implements Renderable {
private final MappingStore mappings;
private final TreeContext src;
private final TreeContext dst;
private File fSrc;
private File fDst;
private List<Action> script;
public ScriptView(File fSrc, File fDst) throws IOException {
this.fSrc = fSrc;
this.fDst = fDst;
src = Generators.getInstance().getTree(fSrc.getAbsolutePath());
dst = Generators.getInstance().getTree(fDst.getAbsolutePath());
Matcher matcher = Matchers.getInstance().getMatcher(src.getRoot(), dst.getRoot());
matcher.match();
mappings = matcher.getMappings();
ActionGenerator g = new ActionGenerator(src.getRoot(), dst.getRoot(), mappings);
g.generate();
this.script = g.getActions();
}
@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.render(DocType.HTML5)
.html(lang("en"))
.render(new BootstrapHeaderView())
.body()
.div(class_("container"))
.div(class_("row"))
.div(class_("col-lg-12"))
.h3()
.write("Script ")
.small().content(String.format("%s -> %s", fSrc.getName(), fDst.getName()))
._h3()
.pre().content(ActionsIoUtils.toText(src, this.script, mappings).toString())
._div()
._div()
._div()
.render(new BootstrapFooterView())
.macros().javascript("/dist/script.js")
._body()
._html();
}
}
@@ -0,0 +1,70 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.web;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TagIndex {
private Map<Integer, List<String>> startTags;
private Map<Integer, List<String>> endTags;
public TagIndex() {
startTags = new HashMap<Integer, List<String>>();
endTags = new HashMap<Integer, List<String>>();
}
public void addTags(int pos, String startTag, int endPos, String endTag) {
addStartTag(pos, startTag);
addEndTag(endPos, endTag);
}
public void addStartTag(int pos, String tag) {
if (!startTags.containsKey(pos)) startTags.put(pos, new ArrayList<String>());
startTags.get(pos).add(tag);
}
public void addEndTag(int pos, String tag) {
if (!endTags.containsKey(pos)) endTags.put(pos, new ArrayList<String>());
endTags.get(pos).add(tag);
}
public String getEndTags(int pos) {
if (!endTags.containsKey(pos)) return "";
StringBuffer b = new StringBuffer();
for (String s: endTags.get(pos)) b.append(s);
return b.toString();
}
public String getStartTags(int pos) {
if (!startTags.containsKey(pos))
return "";
StringBuffer b = new StringBuffer();
for (String s: startTags.get(pos))
b.append(s);
return b.toString();
}
}
@@ -0,0 +1,150 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client.diff.web;
import com.github.gumtreediff.client.Option;
import com.github.gumtreediff.client.Register;
import com.github.gumtreediff.client.diff.AbstractDiffClient;
import com.github.gumtreediff.gen.Registry;
import com.github.gumtreediff.io.DirectoryComparator;
import com.github.gumtreediff.utils.Pair;
import org.rendersnake.HtmlCanvas;
import org.rendersnake.Renderable;
import spark.Spark;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import static spark.Spark.*;
@Register(description = "a web diff client", options = WebDiff.Options.class, priority = Registry.Priority.HIGH)
public class WebDiff extends AbstractDiffClient<WebDiff.Options> {
public WebDiff(String[] args) {
super(args);
}
static class Options extends AbstractDiffClient.Options {
protected int defaultPort = Integer.parseInt(System.getProperty("gumtree.client.web.port", "4567"));
boolean stdin = true;
@Override
public Option[] values() {
return Option.Context.addValue(super.values(),
new Option("--port", String.format("set server port (default to)", defaultPort), 1) {
@Override
protected void process(String name, String[] args) {
int p = Integer.parseInt(args[0]);
if (p > 0)
defaultPort = p;
else
System.err.printf("Invalid port number (%s), using %d\n", args[0], defaultPort);
}
},
new Option("--no-stdin", String.format("Do not listen to stdin"), 0) {
@Override
protected void process(String name, String[] args) {
stdin = false;
}
}
);
}
}
@Override
protected Options newOptions() {
return new Options();
}
@Override
public void run() {
DirectoryComparator comparator = new DirectoryComparator(opts.src, opts.dst);
comparator.compare();
configureSpark(comparator, opts.defaultPort);
Spark.awaitInitialization();
System.out.println(String.format("Starting server: %s:%d", "http://127.0.0.1", opts.defaultPort));
}
public static void configureSpark(final DirectoryComparator comparator, int port) {
port(port);
staticFiles.location("/web/");
get("/", (request, response) -> {
if (comparator.isDirMode())
response.redirect("/list");
else
response.redirect("/diff/0");
return "";
});
get("/list", (request, response) -> {
Renderable view = new DirectoryComparatorView(comparator);
return render(view);
});
get("/diff/:id", (request, response) -> {
int id = Integer.parseInt(request.params(":id"));
Pair<File, File> pair = comparator.getModifiedFiles().get(id);
Renderable view = new DiffView(pair.getFirst(), pair.getSecond());
return render(view);
});
get("/mergely/:id", (request, response) -> {
int id = Integer.parseInt(request.params(":id"));
Renderable view = new MergelyView(id);
return render(view);
});
get("/left/:id", (request, response) -> {
int id = Integer.parseInt(request.params(":id"));
Pair<File, File> pair = comparator.getModifiedFiles().get(id);
return readFile(pair.getFirst().getAbsolutePath(), Charset.defaultCharset());
});
get("/right/:id", (request, response) -> {
int id = Integer.parseInt(request.params(":id"));
Pair<File, File> pair = comparator.getModifiedFiles().get(id);
return readFile(pair.getSecond().getAbsolutePath(), Charset.defaultCharset());
});
get("/script/:id", (request, response) -> {
int id = Integer.parseInt(request.params(":id"));
Pair<File, File> pair = comparator.getModifiedFiles().get(id);
Renderable view = new ScriptView(pair.getFirst(), pair.getSecond());
return render(view);
});
get("/quit", (request, response) -> {
System.exit(0);
return "";
});
}
private static String render(Renderable r) {
HtmlCanvas c = new HtmlCanvas();
try {
r.renderOn(c);
} catch (IOException e) {
e.printStackTrace();
}
return c.toHtml();
}
private static String readFile(String path, Charset encoding) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,334 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
color: black;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror-cursor {
border-left: 1px solid black;
border-right: none;
width: 0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
}
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-animate-fat-cursor {
width: auto;
border: 0;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
background-color: #7e7;
}
@-moz-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@-webkit-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror-overwrite .CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-ruler {
border-left: 1px solid #ccc;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
.CodeMirror-composing { border-bottom: 2px solid; }
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
position: relative;
overflow: hidden;
background: white;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
margin-bottom: -30px;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-cursor { position: absolute; }
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }
File diff suppressed because one or more lines are too long
@@ -0,0 +1,120 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
currentMapping = 0;
if (typeof String.prototype.startsWith != 'function') {
String.prototype.startsWith = function (str){
return this.slice(0, str.length) == str;
};
}
function getMappedElement(eltId) {
if (eltId.startsWith("move-src")) {
return eltId.replace("src","dst");
}
else {
return eltId.replace("dst","src");
}
}
function nextMapping() {
if (currentMapping == 0) {
currentMapping = 1;
return "#mapping-" + currentMapping.toString();
} else {
currentMapping++;
if ($("#mapping-" + currentMapping.toString()).length > 0) {
return "#mapping-" + currentMapping.toString();
} else {
currentMapping = 1;
return "#mapping-" + currentMapping.toString();
}
}
}
function isSrc(eltId) {
return eltId.startsWith("move-src");
}
$(function() {
$("#legend").popover();
$("#shortcuts").popover();
// shortcuts
$("body").keypress(function (event) {
switch(event.which) {
case 110:
var mapping = nextMapping();
$('html, body').animate({scrollTop: $(mapping).offset().top - 200}, 100);
break;
case 116:
$('html, body').animate({scrollTop: 0}, 100);
break;
case 98:
$("html, body").animate({ scrollTop: $(document).height() }, 100);
break;
case 113:
window.location = "/quit";
break;
case 108:
window.location = "/list";
break;
}
});
// highlight
$("span.mv.token, span.token.upd").click(function(event) {
if ($(this).hasClass("selected")) {
$("span.mv.token, span.token.upd").removeClass("selected");
} else {
$("span.mv.token, span.token.upd").removeClass("selected");
var eltId = $(this).attr("id");
var refEltId = getMappedElement(eltId);
$("#" + refEltId).addClass("selected");
$(this).addClass("selected");
var sel = "#dst";
if (isSrc(refEltId))
var sel = "#src";
$div = $(sel);
$span = $("#" + refEltId);
}
event.stopPropagation();
});
$("span.add.token, span.token.del").click(function(event) {
$("span.mv.token, span.token.upd").removeClass("selected");
event.stopPropagation();
});
// tooltip
$("span.token").hover(
function (event) {
$(this).tooltip('show');
event.stopPropagation();
},
function (event) {
$(this).tooltip('hide');
event.stopPropagation();
}
);
});
@@ -0,0 +1,93 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
.add {
border: 1px solid black;
background-color: MediumSeaGreen;
}
.del {
border: 1px solid black;
background-color: DarkSalmon;
}
.mv {
border: 1px solid black;
background-color: Lavender;
}
.upd {
border: 1px solid black;
background-color: RosyBrown;
font-weight: bold;
}
.cupd {
font-weight: normal;
color: DimGray;
}
.selected {
background-color: Gold;
}
.marker {
margin: 0;
padding: 0;
}
.container {
margin-right: auto;
margin-left: auto;
width: 100%;
}
.scrollable {
overflow: scroll;
}
.no-overflow {
overflow: hidden;
}
body, html {
height: 100%;
margin: 0px;
padding: 0px;
}
div {
margin: 0px;
padding: 0px;
}
.max-height {
height: 100%;
}
.pre {
margin: 0px;
padding: 0px;
font-size: 10pt;
color: black;
background-color: white;
border-color: black;
font-family: "Inconsolata", "Consolas", "Liberation Sans Regular", "DejaVu Sans Mono", monospace;
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,31 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
$(function() {
// shortcut
$("body").keypress(function (event) {
switch (event.which) {
case 113:
window.location = "/quit";
break;
}
});
});
@@ -0,0 +1,50 @@
/**
* Copyright (c) 2016 by Jamie Peabody, http://www.mergely.com
* All rights reserved.
* Version: 3.4.3 2016-09-07
*/
/* required */
.mergely-column textarea { width: 80px; height: 200px; }
.mergely-column { float: left; }
.mergely-margin { float: left; }
.mergely-canvas { float: left; width: 28px; }
/* resizeable */
.mergely-resizer { width: 100%; height: 100%; }
/* style configuration */
.mergely-column { border: 1px solid #ccc; }
.mergely-active { border: 1px solid #a3d1ff; }
.mergely.a,.mergely.d,.mergely.c { color: #000; }
.mergely.a.rhs.start { border-top: 1px solid #a3d1ff; }
.mergely.a.lhs.start.end,
.mergely.a.rhs.end { border-bottom: 1px solid #a3d1ff; }
.mergely.a.rhs { background-color: #ddeeff; }
.mergely.a.lhs.start.end.first { border-bottom: 0; border-top: 1px solid #a3d1ff; }
.mergely.d.lhs { background-color: #ffe9e9; }
.mergely.d.lhs.end,
.mergely.d.rhs.start.end { border-bottom: 1px solid #f8e8e8; }
.mergely.d.rhs.start.end.first { border-bottom: 0; border-top: 1px solid #f8e8e8; }
.mergely.d.lhs.start { border-top: 1px solid #f8e8e8; }
.mergely.c.lhs,
.mergely.c.rhs { background-color: #fafafa; }
.mergely.c.lhs.start,
.mergely.c.rhs.start { border-top: 1px solid #a3a3a3; }
.mergely.c.lhs.end,
.mergely.c.rhs.end { border-bottom: 1px solid #a3a3a3; }
.mergely.ch.a.rhs { background-color: #ddeeff; }
.mergely.ch.d.lhs { background-color: #ffe9e9; text-decoration: line-through; color: red !important; }
.mergely.current.start { border-top: 1px solid #000 !important; }
.mergely.current.end { border-bottom: 1px solid #000 !important; }
.mergely.current.lhs.a.start.end,
.mergely.current.rhs.d.start.end { border-top: 0 !important; }
.mergely.current.CodeMirror-linenumber { color: #F9F9F9; font-weight: bold; background-color: #777; }
.CodeMirror-linenumber { cursor: pointer; }
.CodeMirror-code { color: #717171; }
File diff suppressed because one or more lines are too long
@@ -0,0 +1,19 @@
$(document).ready(function () {
$('#compare').mergely({
editor_width: 'calc(50% - 25px)',
editor_height: 'calc(100% - 25px)',
cmsettings: {
readOnly: true,
lineNumbers: true,
lineWrapping: true
}
});
$.get(lhs_url, function(data) {
$('#compare').mergely('lhs', data);
});
$.get(rhs_url, function(data) {
$('#compare').mergely('rhs', data);
});
});
@@ -0,0 +1,8 @@
html, body, #compare, .CodeMirror {
height: 100%;
}
.CodeMirror pre {
font-family: "Inconsolata", "Consolas", "Liberation Sans Regular", "DejaVu Sans Mono", monospace;
font-size: 10pt;
}
@@ -0,0 +1,31 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2016 Floréal Morandat <florealm@gmail.com>
*/
$(function(){
$("body").keypress(function (event) {
switch (event.which) {
case 113:
window.location = "/quit";
break;
case 108:
window.location = "/list";
break;
}
});
});
@@ -0,0 +1,40 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
$(function(){
$("#infos").popover();
$("body").keypress(function (event) {
switch (event.which) {
case 116:
$('html, body').animate({scrollTop: 0}, 100);
break;
case 98:
$("html, body").animate({ scrollTop: $(document).height() }, 100);
break;
case 113:
window.location = "/quit";
break;
case 108:
window.location = "/list";
break;
}
});
});
+24
View File
@@ -0,0 +1,24 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.gumtreediff</groupId>
<artifactId>gumtree</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>client</artifactId>
<packaging>jar</packaging>
<name>GumTree Client Module</name>
<dependencies>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.9-RC1</version>
</dependency>
<dependency>
<groupId>com.github.gumtreediff</groupId>
<artifactId>core</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,28 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client;
public abstract class Client {
public Client(String[] args) {}
public abstract void run() throws Exception;
}
@@ -0,0 +1,62 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client;
import com.github.gumtreediff.gen.Registry;
public class Clients extends Registry<String, Client, Register> {
private static Clients registry;
public static Clients getInstance() {
if (registry == null)
registry = new Clients();
return registry;
}
protected String getName(Register annotation, Class<? extends Client> clazz) {
String name = annotation.name();
if (Register.no_value.equals(name))
name = clazz.getSimpleName().toLowerCase();
return name;
}
@Override
protected Entry newEntry(Class<? extends Client> clazz, Register annotation) {
String name = annotation.name().equals(Register.no_value)
? clazz.getSimpleName() : annotation.name();
return new Entry(name.toLowerCase(), clazz, defaultFactory(clazz, String[].class), annotation.priority()) {
@Override
protected boolean handle(String key) {
return id.equalsIgnoreCase(key);
}
final String description;
{
description = annotation.description();
}
@Override
public String toString() {
return String.format("%s: %s", id, description);
}
};
}
}
@@ -0,0 +1,97 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client;
import com.github.gumtreediff.gen.Generators;
import com.github.gumtreediff.matchers.Matchers;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collection;
@Register(description = "List things (matchers, generators, properties, ...)")
public class List extends Client {
public static final String SYNTAX = "Syntax: list " + Arrays.toString(Listable.values());
private final Listable item;
public List(String[] args) {
super(args);
if (args.length == 0)
throw new Option.OptionException(SYNTAX);
try {
Listable listable = Listable.valueOf(args[0].toUpperCase());
item = listable;
} catch (Exception e) {
throw new Option.OptionException(SYNTAX);
}
}
@Override
public void run() throws IOException {
item.print(System.out);
}
enum Listable {
MATCHERS {
@Override
Collection<?> list() {
return Matchers.getInstance().getEntries();
}
},
GENERATORS {
@Override
Collection<?> list() {
return Generators.getInstance().getEntries();
}
},
PROPERTIES {
@Override
Collection<?> list() {
return Arrays.asList(properties);
}
},
CLIENTS {
@Override
Collection<?> list() {
return Clients.getInstance().getEntries();
}
};
void print(PrintStream out) {
this.list().forEach(item -> out.println(item));
}
abstract Collection<?> list();
}
// This list is generated using (manually) list_properties (it is only an heuristic), some properties may be missing
public static final String[] properties = new String[] {
"gumtree.client.experimental (com.github.gumtreediff.client.Run)",
"gumtree.client.web.port (com.github.gumtreediff.client.diff.WebDiff)",
"gumtree.generator.experimental (com.github.gumtreediff.gen.TreeGeneratorRegistry)",
"line.separator (com.github.gumtreediff.io.IndentingXMLStreamWriter)",
"user.dir (com.github.gumtreediff.client.diff.AbstractDiffClient)"
};
}
@@ -0,0 +1,177 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client;
import java.io.PrintStream;
import java.util.ArrayList;
public abstract class Option {
final String description;
final String key;
final int paramCount;
public interface Context {
Option[] values();
static Option[] addValue(Option[] options, Option... newOptions) {
Option[] nopts = new Option[options.length + newOptions.length];
System.arraycopy(options, 0, nopts, 0, options.length);
System.arraycopy(newOptions, 0, nopts, options.length, newOptions.length);
return nopts;
}
}
@SuppressWarnings("serial")
public static class OptionException extends RuntimeException {
final Context context;
public OptionException(String msg, Context ctx) {
super(msg);
context = ctx;
}
public OptionException(String msg) {
this(msg, null);
}
public Context getContext() {
return context;
}
}
public Option(String key, String text) {
this(key, text, 0);
}
public Option(String key, String text, int params) {
this.key = key;
this.description = text;
this.paramCount = params;
}
public static String[] processCommandLine(String[] args, Context context) {
return processCommandLine(args, context.values(), context);
}
public static String[] processCommandLine(String[] args, Option[] availableOptions, Context ctx) {
ArrayList<String> todo = new ArrayList<>(args.length);
for (int i = 0; i < args.length; i++) {
String arg = args[i];
boolean found = false;
for (int j = 0; j < availableOptions.length && !found; j++) {
if (availableOptions[j].hasOption(arg)) {
int nbParams = availableOptions[j].paramCount;
String[] opts = new String[nbParams];
int currentParam = 0;
while (currentParam < nbParams) {
try {
opts[currentParam++] = args[++i];
} catch (ArrayIndexOutOfBoundsException e) {
throw new OptionException(String.format(
"Option '%s' expects more parameters, using null", arg), ctx);
}
}
availableOptions[j].process(arg, opts);
found = true;
}
}
if (!found) {
todo.add(arg);
}
}
String[] rest = new String[todo.size()];
todo.toArray(rest);
return rest;
}
protected boolean hasOption(String arg) {
return key.equals(arg);
}
protected abstract void process(String name, String[] args);
public String formatHelpText() {
return String.format("%s%s\t%s", key, (paramCount > 0 ? " <" + paramCount + ">" : ""), description);
}
public String toString() {
return key;
}
public static void displayOptions(PrintStream out, Context ctx) {
for (Option opt : ctx.values()) {
out.println(opt.formatHelpText());
}
}
public static class Help extends Option {
protected final Context context;
public Help(final Context ctx) {
super("--help", "Display help (this screen)");
context = ctx;
}
@Override
public void process(String name, String[] args) {
displayOptions(System.out, context);
System.exit(0);
}
}
public static class Text extends Option {
public Text(String text) {
super("", text);
}
@Override
public boolean hasOption(String opt) {
return false;
}
@Override
protected void process(String name, String[] args) {}
@Override
public String formatHelpText() {
return description;
}
}
public static class Verbose extends Option {
public static boolean verbose = false;
public Verbose() {
super("-v", "Verbose mode");
}
@Override
public boolean hasOption(String opt) {
return super.hasOption(opt) || opt.equals("--verbose");
}
@Override
protected void process(String name, String[] opts) {
verbose = true;
}
}
}
@@ -0,0 +1,47 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client;
import com.github.gumtreediff.gen.Registry;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Register {
String name() default no_value;
String description() default "";
int priority() default Registry.Priority.MEDIUM;
// FIXME currently unused, will be useful only for help purpose
Class<? extends Option.Context> options() default NoOption.class;
String no_value = "";
class NoOption implements Option.Context {
@Override
public Option[] values() {
return new Option[]{};
}
}
}
@@ -0,0 +1,141 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client;
import com.github.gumtreediff.gen.Generators;
import com.github.gumtreediff.gen.Registry;
import com.github.gumtreediff.gen.TreeGenerator;
import org.reflections.Reflections;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
public class Run {
public static class Options implements Option.Context {
@Override
public Option[] values() {
return new Option[]{
new Option("-c", "Set global property (-c property value). "
+ "Properties do not need to be prefixed by gumtree.", 2) {
@Override
protected void process(String name, String[] args) {
String key = args[0].startsWith("gumtree.") ? args[0] : "gumtree." + args[0];
System.setProperty(key, args[1]);
}
},
new Option.Verbose(),
new Help(this)
};
}
}
public static void initGenerators() {
Reflections reflections = new Reflections("com.github.gumtreediff.gen");
reflections.getSubTypesOf(TreeGenerator.class).forEach(
gen -> {
com.github.gumtreediff.gen.Register a =
gen.getAnnotation(com.github.gumtreediff.gen.Register.class);
if (a != null)
Generators.getInstance().install(gen, a);
});
}
public static void initClients() {
Reflections reflections = new Reflections("com.github.gumtreediff.client");
reflections.getSubTypesOf(Client.class).forEach(
cli -> {
com.github.gumtreediff.client.Register a =
cli.getAnnotation(com.github.gumtreediff.client.Register.class);
if (a != null)
Clients.getInstance().install(cli, a);
});
}
static {
initGenerators();
}
public static void startClient(String name, Registry.Factory<? extends Client> client, String[] args) {
try {
Client inst = client.newInstance(new Object[]{args});
try {
inst.run();
} catch (Exception e) {
System.err.printf("** Error while running client %s: %s\n", name, e);
}
} catch (InvocationTargetException e) {
System.err.printf("** Error while parsing option for %s:\n%s\n", name, e.getCause());
} catch (InstantiationException | IllegalAccessException e) {
System.err.printf("Can't instantiate client: '%s'\n%s\n", name, e);
e.printStackTrace();
}
}
public static void main(String[] args) {
Options opts = new Options();
args = Option.processCommandLine(args, opts);
initClients();
Registry.Factory<? extends Client> client;
if (args.length == 0) {
System.err.println("** No command given.");
displayHelp(System.err, opts);
} else if ((client = Clients.getInstance().getFactory(args[0])) == null) {
System.err.printf("** Unknown sub-command '%s'.\n", args[0]);
displayHelp(System.err, opts);
} else {
String[] a = new String[args.length - 1];
System.arraycopy(args, 1, a, 0, a.length);
startClient(args[0], client, a);
}
}
public static void displayHelp(PrintStream out, Option.Context ctx) {
out.println("Available Options:");
Option.displayOptions(out, ctx);
out.println("");
listCommand(out);
}
@SuppressWarnings("rawtypes")
public static void listCommand(PrintStream out) {
out.println("Available Commands:");
for (Registry.Entry cmd: Clients.getInstance().getEntries())
out.println("* " + cmd);
}
static class Help extends Option.Help {
public Help(Context ctx) {
super(ctx);
}
@Override
public void process(String name, String[] args) {
displayHelp(System.out, context);
System.exit(0);
}
}
}
@@ -0,0 +1,129 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.client;
import com.github.gumtreediff.io.TreeIoUtils;
import com.github.gumtreediff.gen.Generators;
import com.github.gumtreediff.tree.TreeContext;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.util.Arrays;
@Register(name = "parse", description = "Parse file and dump result")
public class Serializer extends Client {
public static final String SYNTAX = "Syntax: parse [options] file ...";
static class Options implements Option.Context {
protected OutputFormat format = OutputFormat.JSON;
protected String output = null;
protected String[] files;
@Override
public Option[] values() {
return new Option[]{
new Option("-f", "Output format " + Arrays.toString(OutputFormat.values()), 1) {
@Override
protected void process(String name, String[] args) {
OutputFormat o = OutputFormat.valueOf(args[0].toUpperCase());
if (o != null)
format = o;
else
System.err.println("Invalid output type: " + args[0]);
}
},
new Option("-o", "Output filename (or directory if more than one file), defaults to stdout", 1) {
@Override
protected void process(String name, String[] args) {
}
}
};
}
}
enum OutputFormat {
JSON {
@Override
TreeIoUtils.TreeSerializer getSerializer(TreeContext ctx) {
return TreeIoUtils.toJson(ctx);
}
},
XML {
@Override
TreeIoUtils.TreeSerializer getSerializer(TreeContext ctx) {
return TreeIoUtils.toCompactXml(ctx);
}
},
FULLXML {
@Override
TreeIoUtils.TreeSerializer getSerializer(TreeContext ctx) {
return TreeIoUtils.toXml(ctx);
}
},
DOT {
@Override
TreeIoUtils.TreeSerializer getSerializer(TreeContext ctx) {
return TreeIoUtils.toDot(ctx);
}
},
LISP {
@Override
TreeIoUtils.TreeSerializer getSerializer(TreeContext ctx) {
return TreeIoUtils.toLisp(ctx);
}
};
abstract TreeIoUtils.TreeSerializer getSerializer(TreeContext ctx);
}
Options opts = new Options();
public Serializer(String[] args) {
super(args);
args = Option.processCommandLine(args, opts);
if (args.length == 0)
throw new Option.OptionException(SYNTAX);
opts.files = args;
}
@Override
public void run() throws IOException {
final boolean multiple = opts.files.length > 1;
if (multiple && opts.output != null)
Files.createDirectories(FileSystems.getDefault().getPath(opts.output));
for (String file : opts.files) {
try {
TreeContext tc = Generators.getInstance().getTree(file);
opts.format.getSerializer(tc).writeTo(opts.output == null
? System.out
: new FileOutputStream(opts.output));
} catch (Exception e) {
System.err.println(e);
}
}
}
}
@@ -0,0 +1,27 @@
pdf()
files <- dir(pattern="metrics.*csv")
s_script <- vector(mode="integer")
s_ins <- vector(mode="integer")
s_del <- vector(mode="integer")
s_up <- vector(mode="integer")
s_mov <- vector(mode="integer")
t_total <- vector(mode="integer")
for (file in files) {
d <- read.csv(file, header=T, sep=";")
length(d[[3]])
s_script <- cbind(s_script, d[[3]])
s_ins <- cbind(s_ins, d[[3]])
s_del <- cbind(s_del, d[[4]])
s_up <- cbind(s_up, d[[5]])
s_mov <- cbind(s_mov, d[[6]])
t_total <- cbind(t_total, d[[11]])
}
boxplot(s_script, main="Edit script size")
boxplot(s_ins, main="Insert actions")
boxplot(s_del, main="Delete actions")
boxplot(s_up, main="Update actions")
boxplot(s_mov, main="Move actions")
boxplot(t_total, main="Total time")
@@ -0,0 +1,25 @@
#!/bin/sh
#
# This file is part of GumTree.
#
# GumTree is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# GumTree 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with GumTree. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
# Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
#
find . -name '*.java' | xargs grep -o 'System.getProperty.*'|
grep -v '^./samples' | grep -o 'fr/labri.gumtree.*'|
sed 's/System.getProperty("\([^"]*\)".*/\1/' | tr / . |
sed 's/\(.*\).java:\(.*\)/"\2 (\1)",/' | sort -u
+27
View File
@@ -0,0 +1,27 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gumtree</artifactId>
<groupId>com.github.gumtreediff</groupId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>core</artifactId>
<name>GumTree Core Module</name>
<dependencies>
<dependency>
<groupId>com.github.mpkorstanje</groupId>
<artifactId>simmetrics-core</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>net.sf.trove4j</groupId>
<artifactId>trove4j</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,263 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions;
import com.github.gumtreediff.actions.model.*;
import com.github.gumtreediff.matchers.Mapping;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.tree.AbstractTree;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeUtils;
import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ActionGenerator {
private ITree origSrc;
private ITree newSrc;
private ITree origDst;
private MappingStore origMappings;
private MappingStore newMappings;
private Set<ITree> dstInOrder;
private Set<ITree> srcInOrder;
private int lastId;
private List<Action> actions;
private TIntObjectMap<ITree> origSrcTrees;
private TIntObjectMap<ITree> cpySrcTrees;
public ActionGenerator(ITree src, ITree dst, MappingStore mappings) {
this.origSrc = src;
this.newSrc = this.origSrc.deepCopy();
this.origDst = dst;
origSrcTrees = new TIntObjectHashMap<>();
for (ITree t: origSrc.getTrees())
origSrcTrees.put(t.getId(), t);
cpySrcTrees = new TIntObjectHashMap<>();
for (ITree t: newSrc.getTrees())
cpySrcTrees.put(t.getId(), t);
origMappings = new MappingStore();
for (Mapping m: mappings)
this.origMappings.link(cpySrcTrees.get(m.getFirst().getId()), m.getSecond());
this.newMappings = origMappings.copy();
}
public List<Action> getActions() {
return actions;
}
public List<Action> generate() {
ITree srcFakeRoot = new AbstractTree.FakeTree(newSrc);
ITree dstFakeRoot = new AbstractTree.FakeTree(origDst);
newSrc.setParent(srcFakeRoot);
origDst.setParent(dstFakeRoot);
actions = new ArrayList<>();
dstInOrder = new HashSet<>();
srcInOrder = new HashSet<>();
lastId = newSrc.getSize() + 1;
newMappings.link(srcFakeRoot, dstFakeRoot);
List<ITree> bfsDst = TreeUtils.breadthFirst(origDst);
for (ITree x: bfsDst) {
ITree w = null;
ITree y = x.getParent();
ITree z = newMappings.getSrc(y);
if (!newMappings.hasDst(x)) {
int k = findPos(x);
// Insertion case : insert new node.
w = new AbstractTree.FakeTree();
w.setId(newId());
// In order to use the real nodes from the second tree, we
// furnish x instead of w and fake that x has the newly
// generated ID.
Action ins = new Insert(x, origSrcTrees.get(z.getId()), k);
actions.add(ins);
//System.out.println(ins);
origSrcTrees.put(w.getId(), x);
newMappings.link(w, x);
z.getChildren().add(k, w);
w.setParent(z);
} else {
w = newMappings.getSrc(x);
if (!x.equals(origDst)) { // TODO => x != origDst // Case of the root
ITree v = w.getParent();
if (!w.getLabel().equals(x.getLabel())) {
actions.add(new Update(origSrcTrees.get(w.getId()), x));
w.setLabel(x.getLabel());
}
if (!z.equals(v)) {
int k = findPos(x);
// Action mv = new Move(origSrcTrees.get(w.getId()), origSrcTrees.get(z.getId()), k);
Action mv = new Move(origSrcTrees.get(w.getId()), origSrcTrees.get(z.getId()), x, k);
actions.add(mv);
//System.out.println(mv);
int oldk = w.positionInParent();
z.getChildren().add(k, w);
w.getParent().getChildren().remove(oldk);
w.setParent(z);
}
}
}
//FIXME not sure why :D
srcInOrder.add(w);
dstInOrder.add(x);
alignChildren(w, x);
}
for (ITree w : newSrc.postOrder()) {
if (!newMappings.hasSrc(w)) {
actions.add(new Delete(origSrcTrees.get(w.getId())));
//w.getParent().getChildren().remove(w);
}
}
//FIXME should ensure isomorphism.
return actions;
}
private void alignChildren(ITree w, ITree x) {
srcInOrder.removeAll(w.getChildren());
dstInOrder.removeAll(x.getChildren());
List<ITree> s1 = new ArrayList<>();
for (ITree c: w.getChildren())
if (newMappings.hasSrc(c))
if (x.getChildren().contains(newMappings.getDst(c)))
s1.add(c);
List<ITree> s2 = new ArrayList<>();
for (ITree c: x.getChildren())
if (newMappings.hasDst(c))
if (w.getChildren().contains(newMappings.getSrc(c)))
s2.add(c);
List<Mapping> lcs = lcs(s1, s2);
for (Mapping m : lcs) {
srcInOrder.add(m.getFirst());
dstInOrder.add(m.getSecond());
}
for (ITree a : s1) {
for (ITree b: s2 ) {
if (origMappings.has(a, b)) {
if (!lcs.contains(new Mapping(a, b))) {
int k = findPos(b);
// Action mv = new Move(origSrcTrees.get(a.getId()), origSrcTrees.get(w.getId()), k);
Action mv = new Move(origSrcTrees.get(a.getId()), origSrcTrees.get(w.getId()), b, k);
actions.add(mv);
//System.out.println(mv);
int oldk = a.positionInParent();
w.getChildren().add(k, a);
if (k < oldk ) // FIXME this is an ugly way to patch the index
oldk ++;
a.getParent().getChildren().remove(oldk);
a.setParent(w);
srcInOrder.add(a);
dstInOrder.add(b);
}
}
}
}
}
private int findPos(ITree x) {
ITree y = x.getParent();
List<ITree> siblings = y.getChildren();
for (ITree c : siblings) {
if (dstInOrder.contains(c)) {
if (c.equals(x)) return 0;
else break;
}
}
int xpos = x.positionInParent();
ITree v = null;
for (int i = 0; i < xpos; i++) {
ITree c = siblings.get(i);
if (dstInOrder.contains(c)) v = c;
}
//if (v == null) throw new RuntimeException("No rightmost sibling in order");
if (v == null) return 0;
ITree u = newMappings.getSrc(v);
// siblings = u.getParent().getChildren();
// int upos = siblings.indexOf(u);
int upos = u.positionInParent();
// int r = 0;
// for (int i = 0; i <= upos; i++)
// if (srcInOrder.contains(siblings.get(i))) r++;
return upos + 1;
}
private int newId() {
return ++lastId;
}
private List<Mapping> lcs(List<ITree> x, List<ITree> y) {
int m = x.size();
int n = y.size();
List<Mapping> lcs = new ArrayList<>();
int[][] opt = new int[m + 1][n + 1];
for (int i = m - 1; i >= 0; i--) {
for (int j = n - 1; j >= 0; j--) {
if (newMappings.getSrc(y.get(j)).equals(x.get(i))) opt[i][j] = opt[i + 1][j + 1] + 1;
else opt[i][j] = Math.max(opt[i + 1][j], opt[i][j + 1]);
}
}
int i = 0, j = 0;
while (i < m && j < n) {
if (newMappings.getSrc(y.get(j)).equals(x.get(i))) {
lcs.add(new Mapping(x.get(i), y.get(j)));
i++;
j++;
} else if (opt[i + 1][j] >= opt[i][j + 1]) i++;
else j++;
}
return lcs;
}
}
@@ -0,0 +1,50 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions;
import com.github.gumtreediff.actions.model.*;
import com.github.gumtreediff.tree.TreeContext;
import java.util.List;
public class ActionUtil {
private ActionUtil() {}
public static TreeContext apply(TreeContext context, List<Action> actions) {
for (Action a: actions) {
if (a instanceof Insert) {
Insert action = ((Insert) a);
action.getParent().insertChild(action.getNode(), action.getPosition());
} else if (a instanceof Update) {
Update action = ((Update) a);
action.getNode().setLabel(action.getValue());
} else if (a instanceof Move) {
Move action = ((Move) a);
action.getNode().getParent().getChildren().remove(action.getNode());
action.getParent().insertChild(action.getNode(), action.getPosition());
} else if (a instanceof Delete) {
Delete action = ((Delete) a);
action.getNode().getParent().getChildren().remove(action.getNode());
} else throw new RuntimeException("No such action: " + a );
}
return context;
}
}
@@ -0,0 +1,71 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions;
import java.util.List;
import java.util.Set;
import com.github.gumtreediff.actions.model.Delete;
import com.github.gumtreediff.actions.model.Update;
import com.github.gumtreediff.actions.model.Action;
import com.github.gumtreediff.actions.model.Insert;
import com.github.gumtreediff.actions.model.Move;
import com.github.gumtreediff.matchers.Mapping;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeContext;
public class LeavesClassifier extends TreeClassifier {
public LeavesClassifier(TreeContext src, TreeContext dst, Set<Mapping> rawMappings, List<Action> actions) {
super(src, dst, rawMappings, actions);
}
public LeavesClassifier(TreeContext src, TreeContext dst, Matcher m) {
super(src, dst, m);
}
@Override
public void classify() {
for (Action a: actions) {
if (a instanceof Delete && isLeafAction(a)) {
srcDelTrees.add(a.getNode());
} else if (a instanceof Insert && isLeafAction(a)) {
dstAddTrees.add(a.getNode());
} else if (a instanceof Update && isLeafAction(a)) {
srcUpdTrees.add(a.getNode());
dstUpdTrees.add(mappings.getDst(a.getNode()));
} else if (a instanceof Move && isLeafAction(a)) {
srcMvTrees.add(a.getNode());
dstMvTrees.add(mappings.getDst(a.getNode()));
}
}
}
private boolean isLeafAction(Action a) {
for (ITree d: a.getNode().getDescendants()) {
for (Action c: actions)
if (a != c && d == c.getNode()) return false;
}
return true;
}
}
@@ -0,0 +1,85 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.github.gumtreediff.actions.model.Delete;
import com.github.gumtreediff.actions.model.Action;
import com.github.gumtreediff.actions.model.Insert;
import com.github.gumtreediff.actions.model.Move;
import com.github.gumtreediff.actions.model.Update;
import com.github.gumtreediff.matchers.Mapping;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeContext;
public class RootAndLeavesClassifier extends TreeClassifier {
public RootAndLeavesClassifier(TreeContext src, TreeContext dst, Set<Mapping> rawMappings, List<Action> actions) {
super(src, dst, rawMappings, actions);
}
public RootAndLeavesClassifier(TreeContext src, TreeContext dst, Matcher m) {
super(src, dst, m);
}
@Override
public void classify() {
for (Action a: actions) {
if (a instanceof Insert) {
dstAddTrees.add(a.getNode());
} else if (a instanceof Delete) {
srcDelTrees.add(a.getNode());
} else if (a instanceof Update) {
srcUpdTrees.add(a.getNode());
dstUpdTrees.add(mappings.getDst(a.getNode()));
} else if (a instanceof Move) {
srcMvTrees.add(a.getNode());
dstMvTrees.add(mappings.getDst(a.getNode()));
}
}
Set<ITree> fDstAddTrees = new HashSet<>();
for (ITree t: dstAddTrees)
if (!dstAddTrees.contains(t.getParent()))
fDstAddTrees.add(t);
dstAddTrees = fDstAddTrees;
Set<ITree> fSrcDelTrees = new HashSet<>();
for (ITree t: srcDelTrees) {
if (!srcDelTrees.contains(t.getParent()))
fSrcDelTrees.add(t);
}
srcDelTrees = fSrcDelTrees;
@SuppressWarnings("unused")
Set<ITree> fSrcMvTrees = new HashSet<>(); // FIXME check why it's unused
for (ITree t: srcDelTrees) {
if (!srcDelTrees.contains(t.getParent()))
fSrcDelTrees.add(t);
}
srcDelTrees = fSrcDelTrees;
}
}
@@ -0,0 +1,59 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions;
import java.util.List;
import java.util.Set;
import com.github.gumtreediff.actions.model.Delete;
import com.github.gumtreediff.actions.model.Move;
import com.github.gumtreediff.actions.model.Update;
import com.github.gumtreediff.actions.model.Action;
import com.github.gumtreediff.actions.model.Insert;
import com.github.gumtreediff.matchers.Mapping;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.tree.TreeContext;
public class RootsClassifier extends TreeClassifier {
public RootsClassifier(TreeContext src, TreeContext dst, Set<Mapping> rawMappings, List<Action> script) {
super(src, dst, rawMappings, script);
}
public RootsClassifier(TreeContext src, TreeContext dst, Matcher m) {
super(src, dst, m);
}
public void classify() {
for (Action a: actions) {
if (a instanceof Delete) srcDelTrees.add(a.getNode());
else if (a instanceof Insert)
dstAddTrees.add(a.getNode());
else if (a instanceof Update) {
srcUpdTrees.add(a.getNode());
dstUpdTrees.add(mappings.getDst(a.getNode()));
} else if (a instanceof Move) {
srcMvTrees.add(a.getNode());
dstMvTrees.add(mappings.getDst(a.getNode()));
}
}
}
}
@@ -0,0 +1,108 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.github.gumtreediff.actions.model.Action;
import com.github.gumtreediff.matchers.Mapping;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.matchers.Matcher;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeContext;
public abstract class TreeClassifier {
protected Set<ITree> srcUpdTrees;
protected Set<ITree> dstUpdTrees;
protected Set<ITree> srcMvTrees;
protected Set<ITree> dstMvTrees;
protected Set<ITree> srcDelTrees;
protected Set<ITree> dstAddTrees;
protected TreeContext src;
protected TreeContext dst;
protected MappingStore mappings;
protected List<Action> actions;
public TreeClassifier(TreeContext src, TreeContext dst, Set<Mapping> rawMappings, List<Action> actions) {
this(src, dst, rawMappings);
this.actions = actions;
classify();
}
public TreeClassifier(TreeContext src, TreeContext dst, Matcher m) {
this(src, dst, m.getMappingSet());
ActionGenerator g = new ActionGenerator(src.getRoot(), dst.getRoot(), m.getMappings());
g.generate();
this.actions = g.getActions();
classify();
}
private TreeClassifier(TreeContext src, TreeContext dst, Set<Mapping> rawMappings) {
this.src = src;
this.dst = dst;
this.mappings = new MappingStore(rawMappings);
this.srcDelTrees = new HashSet<>();
this.srcMvTrees = new HashSet<>();
this.srcUpdTrees = new HashSet<>();
this.dstMvTrees = new HashSet<>();
this.dstAddTrees = new HashSet<>();
this.dstUpdTrees = new HashSet<>();
}
public abstract void classify();
public Set<ITree> getSrcUpdTrees() {
return srcUpdTrees;
}
public Set<ITree> getDstUpdTrees() {
return dstUpdTrees;
}
public Set<ITree> getSrcMvTrees() {
return srcMvTrees;
}
public Set<ITree> getDstMvTrees() {
return dstMvTrees;
}
public Set<ITree> getSrcDelTrees() {
return srcDelTrees;
}
public Set<ITree> getDstAddTrees() {
return dstAddTrees;
}
}
@@ -0,0 +1,70 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions.model;
import com.github.gumtreediff.tree.ITree;
import java.io.Serializable;
public abstract class Action implements Comparable<Action>,Serializable {
protected ITree node;
protected Integer position;
protected int length = 0;
public Action(ITree node, int pos, int length) {
this.node = node;
this.length = length;
this.position = pos;
}
public ITree getNode() {
return node;
}
public void setNode(ITree node) {
this.node = node;
}
public int getPosition() {
return position;
}
public int getLength() {
return length;
}
public abstract String getName();
@Override
public abstract String toString();
@Override
public int compareTo(Action o) {
int result = this.position.compareTo(o.position);
if (result == 0) {
result = this.length >= o.length ? -1 : 1;
}
return result;
}
}
@@ -0,0 +1,49 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions.model;
import com.github.gumtreediff.tree.ITree;
public abstract class Addition extends Action {
protected ITree parent;
protected int pos;//index position of the new node in the children array list of its corresponding old parent node.
public Addition(ITree node, ITree parent, int pos) {
super(node, node.getPos(), node.getLength());
this.parent = parent;
this.pos = pos;
}
public ITree getParent() {
return parent;
}
public int getPos() {
return pos;
}
@Override
public String toString() {
return getName() + " " + node.toShortString() + " @TO@ " + parent.toShortString() + " @AT@ " + position + " @LENGTH@ " + length;
}
}
@@ -0,0 +1,42 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions.model;
import com.github.gumtreediff.tree.ITree;
public class Delete extends Action {
public Delete(ITree node) {
super(node, node.getPos(), node.getLength());
}
@Override
public String getName() {
return "DEL";
}
@Override
public String toString() {
// node.toShortString: getType()@@getLabel()
// return getName() + " " + node.toShortString() + " / "+node.getChildrenLabels() + " at " + node.getPos();
return getName() + " " + node.toShortString() + " @AT@ " + position + " @LENGTH@ " + length;
}
}
@@ -0,0 +1,36 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions.model;
import com.github.gumtreediff.tree.ITree;
public class Insert extends Addition {
public Insert(ITree node, ITree parent, int pos) {
super(node, parent, pos);
}
@Override
public String getName() {
return "INS";
}
}
@@ -0,0 +1,54 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions.model;
import com.github.gumtreediff.tree.ITree;
public class Move extends Addition {
private ITree newNode;
public Move(ITree node, ITree parent, int pos) {
super(node, parent, pos);
}
/**
*
* @param node, old node.
* @param parent, parent of old node.
* @param newNode, new node.
* @param pos, position of the new node in the children array list of its corresponding old parent node.
*/
public Move(ITree node, ITree parent, ITree newNode, int pos) {
this(node, parent, pos);
this.newNode = newNode;
}
public ITree getNewNode() {
return this.newNode;
}
@Override
public String getName() {
return "MOV";
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.actions.model;
import com.github.gumtreediff.tree.ITree;
public class Update extends Action {
private String value;
private ITree newNode;
public Update(ITree node, ITree newNode) {
super(node, node.getPos(), node.getLength());
this.value = newNode.getLabel();
this.newNode = newNode;
}
@Override
public String getName() {
return "UPD";
}
public String getValue() {
return this.value;
}
public ITree getNewNode() {
return this.newNode;
}
@Override
public String toString() {
// node.toShortString: getType()@@getLabel()
return getName() + " " + node.toShortString() + " @TO@ " + value + " @AT@ " + position + " @LENGTH@ " + length;
}
}
@@ -0,0 +1,79 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.gen;
import com.github.gumtreediff.tree.TreeContext;
import java.io.IOException;
import java.util.Arrays;
import java.util.regex.Pattern;
public class Generators extends Registry<String, TreeGenerator, Register> {
private static Generators registry;
public static final Generators getInstance() {
if (registry == null)
registry = new Generators();
return registry;
}
public TreeContext getTree(String file) throws UnsupportedOperationException, IOException {
TreeGenerator p = get(file);
if (p == null)
throw new UnsupportedOperationException("No generator found for file: " + file);
return p.generateFromFile(file);
}
public TreeContext getTree(String generator, String file) throws UnsupportedOperationException, IOException {
for (Entry e : entries)
if (e.id.equals(generator))
return e.instantiate(null).generateFromFile(file);
throw new UnsupportedOperationException("No generator \"" + generator + "\" found.");
}
@Override
protected Entry newEntry(Class<? extends TreeGenerator> clazz, Register annotation) {
return new Entry(annotation.id(), clazz, defaultFactory(clazz), annotation.priority()) {
final Pattern[] accept;
{
String[] accept = annotation.accept();
this.accept = new Pattern[accept.length];
for (int i = 0; i < accept.length; i++)
this.accept[i] = Pattern.compile(accept[i]);
}
@Override
protected boolean handle(String key) {
for (Pattern pattern : accept)
if (pattern.matcher(key).find())
return true;
return false;
}
@Override
public String toString() {
return String.format("%s: %s", Arrays.toString(accept), clazz.getCanonicalName());
}
};
}
}
@@ -0,0 +1,34 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.gen;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Register {
String id();
String[] accept() default { };
int priority() default Registry.Priority.MEDIUM;
}
@@ -0,0 +1,150 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.gen;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
public abstract class Registry<K, C, A> {
Set<Entry> entries = new TreeSet<>((o1, o2) -> {
int cmp = o1.priority - o2.priority;
if (cmp == 0)
cmp = o1.id.compareToIgnoreCase(o2.id); // FIXME or not ... is id a good unique stuff
return cmp;
});
public class Priority {
public static final int MAXIMUM = 0;
public static final int HIGH = 25;
public static final int MEDIUM = 50;
public static final int LOW = 75;
public static final int MINIMUM = 100;
}
public C get(K key, Object... args) {
Factory<? extends C> factory = getFactory(key);
if (factory != null)
return factory.instantiate(args);
return null;
}
public Factory<? extends C> getFactory(K key) {
Entry entry = find(key);
if (entry != null)
return entry.factory;
return null;
}
protected Entry find(K key) {
Entry entry = findEntry(key);
if (entry == null)
return null;
return entry;
}
protected Entry findById(String id) {
for (Entry e: entries)
if (e.id.equals(id))
return e;
return null;
}
public void install(Class<? extends C> clazz, A annotation) {
Entry entry = newEntry(clazz, annotation);
entries.add(entry);
}
protected abstract Entry newEntry(Class<? extends C> clazz, A annotation);
protected Entry findEntry(K key) {
for (Entry e: entries)
if (e.handle(key))
return e;
return null;
}
public Entry findByClass(Class<? extends C> aClass) {
for (Entry e: entries)
if (e.clazz.equals(aClass))
return e;
return null;
}
public Set<Entry> getEntries() {
return Collections.unmodifiableSet(entries);
}
public abstract class Entry {
public final String id;
public final int priority;
final Class<? extends C> clazz;
final Factory<? extends C> factory;
protected Entry(String id, Class<? extends C> clazz, Factory<? extends C> factory, int priority) {
this.id = id;
this.clazz = clazz;
this.factory = factory;
this.priority = priority;
}
public C instantiate(Object[] args) {
try {
return factory.newInstance(args);
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
return null;
}
}
protected abstract boolean handle(K key);
@Override
public String toString() {
return id;
}
}
@SuppressWarnings("rawtypes")
protected Factory<? extends C> defaultFactory(Class<? extends C> clazz, Class... signature) {
try {
Constructor<? extends C> ctor = clazz.getConstructor(signature);
return (args) -> ctor.newInstance(args);
} catch (NoSuchMethodException e) {
System.out.println(Arrays.toString(clazz.getConstructors()));
throw new RuntimeException(String.format("This is a static bug. Constructor %s(%s) not found",
clazz.getName(), Arrays.toString(signature)), e);
}
}
public interface Factory<C> {
C newInstance(Object[] args) throws IllegalAccessException, InvocationTargetException, InstantiationException;
default C instantiate(Object[] args) {
try {
return newInstance(args);
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
return null;
}
}
}
}
@@ -0,0 +1,76 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.gen;
import com.github.gumtreediff.tree.TreeContext;
import java.io.*;
public abstract class TreeGenerator {
protected abstract TreeContext generate(Reader r) throws IOException;
protected abstract TreeContext generate(Reader r, int astParserType) throws IOException;
public TreeContext generateFromReader(Reader r) throws IOException {
TreeContext ctx = generate(r);
ctx.validate();
return ctx;
}
public TreeContext generateFromFile(String path) throws IOException {
return generateFromReader(new FileReader(path));
}
public TreeContext generateFromFile(File file) throws IOException {
return generateFromReader(new FileReader(file));
}
public TreeContext generateFromStream(InputStream stream) throws IOException {
return generateFromReader(new InputStreamReader(stream));
}
public TreeContext generateFromString(String content) throws IOException {
return generateFromReader(new StringReader(content));
}
public TreeContext generateFromReader(Reader r, int astParserType) throws IOException {
TreeContext ctx = generate(r, astParserType);
ctx.validate();
return ctx;
}
public TreeContext generateFromFile(String path, int astParserType) throws IOException {
return generateFromReader(new FileReader(path), astParserType);
}
public TreeContext generateFromFile(File file, int astParserType) throws IOException {
return generateFromReader(new FileReader(file), astParserType);
}
public TreeContext generateFromStream(InputStream stream, int astParserType) throws IOException {
return generateFromReader(new InputStreamReader(stream), astParserType);
}
public TreeContext generateFromString(String content, int astParserType) throws IOException {
return generateFromReader(new StringReader(content), astParserType);
}
}
@@ -0,0 +1,412 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.io;
import com.github.gumtreediff.actions.model.*;
import com.github.gumtreediff.io.TreeIoUtils.AbstractSerializer;
import com.github.gumtreediff.matchers.Mapping;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeContext;
import com.google.gson.stream.JsonWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
public final class ActionsIoUtils {
private ActionsIoUtils() {
}
public static ActionSerializer toText(TreeContext sctx, List<Action> actions,
MappingStore mappings) throws IOException {
return new ActionSerializer(sctx, mappings, actions) {
@Override
protected ActionFormatter newFormatter(TreeContext ctx, Writer writer) throws Exception {
return new TextFormatter(ctx, writer);
}
};
}
public static ActionSerializer toXml(TreeContext sctx, List<Action> actions,
MappingStore mappings) throws IOException {
return new ActionSerializer(sctx, mappings, actions) {
@Override
protected ActionFormatter newFormatter(TreeContext ctx, Writer writer) throws Exception {
return new XmlFormatter(ctx, writer);
}
};
}
public static ActionSerializer toJson(TreeContext sctx, List<Action> actions,
MappingStore mappings) throws IOException {
return new ActionSerializer(sctx, mappings, actions) {
@Override
protected ActionFormatter newFormatter(TreeContext ctx, Writer writer) throws Exception {
return new JsonFormatter(ctx, writer);
}
};
}
public abstract static class ActionSerializer extends AbstractSerializer {
final TreeContext context;
final MappingStore mappings;
final List<Action> actions;
ActionSerializer(TreeContext context, MappingStore mappings, List<Action> actions) {
this.context = context;
this.mappings = mappings;
this.actions = actions;
}
protected abstract ActionFormatter newFormatter(TreeContext ctx, Writer writer) throws Exception;
@Override
public void writeTo(Writer writer) throws Exception {
ActionFormatter fmt = newFormatter(context, writer);
// Start the output
fmt.startOutput();
// Write the matches
fmt.startMatches();
for (Mapping m: mappings) {
fmt.match(m.getFirst(), m.getSecond());
}
fmt.endMatches();
// Write the actions
fmt.startActions();
for (Action a : actions) {
ITree src = a.getNode();
if (a instanceof Move) {
ITree dst = mappings.getDst(src);
fmt.moveAction(src, dst.getParent(), ((Move) a).getPosition());
} else if (a instanceof Update) {
ITree dst = mappings.getDst(src);
fmt.updateAction(src, dst);
} else if (a instanceof Insert) {
ITree dst = a.getNode();
if (dst.isRoot())
fmt.insertRoot(src);
else
fmt.insertAction(src, dst.getParent(), dst.getParent().getChildPosition(dst));
} else if (a instanceof Delete) {
fmt.deleteAction(src);
}
}
fmt.endActions();
// Finish up
fmt.endOutput();
}
}
interface ActionFormatter {
void startOutput() throws Exception;
void endOutput() throws Exception;
void startMatches() throws Exception;
void match(ITree srcNode, ITree destNode) throws Exception;
void endMatches() throws Exception;
void startActions() throws Exception;
void insertRoot(ITree node) throws Exception;
void insertAction(ITree node, ITree parent, int index) throws Exception;
void moveAction(ITree src, ITree dst, int index) throws Exception;
void updateAction(ITree src, ITree dst) throws Exception;
void deleteAction(ITree node) throws Exception;
void endActions() throws Exception;
}
static class XmlFormatter implements ActionFormatter {
final TreeContext context;
final XMLStreamWriter writer;
XmlFormatter(TreeContext context, Writer w) throws XMLStreamException {
XMLOutputFactory f = XMLOutputFactory.newInstance();
writer = new IndentingXMLStreamWriter(f.createXMLStreamWriter(w));
this.context = context;
}
@Override
public void startOutput() throws XMLStreamException {
writer.writeStartDocument();
}
@Override
public void endOutput() throws XMLStreamException {
writer.writeEndDocument();
}
@Override
public void startMatches() throws XMLStreamException {
writer.writeStartElement("matches");
}
@Override
public void match(ITree srcNode, ITree destNode) throws XMLStreamException {
writer.writeEmptyElement("match");
writer.writeAttribute("src", Integer.toString(srcNode.getId()));
writer.writeAttribute("dest", Integer.toString(destNode.getId()));
}
@Override
public void endMatches() throws XMLStreamException {
writer.writeEndElement();
}
@Override
public void startActions() throws XMLStreamException {
writer.writeStartElement("actions");
}
@Override
public void insertRoot(ITree node) throws Exception {
start(Insert.class, node);
end(node);
}
@Override
public void insertAction(ITree node, ITree parent, int index) throws Exception {
start(Insert.class, node);
writer.writeAttribute("parent", Integer.toString(parent.getId()));
writer.writeAttribute("at", Integer.toString(index));
end(node);
}
@Override
public void moveAction(ITree src, ITree dst, int index) throws XMLStreamException {
start(Move.class, src);
writer.writeAttribute("parent", Integer.toString(dst.getId()));
writer.writeAttribute("at", Integer.toString(index));
end(src);
}
@Override
public void updateAction(ITree src, ITree dst) throws XMLStreamException {
start(Update.class, src);
writer.writeAttribute("label", dst.getLabel());
end(src);
}
@Override
public void deleteAction(ITree node) throws Exception {
start(Delete.class, node);
end(node);
}
@Override
public void endActions() throws XMLStreamException {
writer.writeEndElement();
}
private void start(Class<? extends Action> name, ITree src) throws XMLStreamException {
writer.writeEmptyElement(name.getSimpleName().toLowerCase());
writer.writeAttribute("tree", Integer.toString(src.getId()));
}
private void end(ITree node) throws XMLStreamException {
// writer.writeEndElement();
}
}
static class TextFormatter implements ActionFormatter {
final Writer writer;
final TreeContext context;
public TextFormatter(TreeContext ctx, Writer writer) {
this.context = ctx;
this.writer = writer;
}
@Override
public void startOutput() throws Exception {
}
@Override
public void endOutput() throws Exception {
}
@Override
public void startMatches() throws Exception {
}
@Override
public void match(ITree srcNode, ITree destNode) throws Exception {
write("Match %s to %s", toS(srcNode), toS(destNode));
}
@Override
public void endMatches() throws Exception {
}
@Override
public void startActions() throws Exception {
}
@Override
public void insertRoot(ITree node) throws Exception {
write("Insert root %s", toS(node));
}
@Override
public void insertAction(ITree node, ITree parent, int index) throws Exception {
write("Insert %s into %s at %d", toS(node), toS(parent), index);
}
@Override
public void moveAction(ITree src, ITree dst, int position) throws Exception {
write("Move %s into %s at %d", toS(src), toS(dst), position);
}
@Override
public void updateAction(ITree src, ITree dst) throws Exception {
write("Update %s to %s", toS(src), dst.getLabel());
}
@Override
public void deleteAction(ITree node) throws Exception {
write("Delete %s", toS(node));
}
@Override
public void endActions() throws Exception {
}
private void write(String fmt, Object... objs) throws IOException {
writer.append(String.format(fmt, objs));
writer.append("\n");
}
private String toS(ITree node) {
return String.format("%s(%d)", node.toPrettyString(context), node.getId());
}
}
static class JsonFormatter implements ActionFormatter {
private final JsonWriter writer;
JsonFormatter(TreeContext ctx, Writer writer) {
this.writer = new JsonWriter(writer);
this.writer.setIndent(" ");
}
@Override
public void startOutput() throws IOException {
writer.beginObject();
}
@Override
public void endOutput() throws IOException {
writer.endObject();
}
@Override
public void startMatches() throws Exception {
writer.name("matches").beginArray();
}
@Override
public void match(ITree srcNode, ITree destNode) throws Exception {
writer.beginObject();
writer.name("src").value(srcNode.getId());
writer.name("dest").value(destNode.getId());
writer.endObject();
}
@Override
public void endMatches() throws Exception {
writer.endArray();
}
@Override
public void startActions() throws IOException {
writer.name("actions").beginArray();
}
@Override
public void insertRoot(ITree node) throws IOException {
start(Insert.class, node);
end(node);
}
@Override
public void insertAction(ITree node, ITree parent, int index) throws IOException {
start(Insert.class, node);
writer.name("parent").value(parent.getId());
writer.name("at").value(index);
end(node);
}
@Override
public void moveAction(ITree src, ITree dst, int index) throws IOException {
start(Move.class, src);
writer.name("parent").value(dst.getId());
writer.name("at").value(index);
end(src);
}
@Override
public void updateAction(ITree src, ITree dst) throws IOException {
start(Update.class, src);
writer.name("label").value(dst.getLabel());
end(src);
}
@Override
public void deleteAction(ITree node) throws IOException {
start(Delete.class, node);
end(node);
}
private void start(Class<? extends Action> name, ITree src) throws IOException {
writer.beginObject();
writer.name("action").value(name.getSimpleName().toLowerCase());
writer.name("tree").value(src.getId());
}
private void end(ITree node) throws IOException {
writer.endObject();
}
@Override
public void endActions() throws Exception {
writer.endArray();
}
}
}
@@ -0,0 +1,101 @@
package com.github.gumtreediff.io;
import java.util.HashMap;
import java.util.Map;
public class CNodeMap {
public static Map<Integer, String> map;
static {
map = new HashMap<Integer, String>();
map.put(20100,"Left");
map.put(30100,"ActMisc");
map.put(40000,"FullType");
map.put(50000,"TypeQualifier");
map.put(60100,"BaseType");
map.put(60200,"Pointer");
map.put(60800,"EnumName");
map.put(60900,"StructUnionName");
map.put(61000,"TypeName");
map.put(70002,"SizeType");
map.put(70100,"IntType");
map.put(80001,"CChar");
map.put(80100,"Si");
map.put(90002,"UnSigned");
map.put(100003,"CInt");
map.put(200000,"ParamList");
map.put(210000,"DotsParameter");
map.put(220100,"ParameterType");
map.put(240100,"Ident");
map.put(240200,"Constant");
map.put(240400,"FunCall");
map.put(240500,"CondExpr");
map.put(240600,"Sequence");
map.put(240700,"Assignment");
map.put(240800,"Postfix");
map.put(240900,"Infix");
map.put(241000,"Unary");
map.put(241100,"Binary");
map.put(241200,"ArrayAccess");
map.put(241300,"RecordAccess");
map.put(241400,"RecordPtAccess");
map.put(241500,"SizeOfExpr");
map.put(241600,"SizeOfType");
map.put(241700,"Cast");
map.put(241900,"Constructor");
map.put(242000,"ParenExpr");
map.put(260300,"ExprStatement");
map.put(260800,"Asm");
map.put(270100,"Label");
map.put(270200,"Case");
map.put(270300,"CaseRange");
map.put(270400,"Default");
map.put(280001,"Continue");
map.put(280002,"Break");
map.put(280003,"Return");
map.put(280100,"Goto");
map.put(280200,"ReturnExpr");
map.put(290001,"None");
map.put(290100,"Some");
map.put(300100,"If");
map.put(300200,"Switch");
map.put(310100,"While");
map.put(310200,"DoWhile");
map.put(310300,"For");
map.put(310400,"MacroIteration");
map.put(330000,"Compound");
map.put(340000,"Storage");
map.put(350100,"DeclList");
map.put(350200,"MacroDecl");
map.put(360100,"InitExpr");
map.put(360200,"InitList");
map.put(360300,"InitDesignators");
map.put(370100,"DesignatorField");
map.put(370200,"DesignatorIndex");
map.put(370300,"DesignatorRange");
map.put(380000,"Definition");
map.put(400100,"Define");
map.put(400200,"Include");
map.put(400400,"OtherDirective");
map.put(410001,"DefineVar");
map.put(410002,"Undef");
map.put(410100,"DefineFunc");
map.put(420001,"DefineEmpty");
map.put(420100,"DefineExpr");
map.put(420200,"DefineStmt");
map.put(420400,"DefineDoWhileZero");
map.put(420600,"DefineInit");
map.put(440100,"IfdefDirective");
map.put(450100,"Declaration");
map.put(450200,"Definition");
map.put(450300,"CppTop");
map.put(450400,"IfdefTop");
map.put(450700,"NotParsedCorrectly");
map.put(450800,"FinalDef");
map.put(460000,"Program");
map.put(470000,"GenericList");
map.put(480000,"GenericString");
map.put(490100,"IfToken");
}
}
@@ -0,0 +1,178 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.io;
import com.github.gumtreediff.utils.Pair;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class DirectoryComparator {
private Path src;
public Path getSrc() {
return src;
}
public Path getDst() {
return dst;
}
private Path dst;
private List<Pair<File, File>> modifiedFiles;
private Set<File> deletedFiles;
private Set<File> addedFiles;
private boolean dirMode = true;
public DirectoryComparator(String src, String dst) {
modifiedFiles = new ArrayList<>();
addedFiles = new HashSet<>();
deletedFiles = new HashSet<>();
this.src = Paths.get(src);
this.dst = Paths.get(dst);
if (!Files.exists(this.src) || !Files.exists(this.dst))
throw new RuntimeException();
else {
if (!Files.isDirectory(this.src) && !Files.isDirectory(this.dst)) {
this.modifiedFiles.add(new Pair<>(this.src.toFile(), this.dst.toFile()));
this.src = this.src.getParent();
this.dst = this.dst.getParent();
this.dirMode = false;
} else if (!(Files.isDirectory(this.src) && Files.isDirectory(this.dst))) {
throw new RuntimeException();
}
}
}
public void compare() {
if (!dirMode) return;
AllFilesVisitor vSrc = new AllFilesVisitor(src);
AllFilesVisitor vDst = new AllFilesVisitor(dst);
try {
Files.walkFileTree(src, vSrc);
Files.walkFileTree(dst, vDst);
Set<String> addedFiles = new HashSet<>();
addedFiles.addAll(vDst.files);
addedFiles.removeAll(vSrc.files);
for (String file : addedFiles) this.addedFiles.add(toDstFile(file));
Set<String> deletedFiles = new HashSet<>();
deletedFiles.addAll(vSrc.files);
deletedFiles.removeAll(vDst.files);
for (String file : deletedFiles) this.deletedFiles.add(toSrcFile(file));
Set<String> commonFiles = new HashSet<>();
commonFiles.addAll(vSrc.files);
commonFiles.retainAll(vDst.files);
for (String file : commonFiles)
if (hasChanged(file, file))
modifiedFiles.add(new Pair<File, File>(toSrcFile(file), toDstFile(file)));
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean isDirMode() {
return dirMode;
}
public List<Pair<File, File>> getModifiedFiles() {
return modifiedFiles;
}
public Set<File> getDeletedFiles() {
return deletedFiles;
}
public Set<File> getAddedFiles() {
return addedFiles;
}
private File toSrcFile(String s) {
return new File(src.toFile(), s);
}
private File toDstFile(String s) {
return new File(dst.toFile(), s);
}
public boolean hasChanged(String s1, String s2) throws IOException {
File f1 = toSrcFile(s1);
File f2 = toDstFile(s2);
long l1 = Files.size(f1.toPath());
long l2 = Files.size(f2.toPath());
if (l1 != l2) return true;
else {
try (DataInputStream dis1 = new DataInputStream(new FileInputStream(f1));
DataInputStream dis2 = new DataInputStream(new FileInputStream(f2))) {
int c1, c2;
while ((c1 = dis1.read()) != -1) {
c2 = dis2.read();
if (c1 != c2)
return true;
}
return false;
}
}
}
public static class AllFilesVisitor extends SimpleFileVisitor<Path> {
private Set<String> files = new HashSet<>();
private Path root;
public AllFilesVisitor(Path root) {
this.root = root;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (!file.getFileName().startsWith("."))
files.add(root.relativize(file).toString());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
return (dir.getFileName().toString().startsWith("."))
? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE;
}
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2006, John Kristian
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of StAX-Utils nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.github.gumtreediff.io;
/**
* Characters that represent line breaks and indentation. These are represented
* as String-valued JavaBean properties.
*/
public interface Indentation {
/** Two spaces; the default indentation. */
public static final String DEFAULT_INDENT = " ";
/**
* Set the characters used for one level of indentation. The default is
* {@link #DEFAULT_INDENT}. "\t" is a popular alternative.
*/
void setIndent(String indent);
/** The characters used for one level of indentation. */
String getIndent();
/**
* "\n"; the normalized representation of end-of-line in <a
* href="http://www.w3.org/TR/xml11/#sec-line-ends">XML</a>.
*/
public static final String NORMAL_END_OF_LINE = "\n";
/**
* Set the characters that introduce a new line. The default is
* {@link #NORMAL_END_OF_LINE}.
* {@link IndentingXMLStreamWriter#getLineSeparator}() is a popular
* alternative.
*/
public void setNewLine(String newLine);
/** The characters that introduce a new line. */
String getNewLine();
}
@@ -0,0 +1,342 @@
/*
* Copyright (c) 2006, John Kristian
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of StAX-Utils nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.github.gumtreediff.io;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
/**
* A filter that indents an XML stream. To apply it, construct a filter that
* contains another {@link XMLStreamWriter}, which you pass to the constructor.
* Then call methods of the filter instead of the contained stream. For example:
*
* <pre>
* {@link XMLStreamWriter} stream = ...
* stream = new {@link IndentingXMLStreamWriter}(stream);
* stream.writeStartDocument();
* ...
* </pre>
*
* <p>
* The filter inserts characters to format the document as an outline, with
* nested elements indented. Basically, it inserts a line break and whitespace
* before:
* <ul>
* <li>each DTD, processing instruction or comment that's not preceded by data</li>
* <li>each starting tag that's not preceded by data</li>
* <li>each ending tag that's preceded by nested elements but not data</li>
* </ul>
* This works well with 'data-oriented' XML, wherein each element contains
* either data or nested elements but not both. It can work badly with other
* styles of XML. For example, the data in a 'mixed content' document are apt to
* be polluted with indentation characters.
*
* <p>
* Indentation can be adjusted by setting the newLine and indent properties. But
* set them to whitespace only, for best results. Non-whitespace is apt to cause
* problems, for example when this class attempts to insert newLine before the
* root element.
*
* @author <a href="mailto:jk2006@engineer.com">John Kristian</a>
*/
public class IndentingXMLStreamWriter extends StreamWriterDelegate implements Indentation {
public IndentingXMLStreamWriter(XMLStreamWriter out) {
super(out);
}
/** How deeply nested the current scope is. The root element is depth 1. */
private int depth = 0; // document scope
/** stack[depth] indicates what's been written into the current scope. */
private int[] stack = new int[] { 0, 0, 0, 0 }; // nothing written yet
private static final int WROTE_MARKUP = 1;
private static final int WROTE_DATA = 2;
private String indent = DEFAULT_INDENT;
private String newLine = NORMAL_END_OF_LINE;
/** newLine followed by copies of indent. */
private char[] linePrefix = null;
public void setIndent(String indent) {
if (!indent.equals(this.indent)) {
this.indent = indent;
linePrefix = null;
}
}
public String getIndent() {
return indent;
}
public void setNewLine(String newLine) {
if (!newLine.equals(this.newLine)) {
this.newLine = newLine;
linePrefix = null;
}
}
/**
* @return System.getProperty("line.separator"); or
* {@link #NORMAL_END_OF_LINE} if that fails.
*/
public static String getLineSeparator() {
try {
return System.getProperty("line.separator");
} catch (SecurityException ignored) {
ignored.printStackTrace();
}
return NORMAL_END_OF_LINE;
}
public String getNewLine() {
return newLine;
}
public void writeStartDocument() throws XMLStreamException {
beforeMarkup();
out.writeStartDocument();
afterMarkup();
}
public void writeStartDocument(String version) throws XMLStreamException {
beforeMarkup();
out.writeStartDocument(version);
afterMarkup();
}
public void writeStartDocument(String encoding, String version) throws XMLStreamException {
beforeMarkup();
out.writeStartDocument(encoding, version);
afterMarkup();
}
public void writeDTD(String dtd) throws XMLStreamException {
beforeMarkup();
out.writeDTD(dtd);
afterMarkup();
}
public void writeProcessingInstruction(String target) throws XMLStreamException {
beforeMarkup();
out.writeProcessingInstruction(target);
afterMarkup();
}
public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
beforeMarkup();
out.writeProcessingInstruction(target, data);
afterMarkup();
}
public void writeComment(String data) throws XMLStreamException {
beforeMarkup();
out.writeComment(data);
afterMarkup();
}
public void writeEmptyElement(String localName) throws XMLStreamException {
beforeMarkup();
out.writeEmptyElement(localName);
afterMarkup();
}
public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
beforeMarkup();
out.writeEmptyElement(namespaceURI, localName);
afterMarkup();
}
public void writeEmptyElement(String prefix, String localName, String namespaceURI)
throws XMLStreamException {
beforeMarkup();
out.writeEmptyElement(prefix, localName, namespaceURI);
afterMarkup();
}
public void writeStartElement(String localName) throws XMLStreamException {
beforeStartElement();
out.writeStartElement(localName);
afterStartElement();
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
beforeStartElement();
out.writeStartElement(namespaceURI, localName);
afterStartElement();
}
public void writeStartElement(String prefix, String localName, String namespaceURI)
throws XMLStreamException {
beforeStartElement();
out.writeStartElement(prefix, localName, namespaceURI);
afterStartElement();
}
public void writeCharacters(String text) throws XMLStreamException {
out.writeCharacters(text);
afterData();
}
public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
out.writeCharacters(text, start, len);
afterData();
}
public void writeCData(String data) throws XMLStreamException {
out.writeCData(data);
afterData();
}
public void writeEntityRef(String name) throws XMLStreamException {
out.writeEntityRef(name);
afterData();
}
public void writeEndElement() throws XMLStreamException {
beforeEndElement();
out.writeEndElement();
afterEndElement();
}
public void writeEndDocument() throws XMLStreamException {
try {
while (depth > 0) {
writeEndElement(); // indented
}
} catch (Exception ignored) {
ignored.printStackTrace();
}
out.writeEndDocument();
afterEndDocument();
}
/** Prepare to write markup, by writing a new line and indentation. */
protected void beforeMarkup() {
int soFar = stack[depth];
if ((soFar & WROTE_DATA) == 0 // no data in this scope
&& (depth > 0 || soFar != 0)) {
try {
writeNewLine(depth);
if (depth > 0 && getIndent().length() > 0) {
afterMarkup(); // indentation was written
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/** Note that markup or indentation was written. */
protected void afterMarkup() {
stack[depth] |= WROTE_MARKUP;
}
/** Note that data were written. */
protected void afterData() {
stack[depth] |= WROTE_DATA;
}
/** Prepare to start an element, by allocating stack space. */
protected void beforeStartElement() {
beforeMarkup();
if (stack.length <= depth + 1) {
// Allocate more space for the stack:
int[] newStack = new int[stack.length * 2];
System.arraycopy(stack, 0, newStack, 0, stack.length);
stack = newStack;
}
stack[depth + 1] = 0; // nothing written yet
}
/** Note that an element was started. */
protected void afterStartElement() {
afterMarkup();
++depth;
}
/** Prepare to end an element, by writing a new line and indentation. */
protected void beforeEndElement() {
if (depth > 0 && stack[depth] == WROTE_MARKUP) { // but not data
try {
writeNewLine(depth - 1);
} catch (Exception ignored) {
ignored.printStackTrace();
}
}
}
/** Note that an element was ended. */
protected void afterEndElement() {
if (depth > 0) {
--depth;
}
}
/** Note that a document was ended. */
protected void afterEndDocument() {
if (stack[depth = 0] == WROTE_MARKUP) { // but not data
try {
writeNewLine(0);
} catch (Exception ignored) {
ignored.printStackTrace();
}
}
stack[depth] = 0; // start fresh
}
/** Write a line separator followed by indentation. */
protected void writeNewLine(int indentation) throws XMLStreamException {
final int newLineLength = getNewLine().length();
final int prefixLength = newLineLength + (getIndent().length() * indentation);
if (prefixLength > 0) {
if (linePrefix == null) {
linePrefix = (getNewLine() + getIndent()).toCharArray();
}
while (prefixLength > linePrefix.length) {
// make linePrefix longer:
char[] newPrefix = new char[newLineLength
+ ((linePrefix.length - newLineLength) * 2)];
System.arraycopy(linePrefix, 0, newPrefix, 0, linePrefix.length);
System.arraycopy(linePrefix, newLineLength, newPrefix, linePrefix.length,
linePrefix.length - newLineLength);
linePrefix = newPrefix;
}
out.writeCharacters(linePrefix, 0, prefixLength);
}
}
}
@@ -0,0 +1,62 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.io;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
public class LineReader extends Reader {
private Reader reader;
private int currentPos = 0;
private ArrayList<Integer> lines = new ArrayList<>(Arrays.asList(0));
public LineReader(Reader parent) {
reader = parent;
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
int r = reader.read(cbuf, off, len);
for (int i = 0; i < len; i ++)
if (cbuf[off + i] == '\n')
lines.add(currentPos + i);
currentPos += len;
return r;
}
// Line and column starts at 1
public int positionFor(int line, int column) {
return lines.get(line - 1) + column - 1;
}
// public int[] positionFor(int offset) { // TODO write this method
// Arrays.binarySearch(lines., null, null)
// }
@Override
public void close() throws IOException {
reader.close();
}
}
@@ -0,0 +1,51 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.io;
public final class MatrixDebugger {
private MatrixDebugger() {
}
public static void dump(Object[][] mat) {
for (Object[] r : mat) {
for (Object l: r) System.out.print(l + "\t");
System.out.println();
}
}
public static void dump(boolean[][] mat) {
for (boolean[] r : mat) {
for (boolean l: r) System.out.print(l + "\t");
System.out.println();
}
}
public static void dump(double[][] mat) {
System.out.println("---");
for (double[] r : mat) {
for (double l: r) System.out.print(l + "\t");
System.out.println();
}
System.out.println("---");
}
}
@@ -0,0 +1,185 @@
/*
* Copyright (c) 2006, John Kristian
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of StAX-Utils nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.github.gumtreediff.io;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
/**
* Abstract class for writing filtered XML streams. This class provides methods
* that merely delegate to the contained stream. Subclasses should override some
* of these methods, and may also provide additional methods and fields.
*
* @author <a href="mailto:jk2006@engineer.com">John Kristian</a>
*/
public abstract class StreamWriterDelegate implements XMLStreamWriter {
protected StreamWriterDelegate(XMLStreamWriter out) {
this.out = out;
}
protected XMLStreamWriter out;
public Object getProperty(String name) throws IllegalArgumentException {
return out.getProperty(name);
}
public NamespaceContext getNamespaceContext() {
return out.getNamespaceContext();
}
public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
out.setNamespaceContext(context);
}
public void setDefaultNamespace(String uri) throws XMLStreamException {
out.setDefaultNamespace(uri);
}
public void writeStartDocument() throws XMLStreamException {
out.writeStartDocument();
}
public void writeStartDocument(String version) throws XMLStreamException {
out.writeStartDocument(version);
}
public void writeStartDocument(String encoding, String version) throws XMLStreamException {
out.writeStartDocument(encoding, version);
}
public void writeDTD(String dtd) throws XMLStreamException {
out.writeDTD(dtd);
}
public void writeProcessingInstruction(String target) throws XMLStreamException {
out.writeProcessingInstruction(target);
}
public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
out.writeProcessingInstruction(target, data);
}
public void writeComment(String data) throws XMLStreamException {
out.writeComment(data);
}
public void writeEmptyElement(String localName) throws XMLStreamException {
out.writeEmptyElement(localName);
}
public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
out.writeEmptyElement(namespaceURI, localName);
}
public void writeEmptyElement(String prefix, String localName, String namespaceURI)
throws XMLStreamException {
out.writeEmptyElement(prefix, localName, namespaceURI);
}
public void writeStartElement(String localName) throws XMLStreamException {
out.writeStartElement(localName);
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
out.writeStartElement(namespaceURI, localName);
}
public void writeStartElement(String prefix, String localName, String namespaceURI)
throws XMLStreamException {
out.writeStartElement(prefix, localName, namespaceURI);
}
public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
out.writeDefaultNamespace(namespaceURI);
}
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
out.writeNamespace(prefix, namespaceURI);
}
public String getPrefix(String uri) throws XMLStreamException {
return out.getPrefix(uri);
}
public void setPrefix(String prefix, String uri) throws XMLStreamException {
out.setPrefix(prefix, uri);
}
public void writeAttribute(String localName, String value) throws XMLStreamException {
out.writeAttribute(localName, value);
}
public void writeAttribute(String namespaceURI, String localName, String value)
throws XMLStreamException {
out.writeAttribute(namespaceURI, localName, value);
}
public void writeAttribute(String prefix, String namespaceURI, String localName, String value)
throws XMLStreamException {
out.writeAttribute(prefix, namespaceURI, localName, value);
}
public void writeCharacters(String text) throws XMLStreamException {
out.writeCharacters(text);
}
public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
out.writeCharacters(text, start, len);
}
public void writeCData(String data) throws XMLStreamException {
out.writeCData(data);
}
public void writeEntityRef(String name) throws XMLStreamException {
out.writeEntityRef(name);
}
public void writeEndElement() throws XMLStreamException {
out.writeEndElement();
}
public void writeEndDocument() throws XMLStreamException {
out.writeEndDocument();
}
public void flush() throws XMLStreamException {
out.flush();
}
public void close() throws XMLStreamException {
out.close();
}
}
@@ -0,0 +1,699 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.io;
import com.github.gumtreediff.gen.Register;
import com.github.gumtreediff.gen.TreeGenerator;
import com.github.gumtreediff.matchers.MappingStore;
import com.github.gumtreediff.tree.ITree;
import com.github.gumtreediff.tree.TreeContext;
import com.github.gumtreediff.tree.TreeContext.MetadataSerializers;
import com.github.gumtreediff.tree.TreeContext.MetadataUnserializers;
import com.github.gumtreediff.tree.TreeUtils;
import com.google.gson.stream.JsonWriter;
import javax.xml.namespace.QName;
import javax.xml.stream.*;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public final class TreeIoUtils {
private TreeIoUtils() {} // Forbids instantiation of TreeIOUtils
public static TreeGenerator fromXml() {
return new XmlInternalGenerator();
}
public static TreeGenerator fromXml(MetadataUnserializers unserializers) {
XmlInternalGenerator generator = new XmlInternalGenerator();
generator.getUnserializers().addAll(unserializers);
return generator;
}
public static TreeSerializer toXml(TreeContext ctx) {
return new TreeSerializer(ctx) {
@Override
protected TreeFormatter newFormatter(TreeContext ctx, MetadataSerializers serializers, Writer writer)
throws XMLStreamException {
return new XmlFormatter(writer, ctx);
}
};
}
public static TreeSerializer toAnnotatedXml(TreeContext ctx, boolean isSrc, MappingStore m) {
return new TreeSerializer(ctx) {
@Override
protected TreeFormatter newFormatter(TreeContext ctx, MetadataSerializers serializers, Writer writer)
throws XMLStreamException {
return new XmlAnnotatedFormatter(writer, ctx, isSrc, m);
}
};
}
public static TreeSerializer toCompactXml(TreeContext ctx) {
return new TreeSerializer(ctx) {
@Override
protected TreeFormatter newFormatter(TreeContext ctx, MetadataSerializers serializers, Writer writer)
throws Exception {
return new XmlCompactFormatter(writer, ctx);
}
};
}
public static TreeSerializer toJson(TreeContext ctx) {
return new TreeSerializer(ctx) {
@Override
protected TreeFormatter newFormatter(TreeContext ctx, MetadataSerializers serializers, Writer writer)
throws Exception {
return new JsonFormatter(writer, ctx);
}
};
}
public static TreeSerializer toLisp(TreeContext ctx) {
return new TreeSerializer(ctx) {
@Override
protected TreeFormatter newFormatter(TreeContext ctx, MetadataSerializers serializers, Writer writer)
throws Exception {
return new LispFormatter(writer, ctx);
}
};
}
public static TreeSerializer toDot(TreeContext ctx) {
return new TreeSerializer(ctx) {
@Override
protected TreeFormatter newFormatter(TreeContext ctx, MetadataSerializers serializer, Writer writer)
throws Exception {
return new DotFormatter(writer, ctx);
}
};
}
public abstract static class AbstractSerializer {
public abstract void writeTo(Writer writer) throws Exception;
public void writeTo(OutputStream writer) throws Exception {
// FIXME Since the stream is already open, we should not close it, however due to semantic issue
// it should stay like this
try (OutputStreamWriter os = new OutputStreamWriter(writer)) {
writeTo(os);
}
}
public String toString() {
try (StringWriter s = new StringWriter()) {
writeTo(s);
return s.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void writeTo(String file) throws Exception {
try (FileWriter w = new FileWriter(file)) {
writeTo(w);
}
}
public void writeTo(File file) throws Exception {
try (FileWriter w = new FileWriter(file)) {
writeTo(w);
}
}
}
public abstract static class TreeSerializer extends AbstractSerializer {
final TreeContext context;
final MetadataSerializers serializers = new MetadataSerializers();
public TreeSerializer(TreeContext ctx) {
context = ctx;
serializers.addAll(ctx.getSerializers());
}
protected abstract TreeFormatter newFormatter(TreeContext ctx, MetadataSerializers serializers, Writer writer)
throws Exception;
public void writeTo(Writer writer) throws Exception {
TreeFormatter formatter = newFormatter(context, serializers, writer);
try {
writeTree(formatter, context.getRoot());
} finally {
formatter.close();
}
}
private void forwardException(Exception e) {
throw new FormatException(e);
}
protected void writeTree(TreeFormatter formatter, ITree root) throws Exception {
formatter.startSerialization();
writeAttributes(formatter, context.getMetadata());
formatter.endProlog();
try {
TreeUtils.visitTree(root, new TreeUtils.TreeVisitor() {
@Override
public void startTree(ITree tree) {
try {
assert tree != null;
formatter.startTree(tree);
writeAttributes(formatter, tree.getMetadata());
formatter.endTreeProlog(tree);
} catch (Exception e) {
forwardException(e);
}
}
@Override
public void endTree(ITree tree) {
try {
formatter.endTree(tree);
} catch (Exception e) {
forwardException(e);
}
}
});
} catch (FormatException e) {
throw e.getCause();
}
formatter.stopSerialization();
}
protected void writeAttributes(TreeFormatter formatter, Iterator<Entry<String, Object>> it) throws Exception {
while (it.hasNext()) {
Entry<String, Object> entry = it.next();
serializers.serialize(formatter, entry.getKey(), entry.getValue());
}
}
public TreeSerializer export(String name, MetadataSerializer serializer) {
serializers.add(name, serializer);
return this;
}
public TreeSerializer export(String... name) {
for (String n: name)
serializers.add(n, Object::toString);
return this;
}
}
public interface TreeFormatter {
void startSerialization() throws Exception;
void endProlog() throws Exception;
void stopSerialization() throws Exception;
void startTree(ITree tree) throws Exception;
void endTreeProlog(ITree tree) throws Exception;
void endTree(ITree tree) throws Exception;
void close() throws Exception;
void serializeAttribute(String name, String value) throws Exception;
}
@FunctionalInterface
public interface MetadataSerializer {
String toString(Object object);
}
@FunctionalInterface
public interface MetadataUnserializer {
Object fromString(String value);
}
static class FormatException extends RuntimeException {
private static final long serialVersionUID = 593766540545763066L;
Exception cause;
public FormatException(Exception cause) {
super(cause);
this.cause = cause;
}
@Override
public Exception getCause() {
return cause;
}
}
static class TreeFormatterAdapter implements TreeFormatter {
protected final TreeContext context;
protected TreeFormatterAdapter(TreeContext ctx) {
context = ctx;
}
@Override
public void startSerialization() throws Exception { }
@Override
public void endProlog() throws Exception { }
@Override
public void startTree(ITree tree) throws Exception { }
@Override
public void endTreeProlog(ITree tree) throws Exception { }
@Override
public void endTree(ITree tree) throws Exception { }
@Override
public void stopSerialization() throws Exception { }
@Override
public void close() throws Exception { }
@Override
public void serializeAttribute(String name, String value) throws Exception { }
}
abstract static class AbsXmlFormatter extends TreeFormatterAdapter {
protected final XMLStreamWriter writer;
protected AbsXmlFormatter(Writer w, TreeContext ctx) throws XMLStreamException {
super(ctx);
XMLOutputFactory f = XMLOutputFactory.newInstance();
writer = new IndentingXMLStreamWriter(f.createXMLStreamWriter(w));
}
@Override
public void startSerialization() throws XMLStreamException {
writer.writeStartDocument();
}
@Override
public void stopSerialization() throws XMLStreamException {
writer.writeEndDocument();
}
@Override
public void close() throws XMLStreamException {
writer.close();
}
}
static class XmlFormatter extends AbsXmlFormatter {
public XmlFormatter(Writer w, TreeContext ctx) throws XMLStreamException {
super(w, ctx);
}
@Override
public void startSerialization() throws XMLStreamException {
super.startSerialization();
writer.writeStartElement("root");
writer.writeStartElement("context");
}
@Override
public void endProlog() throws XMLStreamException {
writer.writeEndElement();
}
@Override
public void stopSerialization() throws XMLStreamException {
writer.writeEndElement();
super.stopSerialization();
}
@Override
public void serializeAttribute(String name, String value) throws XMLStreamException {
writer.writeStartElement(name);
writer.writeCharacters(value);
writer.writeEndElement();
}
@Override
public void startTree(ITree tree) throws XMLStreamException {
writer.writeStartElement("tree");
writer.writeAttribute("type", Integer.toString(tree.getType()));
if (tree.hasLabel()) writer.writeAttribute("label", tree.getLabel());
if (context.hasLabelFor(tree.getType()))
writer.writeAttribute("typeLabel", context.getTypeLabel(tree.getType()));
if (ITree.NO_VALUE != tree.getPos()) {
writer.writeAttribute("pos", Integer.toString(tree.getPos()));
writer.writeAttribute("length", Integer.toString(tree.getLength()));
}
}
@Override
public void endTree(ITree tree) throws XMLStreamException {
writer.writeEndElement();
}
}
static class XmlAnnotatedFormatter extends XmlFormatter {
final SearchOther searchOther;
public XmlAnnotatedFormatter(Writer w, TreeContext ctx, boolean isSrc,
MappingStore m) throws XMLStreamException {
super(w, ctx);
if (isSrc)
searchOther = (tree) -> m.hasSrc(tree) ? m.getDst(tree) : null;
else
searchOther = (tree) -> m.hasDst(tree) ? m.getSrc(tree) : null;
}
interface SearchOther {
ITree lookup(ITree tree);
}
@Override
public void startTree(ITree tree) throws XMLStreamException {
super.startTree(tree);
ITree o = searchOther.lookup(tree);
if (o != null) {
if (ITree.NO_VALUE != o.getPos()) {
writer.writeAttribute("other_pos", Integer.toString(o.getPos()));
writer.writeAttribute("other_length", Integer.toString(o.getLength()));
}
}
}
}
static class XmlCompactFormatter extends AbsXmlFormatter {
public XmlCompactFormatter(Writer w, TreeContext ctx) throws XMLStreamException {
super(w, ctx);
}
@Override
public void startSerialization() throws XMLStreamException {
super.startSerialization();
writer.writeStartElement("root");
}
@Override
public void stopSerialization() throws XMLStreamException {
writer.writeEndElement();
super.stopSerialization();
}
@Override
public void serializeAttribute(String name, String value) throws XMLStreamException {
writer.writeAttribute(name, value);
}
@Override
public void startTree(ITree tree) throws XMLStreamException {
if (tree.getChildren().size() == 0)
writer.writeEmptyElement(context.getTypeLabel(tree.getType()));
else
writer.writeStartElement(context.getTypeLabel(tree.getType()));
if (tree.hasLabel())
writer.writeAttribute("label", tree.getLabel());
}
@Override
public void endTree(ITree tree) throws XMLStreamException {
if (tree.getChildren().size() > 0)
writer.writeEndElement();
}
}
static class LispFormatter extends TreeFormatterAdapter {
protected final Writer writer;
protected final Pattern replacer = Pattern.compile("[\\\\\"]");
int level = 0;
protected LispFormatter(Writer w, TreeContext ctx) {
super(ctx);
writer = w;
}
@Override
public void startSerialization() throws IOException {
writer.write("((");
}
@Override
public void startTree(ITree tree) throws IOException {
if (!tree.isRoot())
writer.write("\n");
for (int i = 0; i < level; i ++)
writer.write(" ");
level ++;
String pos = (ITree.NO_VALUE == tree.getPos() ? "" : String.format("(%d %d)",
tree.getPos(), tree.getLength()));
writer.write(String.format("(%d %s %s (%s",
tree.getType(), protect(context.getTypeLabel(tree)), protect(tree.getLabel()), pos));
}
@Override
public void endProlog() throws Exception {
writer.append(") ");
}
@Override
public void endTreeProlog(ITree tree) throws Exception {
writer.append(") (");
}
@Override
public void serializeAttribute(String name, String value) throws Exception {
writer.append(String.format("(:%s %s) ", name, protect(value)));
}
protected String protect(String val) {
return String.format("\"%s\"", replacer.matcher(val).replaceAll("\\\\$0"));
}
@Override
public void endTree(ITree tree) throws IOException {
writer.write(")");
level --;
}
@Override
public void stopSerialization() throws IOException {
writer.write(")");
}
}
static class DotFormatter extends TreeFormatterAdapter {
protected final Writer writer;
protected DotFormatter(Writer w, TreeContext ctx) {
super(ctx);
writer = w;
}
@Override
public void startSerialization() throws Exception {
writer.write("digraph G {\n");
}
@Override
public void startTree(ITree tree) throws Exception {
String label = tree.toPrettyString(context);
if (label.contains("\"") || label.contains("\\s"))
label = label.replaceAll("\"", "").replaceAll("\\s", "").replaceAll("\\\\", "");
if (label.length() > 30)
label = label.substring(0, 30);
writer.write(tree.getId() + " [label=\"" + label + "\"];\n");
if (tree.getParent() != null)
writer.write(tree.getParent().getId() + " -> " + tree.getId() + ";\n");
}
@Override
public void stopSerialization() throws Exception {
writer.write("}");
}
}
static class JsonFormatter extends TreeFormatterAdapter {
private final JsonWriter writer;
public JsonFormatter(Writer w, TreeContext ctx) {
super(ctx);
writer = new JsonWriter(w);
writer.setIndent(" ");
}
@Override
public void startTree(ITree t) throws IOException {
writer.beginObject();
writer.name("type").value(Integer.toString(t.getType()));
if (t.hasLabel()) writer.name("label").value(t.getLabel());
if (context.hasLabelFor(t.getType())) writer.name("typeLabel").value(context.getTypeLabel(t.getType()));
if (ITree.NO_VALUE != t.getPos()) {
writer.name("pos").value(Integer.toString(t.getPos()));
writer.name("length").value(Integer.toString(t.getLength()));
}
}
@Override
public void endTreeProlog(ITree tree) throws IOException {
writer.name("children");
writer.beginArray();
}
@Override
public void endTree(ITree tree) throws IOException {
writer.endArray();
writer.endObject();
}
@Override
public void startSerialization() throws IOException {
writer.beginObject();
writer.setIndent("\t");
}
@Override
public void endProlog() throws IOException {
writer.name("root");
}
@Override
public void serializeAttribute(String key, String value) throws IOException {
writer.name(key).value(value);
}
@Override
public void stopSerialization() throws IOException {
writer.endObject();
}
@Override
public void close() throws IOException {
writer.close();
}
}
@Register(id = "xml", accept = "\\.gxml$")
// TODO Since it is not in the right package, I'm not even sure it is visible in the registry
// TODO should we move this class elsewhere (another package)
public static class XmlInternalGenerator extends TreeGenerator {
static MetadataUnserializers defaultUnserializers = new MetadataUnserializers();
final MetadataUnserializers unserializers = new MetadataUnserializers(); // FIXME should it be pushed up or not?
private static final QName TYPE = new QName("type");
private static final QName LABEL = new QName("label");
private static final QName TYPE_LABEL = new QName("typeLabel");
private static final String POS = "pos";
private static final String LENGTH = "length";
private static final String LINE_BEFORE = "line_before";
private static final String LINE_AFTER = "line_after";
static {
// defaultUnserializers.add(POS, Integer::parseInt);
// defaultUnserializers.add(LENGTH, Integer::parseInt);
defaultUnserializers.add(LINE_BEFORE, Integer::parseInt);
defaultUnserializers.add(LINE_AFTER, Integer::parseInt);
}
public static <T, E> List<T> getKeysByValue(Map<T, E> map, E value) {
return map.entrySet()
.stream()
.filter(entry -> Objects.equals(entry.getValue(), value))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
public XmlInternalGenerator() {
unserializers.addAll(defaultUnserializers);
}
@Override
protected TreeContext generate(Reader source) throws IOException {
XMLInputFactory fact = XMLInputFactory.newInstance();
TreeContext context = new TreeContext();
try {
Stack<ITree> trees = new Stack<>();
XMLEventReader r = fact.createXMLEventReader(source);
while (r.hasNext()) {
XMLEvent e = r.nextEvent();
if (e instanceof StartElement) {
StartElement s = (StartElement) e;
if (!s.getName().getLocalPart().equals("tree")) // FIXME need to deal with options
continue;
// int type = Integer.parseInt(s.getAttributeByName(TYPE).getValue());
List<Integer> keysByValue = getKeysByValue(CNodeMap.map, s.getAttributeByName(TYPE).getValue());
int type = keysByValue.get(0);
ITree t = context.createTree(type,
labelForAttribute(s, LABEL), labelForAttribute(s, TYPE_LABEL));
// FIXME this iterator has no type, due to the API. We have to cast it later
Iterator<?> it = s.getAttributes();
while (it.hasNext()) {
Attribute a = (Attribute) it.next();
unserializers.load(t, a.getName().getLocalPart(), a.getValue());
}
if (trees.isEmpty())
context.setRoot(t);
else
t.setParentAndUpdateChildren(trees.peek());
trees.push(t);
} else if (e instanceof EndElement) {
if (!((EndElement)e).getName().getLocalPart().equals("tree")) // FIXME need to deal with options
continue;
trees.pop();
}
}
context.validate();
return context;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected TreeContext generate(Reader source, int astParserType) throws IOException {
return generate(source);
}
private static String labelForAttribute(StartElement s, QName attrName) {
Attribute attr = s.getAttributeByName(attrName);
return attr == null ? ITree.NO_LABEL : attr.getValue();
}
public MetadataUnserializers getUnserializers() {
return unserializers;
}
}
}
@@ -0,0 +1,40 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.matchers;
import com.github.gumtreediff.tree.ITree;
public class CompositeMatcher extends Matcher {
protected final Matcher[] matchers;
public CompositeMatcher(ITree src, ITree dst, MappingStore store, Matcher[] matchers) {
super(src, dst, store);
this.matchers = matchers;
}
public void match() {
for (Matcher matcher : matchers) {
matcher.match();
}
}
}
@@ -0,0 +1,78 @@
/*
* This file is part of GumTree.
*
* GumTree is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GumTree 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GumTree. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2011-2015 Jean-Rémy Falleri <jr.falleri@gmail.com>
* Copyright 2011-2015 Floréal Morandat <florealm@gmail.com>
*/
package com.github.gumtreediff.matchers;
import com.github.gumtreediff.gen.Registry;
import com.github.gumtreediff.matchers.heuristic.cd.ChangeDistillerBottomUpMatcher;
import com.github.gumtreediff.matchers.heuristic.cd.ChangeDistillerLeavesMatcher;
import com.github.gumtreediff.matchers.heuristic.gt.CompleteBottomUpMatcher;
import com.github.gumtreediff.matchers.heuristic.XyBottomUpMatcher;
import com.github.gumtreediff.matchers.heuristic.gt.CliqueSubtreeMatcher;
import com.github.gumtreediff.matchers.heuristic.gt.GreedyBottomUpMatcher;
import com.github.gumtreediff.matchers.heuristic.gt.GreedySubtreeMatcher;
import com.github.gumtreediff.tree.ITree;
public class CompositeMatchers {
@Register(id = "gumtree", defaultMatcher = true, priority = Registry.Priority.HIGH)
public static class ClassicGumtree extends CompositeMatcher {
public ClassicGumtree(ITree src, ITree dst, MappingStore store) {
super(src, dst, store, new Matcher[]{
new GreedySubtreeMatcher(src, dst, store),
new GreedyBottomUpMatcher(src, dst, store)
});
}
}
@Register(id = "gumtree-complete")
public static class CompleteGumtreeMatcher extends CompositeMatcher {
public CompleteGumtreeMatcher(ITree src, ITree dst, MappingStore store) {
super(src, dst, store, new Matcher[]{
new CliqueSubtreeMatcher(src, dst, store),
new CompleteBottomUpMatcher(src, dst, store)
});
}
}
@Register(id = "change-distiller")
public static class ChangeDistiller extends CompositeMatcher {
public ChangeDistiller(ITree src, ITree dst, MappingStore store) {
super(src, dst, store, new Matcher[]{
new ChangeDistillerLeavesMatcher(src, dst, store),
new ChangeDistillerBottomUpMatcher(src, dst, store)
});
}
}
@Register(id = "xy")
public static class XyMatcher extends CompositeMatcher {
public XyMatcher(ITree src, ITree dst, MappingStore store) {
super(src, dst, store, new Matcher[]{
new GreedySubtreeMatcher(src, dst, store),
new XyBottomUpMatcher(src, dst, store)
});
}
}
}

Some files were not shown because too many files have changed in this diff Show More