private void writeDeltas(final String query, final File file, final List<Delta> deltas) throws IOException { LOGGER.info("Creating {}", file.getAbsolutePath()); BufferedOutputStream os = null; try { os = new BufferedOutputStream(new FileOutputStream(file)); os.write(query.getBytes(Charsets.UTF_8)); os.write("\n\n".getBytes(Charsets.UTF_8)); for (final Delta delta : deltas) { final Chunk original = delta.getOriginal(); final Chunk revised = delta.getRevised(); os.write( String.format( "\n\n" + "---------- 1 (position %d, size %d) ----------\n\n%s\n\n" + "---------- 2 (position %d, size %d) ----------\n\n%s\n\n", original.getPosition(), original.size(), original.getLines(), revised.getPosition(), revised.size(), revised.getLines()) .getBytes(Charsets.UTF_8)); } } finally { if (os != null) { os.close(); } } }
/** * Remove unwanted deltas. * * @param diff Patch to filter. * @return Patch with unwanted deltas removed. * @todo #469:30min Remove the method below and find a way to format tags correctly in XML. * Attributes should be indented by 4 spaces, just like XML tags, but in IT xml-violations * there is a tag that our Prettifier want to be indented by 3 spaces which is wrong. Another * problem is that in the parent tag, attributes are indented to match the first attribute, * this is also wrong - all attributes on new line should be indented by 4 spaces. */ private static Patch filter(final Patch diff) { final Patch patch = new Patch(); for (final Delta delta : diff.getDeltas()) { final List<?> prev = delta.getOriginal().getLines(); if (prev.size() != 1 || delta.getRevised().getLines().size() != 1 || !XmlValidator.ATTRS_PATTERN.matcher(prev.get(0).toString()).matches()) { patch.addDelta(delta); } } return patch; }
private boolean isInsert(Delta delta) { boolean original_is_blank = true; for (Object l : delta.getOriginal().getLines()) { String line = (String) l; if (!line.matches("[\\t\\s\\n]*")) { original_is_blank = false; } } return original_is_blank || delta.getType() == Delta.TYPE.INSERT; }
private boolean isDelete(Delta delta) { boolean replacement_is_blank = true; for (Object l : delta.getRevised().getLines()) { String line = (String) l; if (!line.matches("^[\\t\\s\\n]*$")) { replacement_is_blank = false; } } return replacement_is_blank || delta.getType() == Delta.TYPE.DELETE; }
/** * Generate source different count elements * * @param sourceDiffFile The source differences * @param root Root element where the generated element will be placed */ private void generateSourceDifferenceCount(DiffFile sourceDiffFile, Element root) { int removedLinesCount = 0, addedLinesCount = 0; for (Delta sourceDiff : sourceDiffFile.getChanges()) { if (sourceDiff.getType() == TYPE.CHANGE) { removedLinesCount += sourceDiff.getOriginal().size(); addedLinesCount += sourceDiff.getRevised().size(); } else if (sourceDiff.getType() == TYPE.DELETE) { removedLinesCount += sourceDiff.getOriginal().size(); } else if (sourceDiff.getType() == TYPE.INSERT) { addedLinesCount += sourceDiff.getRevised().size(); } } int totalLinesChangedCount = sourceDiffFile.getRevisedLineCount() - sourceDiffFile.getOriginalLineCount(); double totalPercentage = 100.0; if (sourceDiffFile.getOriginalLineCount() > 0) { totalPercentage = Math.round( (double) totalLinesChangedCount / (double) sourceDiffFile.getOriginalLineCount() * (double) 10000) / (double) 100; } root.setAttribute("sizeChange", totalLinesChangedCount + " (" + totalPercentage + "%)"); if (removedLinesCount > 0) { Element removedLines = doc.createElement("removedLineCount"); double percentage = Math.round( (double) removedLinesCount / (double) sourceDiffFile.getOriginalLineCount() * (double) 10000) / (double) 100; removedLines.appendChild(doc.createTextNode(removedLinesCount + " (" + percentage + "%)")); root.appendChild(removedLines); } if (addedLinesCount > 0) { Element addedLines = doc.createElement("addedLineCount"); double percentage = 100.0; if (sourceDiffFile.getOriginalLineCount() > 0) { percentage = Math.round( (double) addedLinesCount / (double) sourceDiffFile.getOriginalLineCount() * (double) 10000) / (double) 100; } addedLines.appendChild(doc.createTextNode(addedLinesCount + " (" + percentage + "%)")); root.appendChild(addedLines); } }
@Test public void testWholeInsert() { String s1 = ""; String s2 = "And this has been added. That quick brown fox jumped over a lazy dog. " + "This sentence stays the same. " + "And this has been newly added. This will be the same."; String[] l1 = s1.split("\\s"); String[] l2 = s2.split("\\s"); difflib.Patch patch = DiffUtils.diff(Arrays.asList(l1), Arrays.asList(l2)); System.out.println(patch.getDeltas().size()); for (Delta delta : patch.getDeltas()) { System.out.println(delta.getRevised().getLines() + "\t" + delta.getType()); } }
@Test public void testNewAlgo() { List<String> original = new ArrayList<>(); original.add("The quick brown fox jumps over the lazy dog"); original.add("This sentence stays the same"); original.add("But this will be removed."); original.add("This will be the same."); List<String> revised = new ArrayList<>(); revised.add("And this has been added."); revised.add("That quick brown fox jumped over a lazy dog."); revised.add("This sentence stays the same"); revised.add("And this has been newly added."); revised.add("This will be the same."); // Compute diff. Get the Patch object. Patch is the container for computed deltas. difflib.Patch patch = DiffUtils.diff(original, revised); System.out.println(patch.getDeltas().size()); for (Delta delta : patch.getDeltas()) { System.out.println(delta + "\t" + delta.getType() + delta.getOriginal().getLines()); } }
@Override public List<Diff> perform(SuperResource left, SuperResource right) { String left_string = left.getContents(); String right_string = right.getContents(); List<String> original = stringToLines(left_string); List<String> revised = stringToLines(right_string); // Compute diff. Get the Patch object. Patch is the container for computed deltas. Patch patch = DiffUtils.diff(original, revised); List<Diff> ret = new ArrayList<Diff>(); for (Delta delta : patch.getDeltas()) { if (isDelete(delta)) { // If multiple lines were removed, treat it as multiple removals of single lines. int pos = delta.getOriginal().getPosition(); for (Object l : delta.getOriginal().getLines()) { String line = (String) l; ArrayList<String> line_array = new ArrayList<String>(); line_array.add(line); Chunk c = new Chunk(pos++, line_array); Delta new_delta = new DeleteDelta(c, delta.getRevised()); Diff diff = new SimpleTextDiff(new_delta, original, revised, delimiter); diff.setParent(this); ret.add(diff); } } else if (isInsert(delta)) { // If multiple lines were inserted, treat it as multiple inserts of single lines. int pos = delta.getRevised().getPosition(); for (Object l : delta.getRevised().getLines()) { String line = (String) l; ArrayList<String> line_array = new ArrayList<String>(); line_array.add(line); Chunk c = new Chunk(pos++, line_array); Delta new_delta = new InsertDelta(delta.getOriginal(), c); Diff diff = new SimpleTextDiff(new_delta, original, revised, delimiter); diff.setParent(this); ret.add(diff); } } else { Diff diff = new SimpleTextDiff(delta, original, revised, delimiter); diff.setParent(this); ret.add(diff); } } // Now we diff the compiler messages. List<CompilerMessage> original_messages = left.getCompilerMessages(); List<CompilerMessage> revised_messages = right.getCompilerMessages(); Patch messages_patch = DiffUtils.diff(original_messages, revised_messages); for (Delta delta : messages_patch.getDeltas()) { Diff diff = new SimpleMessageDiff(delta, original, revised, delimiter); diff.setParent(this); ret.add(diff); } return ret; }
/** * Generate a summary of the coverage and source differences of the comparison * * @param summaryRoot */ public void generateSummary(Element summaryRoot) { Element classChanges = doc.createElement("classChanges"); Element testChanges = doc.createElement("testChanges"); List<OperiasFile> changedClasses = report.getChangedClasses(); int totalRelevantLineCountRemoved = 0, totalRelevantLineCountAdded = 0; int totalRelevantLineCountCoveredAndRemoved = 0, totalRelevantLineCountCoveredAndAdded = 0; for (OperiasFile changedClass : changedClasses) { List<OperiasChange> changes = changedClass.getChanges(); // Collect all numbers for (OperiasChange change : changes) { // Either there is a change, else no source changes were found, which means that only the // coverage changed if (change.getSourceDiffDelta() != null) { if (change.getSourceDiffDelta().getType() == TYPE.DELETE || change.getSourceDiffDelta().getType() == TYPE.CHANGE) { totalRelevantLineCountRemoved += change.countOriginalRelevantLines(); totalRelevantLineCountCoveredAndRemoved += change.countOriginalLinesCovered(); } if (change.getSourceDiffDelta().getType() == TYPE.INSERT || change.getSourceDiffDelta().getType() == TYPE.CHANGE) { totalRelevantLineCountAdded += change.countRevisedRelevantLines(); totalRelevantLineCountCoveredAndAdded += change.countRevisedLinesCovered(); } } } } Element coverageChanges = doc.createElement("coverageChanges"); coverageChanges.setAttribute( "originalLineRate", report.getOriginalCoverageReport().getLineRate() + ""); coverageChanges.setAttribute( "originalConditionRate", report.getOriginalCoverageReport().getConditionRate() + ""); coverageChanges.setAttribute( "revisedLineRate", report.getRevisedCoverageReport().getLineRate() + ""); coverageChanges.setAttribute( "revisedConditionRate", report.getRevisedCoverageReport().getConditionRate() + ""); // Element for removed lines if (totalRelevantLineCountRemoved > 0) { Element coverableLinesRemoved = doc.createElement("totalCoverableLinesRemoved"); Element coverableLinesRemovedCount = doc.createElement("lineCount"); Element coverableLinesRemovedPercentage = doc.createElement("lineRate"); coverableLinesRemovedCount.appendChild( doc.createTextNode("" + totalRelevantLineCountRemoved)); coverableLinesRemovedPercentage.appendChild( doc.createTextNode( "" + Math.round( (double) totalRelevantLineCountCoveredAndRemoved / (double) totalRelevantLineCountRemoved * 100.0f) / (double) 100)); coverableLinesRemoved.appendChild(coverableLinesRemovedCount); coverableLinesRemoved.appendChild(coverableLinesRemovedPercentage); coverageChanges.appendChild(coverableLinesRemoved); } // Elements for added lines if (totalRelevantLineCountAdded > 0) { Element coverableLinesAdded = doc.createElement("totalCoverableLinesAdded"); Element coverableLinesAddedCount = doc.createElement("lineCount"); Element coverableLinesAddedPercentage = doc.createElement("lineRate"); coverableLinesAddedCount.appendChild(doc.createTextNode("" + totalRelevantLineCountAdded)); coverableLinesAddedPercentage.appendChild( doc.createTextNode( "" + Math.round( (double) totalRelevantLineCountCoveredAndAdded / (double) totalRelevantLineCountAdded * 100.0f) / (double) 100)); coverableLinesAdded.appendChild(coverableLinesAddedCount); coverableLinesAdded.appendChild(coverableLinesAddedPercentage); coverageChanges.appendChild(coverableLinesAdded); } classChanges.appendChild(coverageChanges); // Collect a summary of source changes int totalClassSourceLinesAdded = 0, totalClassSourceLinesRemoved = 0; int totalClassSourceLinesOriginal = 0; for (OperiasFile classFile : report.getChangedClasses()) { totalClassSourceLinesOriginal += classFile.getSourceDiff().getOriginalLineCount(); for (Delta sourceDiff : classFile.getSourceDiff().getChanges()) { if (sourceDiff.getType() == TYPE.CHANGE) { totalClassSourceLinesRemoved += sourceDiff.getOriginal().size(); totalClassSourceLinesAdded += sourceDiff.getRevised().size(); } else if (sourceDiff.getType() == TYPE.DELETE) { totalClassSourceLinesRemoved += sourceDiff.getOriginal().size(); } else if (sourceDiff.getType() == TYPE.INSERT) { totalClassSourceLinesAdded += sourceDiff.getRevised().size(); } } } // All counts collected Element classSourceChanges = doc.createElement("sourceChanges"); Element classSourceLinesAdded = doc.createElement("addedLineCount"); Element classSourceLinesRemoved = doc.createElement("removedLineCount"); classSourceLinesAdded.appendChild( doc.createTextNode( totalClassSourceLinesAdded + " (" + Math.round( (double) totalClassSourceLinesAdded / (double) totalClassSourceLinesOriginal * (double) 10000) / (double) 100 + "%)")); classSourceLinesRemoved.appendChild( doc.createTextNode( totalClassSourceLinesRemoved + " (" + Math.round( (double) totalClassSourceLinesRemoved / (double) totalClassSourceLinesOriginal * (double) 10000) / (double) 100 + "%)")); classSourceChanges.appendChild(classSourceLinesAdded); classSourceChanges.appendChild(classSourceLinesRemoved); classChanges.appendChild(classSourceChanges); summaryRoot.appendChild(classChanges); // Collect a summary of source changes totalClassSourceLinesAdded = 0; totalClassSourceLinesRemoved = 0; totalClassSourceLinesOriginal = 0; for (DiffFile testFile : report.getChangedTests()) { totalClassSourceLinesOriginal += testFile.getOriginalLineCount(); for (Delta sourceDiff : testFile.getChanges()) { if (sourceDiff.getType() == TYPE.CHANGE) { totalClassSourceLinesRemoved += sourceDiff.getOriginal().size(); totalClassSourceLinesAdded += sourceDiff.getRevised().size(); } else if (sourceDiff.getType() == TYPE.DELETE) { totalClassSourceLinesRemoved += sourceDiff.getOriginal().size(); } else if (sourceDiff.getType() == TYPE.INSERT) { totalClassSourceLinesAdded += sourceDiff.getRevised().size(); } } } // All counts collected Element testSourceChanges = doc.createElement("sourceChanges"); Element testSourceLinesAdded = doc.createElement("addedLineCount"); Element testSourceLinesRemoved = doc.createElement("removedLineCount"); testSourceLinesAdded.appendChild( doc.createTextNode( totalClassSourceLinesAdded + " (" + Math.round( (double) totalClassSourceLinesAdded / (double) totalClassSourceLinesOriginal * (double) 10000) / (double) 100 + "%)")); testSourceLinesRemoved.appendChild( doc.createTextNode( totalClassSourceLinesRemoved + " (" + Math.round( (double) totalClassSourceLinesRemoved / (double) totalClassSourceLinesOriginal * (double) 10000) / (double) 100 + "%)")); testSourceChanges.appendChild(testSourceLinesAdded); testSourceChanges.appendChild(testSourceLinesRemoved); testChanges.appendChild(testSourceChanges); summaryRoot.appendChild(testChanges); }