++
сравнение
This commit is contained in:
211
src/com/github/difflib/unifieddiff/UnifiedDiffWriter.java
Normal file
211
src/com/github/difflib/unifieddiff/UnifiedDiffWriter.java
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright 2019 java-diff-utils.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.github.difflib.unifieddiff;
|
||||
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @todo use an instance to store contextSize and originalLinesProvider.
|
||||
* @author Tobias Warneke (t.warneke@gmx.net)
|
||||
*/
|
||||
public class UnifiedDiffWriter {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(UnifiedDiffWriter.class.getName());
|
||||
|
||||
public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Writer writer, int contextSize) throws IOException {
|
||||
Objects.requireNonNull(originalLinesProvider, "original lines provider needs to be specified");
|
||||
write(diff, originalLinesProvider, line -> {
|
||||
try {
|
||||
writer.append(line).append("\n");
|
||||
} catch (IOException ex) {
|
||||
LOG.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}, contextSize);
|
||||
}
|
||||
|
||||
public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Consumer<String> writer, int contextSize) throws IOException {
|
||||
if (diff.getHeader() != null) {
|
||||
writer.accept(diff.getHeader());
|
||||
}
|
||||
|
||||
for (UnifiedDiffFile file : diff.getFiles()) {
|
||||
List<AbstractDelta<String>> patchDeltas = new ArrayList<>(
|
||||
file.getPatch().getDeltas());
|
||||
if (!patchDeltas.isEmpty()) {
|
||||
writeOrNothing(writer, file.getDiffCommand());
|
||||
if (file.getIndex() != null) {
|
||||
writer.accept("index " + file.getIndex());
|
||||
}
|
||||
|
||||
writer.accept("--- " + (file.getFromFile() == null ? "/dev/null" : file.getFromFile()));
|
||||
|
||||
if (file.getToFile() != null) {
|
||||
writer.accept("+++ " + file.getToFile());
|
||||
}
|
||||
|
||||
List<String> originalLines = originalLinesProvider.apply(file.getFromFile());
|
||||
|
||||
List<AbstractDelta<String>> deltas = new ArrayList<>();
|
||||
|
||||
AbstractDelta<String> delta = patchDeltas.get(0);
|
||||
deltas.add(delta); // add the first Delta to the current set
|
||||
// if there's more than 1 Delta, we may need to output them together
|
||||
if (patchDeltas.size() > 1) {
|
||||
for (int i = 1; i < patchDeltas.size(); i++) {
|
||||
int position = delta.getSource().getPosition();
|
||||
|
||||
// Check if the next Delta is too close to the current
|
||||
// position.
|
||||
// And if it is, add it to the current set
|
||||
AbstractDelta<String> nextDelta = patchDeltas.get(i);
|
||||
if ((position + delta.getSource().size() + contextSize) >= (nextDelta
|
||||
.getSource().getPosition() - contextSize)) {
|
||||
deltas.add(nextDelta);
|
||||
} else {
|
||||
// if it isn't, output the current set,
|
||||
// then create a new set and add the current Delta to
|
||||
// it.
|
||||
processDeltas(writer, originalLines, deltas, contextSize, false);
|
||||
deltas.clear();
|
||||
deltas.add(nextDelta);
|
||||
}
|
||||
delta = nextDelta;
|
||||
}
|
||||
|
||||
}
|
||||
// don't forget to process the last set of Deltas
|
||||
processDeltas(writer, originalLines, deltas, contextSize,
|
||||
patchDeltas.size() == 1 && file.getFromFile() == null);
|
||||
}
|
||||
|
||||
}
|
||||
if (diff.getTail() != null) {
|
||||
writer.accept("--");
|
||||
writer.accept(diff.getTail());
|
||||
}
|
||||
}
|
||||
|
||||
private static void processDeltas(Consumer<String> writer,
|
||||
List<String> origLines, List<AbstractDelta<String>> deltas,
|
||||
int contextSize, boolean newFile) {
|
||||
List<String> buffer = new ArrayList<>();
|
||||
int origTotal = 0; // counter for total lines output from Original
|
||||
int revTotal = 0; // counter for total lines output from Original
|
||||
int line;
|
||||
|
||||
AbstractDelta<String> curDelta = deltas.get(0);
|
||||
|
||||
int origStart;
|
||||
if (newFile) {
|
||||
origStart = 0;
|
||||
} else {
|
||||
// NOTE: +1 to overcome the 0-offset Position
|
||||
origStart = curDelta.getSource().getPosition() + 1 - contextSize;
|
||||
if (origStart < 1) {
|
||||
origStart = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int revStart = curDelta.getTarget().getPosition() + 1 - contextSize;
|
||||
if (revStart < 1) {
|
||||
revStart = 1;
|
||||
}
|
||||
|
||||
// find the start of the wrapper context code
|
||||
int contextStart = curDelta.getSource().getPosition() - contextSize;
|
||||
if (contextStart < 0) {
|
||||
contextStart = 0; // clamp to the start of the file
|
||||
}
|
||||
|
||||
// output the context before the first Delta
|
||||
for (line = contextStart; line < curDelta.getSource().getPosition()
|
||||
&& line < origLines.size(); line++) { //
|
||||
buffer.add(" " + origLines.get(line));
|
||||
origTotal++;
|
||||
revTotal++;
|
||||
}
|
||||
// output the first Delta
|
||||
getDeltaText(txt -> buffer.add(txt), curDelta);
|
||||
origTotal += curDelta.getSource().getLines().size();
|
||||
revTotal += curDelta.getTarget().getLines().size();
|
||||
|
||||
int deltaIndex = 1;
|
||||
while (deltaIndex < deltas.size()) { // for each of the other Deltas
|
||||
AbstractDelta<String> nextDelta = deltas.get(deltaIndex);
|
||||
int intermediateStart = curDelta.getSource().getPosition()
|
||||
+ curDelta.getSource().getLines().size();
|
||||
for (line = intermediateStart; line < nextDelta.getSource().getPosition()
|
||||
&& line < origLines.size(); line++) {
|
||||
// output the code between the last Delta and this one
|
||||
buffer.add(" " + origLines.get(line));
|
||||
origTotal++;
|
||||
revTotal++;
|
||||
}
|
||||
getDeltaText(txt -> buffer.add(txt), nextDelta); // output the Delta
|
||||
origTotal += nextDelta.getSource().getLines().size();
|
||||
revTotal += nextDelta.getTarget().getLines().size();
|
||||
curDelta = nextDelta;
|
||||
deltaIndex++;
|
||||
}
|
||||
|
||||
// Now output the post-Delta context code, clamping the end of the file
|
||||
contextStart = curDelta.getSource().getPosition()
|
||||
+ curDelta.getSource().getLines().size();
|
||||
for (line = contextStart; (line < (contextStart + contextSize))
|
||||
&& (line < origLines.size()); line++) {
|
||||
buffer.add(" " + origLines.get(line));
|
||||
origTotal++;
|
||||
revTotal++;
|
||||
}
|
||||
|
||||
// Create and insert the block header, conforming to the Unified Diff
|
||||
// standard
|
||||
writer.accept("@@ -" + origStart + "," + origTotal + " +" + revStart + "," + revTotal + " @@");
|
||||
buffer.forEach(txt -> {
|
||||
writer.accept(txt);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter.
|
||||
*
|
||||
* @param writer consumer for the list of String lines of code
|
||||
* @param delta the Delta to output
|
||||
*/
|
||||
private static void getDeltaText(Consumer<String> writer, AbstractDelta<String> delta) {
|
||||
for (String line : delta.getSource().getLines()) {
|
||||
writer.accept("-" + line);
|
||||
}
|
||||
for (String line : delta.getTarget().getLines()) {
|
||||
writer.accept("+" + line);
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeOrNothing(Consumer<String> writer, String str) throws IOException {
|
||||
if (str != null) {
|
||||
writer.accept(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user