Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion team/bundles/org.eclipse.compare/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ Export-Package: org.eclipse.compare;
org.eclipse.ui,
org.eclipse.ui.services,
org.eclipse.ui.texteditor",
org.eclipse.compare.unifieddiff;x-internal:=true
org.eclipse.compare.unifieddiff;x-internal:=true,
org.eclipse.compare.unifieddiff.internal;x-friends:="org.eclipse.team.tests.core"
Require-Bundle: org.eclipse.ui;bundle-version="[3.206.0,4.0.0)",
org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
org.eclipse.jface.text;bundle-version="[3.8.0,4.0.0)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@

import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.error;
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.isOverlay;
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffText.countLines;
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffText.mapOffsetToTabExpanded;
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffText.mergeStyleRanges;
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffText.removeLeadingNewLines;
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffText.removeTrailingNewLines;
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffText.replaceTabWithSpaces;

import java.lang.reflect.Method;
import java.util.ArrayList;
Expand Down Expand Up @@ -377,28 +383,6 @@ public UnifiedDiffLineHeaderCodeMining(Position position, ICodeMiningProvider pr
((MouseClickConsumer) getAction()).setCodeMining(this);
}

private static String removeTrailingNewLines(String str) {
if (str == null) {
return str;
}
int end = str.length();
while (end > 0 && (str.charAt(end - 1) == '\n' || str.charAt(end - 1) == '\r')) {
end--;
}
return end == str.length() ? str : str.substring(0, end);
}

private static String removeLeadingNewLines(String str) {
if (str == null) {
return str;
}
int start = 0;
while (start < str.length() && (str.charAt(start) == '\n' || str.charAt(start) == '\r')) {
start++;
}
return start == 0 ? str : str.substring(start);
}

private static final class ForegroundInfo {

final int x;
Expand Down Expand Up @@ -470,58 +454,6 @@ public void keyPressed(KeyEvent e) {
setTextEditorActionsActivated(false);
}

private List<StyleRange> mergeStyleRanges(List<StyleRange> backgrounds, List<StyleRange> foregrounds) {
if (backgrounds.isEmpty()) {
return foregrounds;
}
if (foregrounds.isEmpty()) {
return backgrounds;
}
List<StyleRange> result = new ArrayList<>();
int bgIdx = 0;
for (StyleRange fg : foregrounds) {
int fgStart = fg.start;
int fgEnd = fg.start + fg.length;
int pos = fgStart;
while (pos < fgEnd && bgIdx < backgrounds.size()) {
StyleRange bg = backgrounds.get(bgIdx);
int bgStart = bg.start;
int bgEnd = bg.start + bg.length;
if (bgEnd <= pos) {
bgIdx++;
continue;
}
if (bgStart >= fgEnd) {
break;
}
if (bgStart > pos) {
result.add(createRange(fg, pos, bgStart - pos, null));
pos = bgStart;
}
int overlapEnd = Math.min(bgEnd, fgEnd);
result.add(createRange(fg, pos, overlapEnd - pos, bg.background));
pos = overlapEnd;
if (bgEnd <= fgEnd) {
bgIdx++;
}
}
if (pos < fgEnd) {
result.add(createRange(fg, pos, fgEnd - pos, null));
}
}
return result;
}

private StyleRange createRange(StyleRange base, int start, int length, Color background) {
StyleRange r = (StyleRange) base.clone();
r.start = start;
r.length = length;
if (background != null) {
r.background = background;
}
return r;
}

private List<StyleRange> createDetailedDiffBackgroundRanges(UnifiedDiffLineHeaderCodeMining miningParam,
String txt) {
List<StyleRange> ranges = new ArrayList<>();
Expand Down Expand Up @@ -566,17 +498,6 @@ private List<StyleRange> createDetailedDiffBackgroundRanges(UnifiedDiffLineHeade
return ranges;
}

private static int mapOffsetToTabExpanded(String originalStr, int offset, int tabWidth) {
int tabCount = 0;
int limit = Math.min(offset, originalStr.length());
for (int i = 0; i < limit; i++) {
if (originalStr.charAt(i) == '\t') {
tabCount++;
}
}
return offset + tabCount * (tabWidth - 1);
}

private void setTextEditorActionsActivated(boolean state) {
IEditorPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
.getActiveEditor();
Expand Down Expand Up @@ -729,9 +650,10 @@ public Point draw(GC gc, StyledText textWidget, Color color, int x, int y) {
}
try {
var rangeInfo = new RangeInfo(-1, -1, null);
String l = diffStr.substring(0, detailedDiffStart);
int fromLine = l.split("\n").length; //$NON-NLS-1$
int toLine = diffStr.substring(0, detailedDiffStart + detailedDiffLength).split("\n").length; //$NON-NLS-1$
// String#split drops trailing empty strings, so it must not be used to
// count lines: a prefix ending with \n starts the next line
int fromLine = countLines(diffStr.substring(0, detailedDiffStart));
int toLine = countLines(diffStr.substring(0, detailedDiffStart + detailedDiffLength));
if (fromLine == toLine) {
int starty = getYForLine(fromLine - 1, y, gc, textWidget);
Point start = getPositionForOffset(textWidget, gc, detailedDiffStart, diffStr, ranges,
Expand Down Expand Up @@ -1067,16 +989,4 @@ static RGB interpolate(RGB fg, RGB bg, double scale) {
}
return new RGB(128, 128, 128); // a gray
}

private static String replaceTabWithSpaces(String leftStr, int tabWidth) {
if (leftStr == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int s = 0; s < tabWidth; s++) {
sb.append(' ');
}
String result = leftStr.replace("\t", sb); //$NON-NLS-1$
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*******************************************************************************
* Copyright (c) 2026 SAP
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* SAP - initial implementation
*******************************************************************************/
package org.eclipse.compare.unifieddiff.internal;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;

/**
* Side-effect free text and style-range helpers used to lay out the unified
* diff code minings.
*/
public final class UnifiedDiffText {

private UnifiedDiffText() {
}

/**
* Returns the number of lines of the given string, counting a trailing line
* delimiter as starting a new (empty) line. An empty string is one line.
*/
public static int countLines(String str) {
if (str == null) {
return 0;
}
int result = 1;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '\n') {
result++;
}
}
return result;
}

public static String removeTrailingNewLines(String str) {
if (str == null) {
return str;
}
int end = str.length();
while (end > 0 && (str.charAt(end - 1) == '\n' || str.charAt(end - 1) == '\r')) {
end--;
}
return end == str.length() ? str : str.substring(0, end);
}

public static String removeLeadingNewLines(String str) {
if (str == null) {
return str;
}
int start = 0;
while (start < str.length() && (str.charAt(start) == '\n' || str.charAt(start) == '\r')) {
start++;
}
return start == 0 ? str : str.substring(start);
}

/**
* Expands every tab into {@code tabWidth} spaces. {@code GC#stringExtent} does
* not account for tabs, so widths are always measured on the expanded string.
*/
public static String replaceTabWithSpaces(String str, int tabWidth) {
if (str == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int s = 0; s < tabWidth; s++) {
sb.append(' ');
}
return str.replace("\t", sb); //$NON-NLS-1$
}

/**
* Maps an offset in {@code originalStr} to the corresponding offset in
* {@link #replaceTabWithSpaces(String, int)} of the same string.
*/
public static int mapOffsetToTabExpanded(String originalStr, int offset, int tabWidth) {
int tabCount = 0;
int limit = Math.min(offset, originalStr.length());
for (int i = 0; i < limit; i++) {
if (originalStr.charAt(i) == '\t') {
tabCount++;
}
}
return offset + tabCount * (tabWidth - 1);
}

/**
* Overlays the detailed-diff background ranges onto the syntax coloring ranges.
* Both lists must be sorted by offset and must not overlap within themselves.
* The returned ranges keep the foreground styling and cover exactly the extent
* of {@code foregrounds}.
*/
public static List<StyleRange> mergeStyleRanges(List<StyleRange> backgrounds, List<StyleRange> foregrounds) {
if (backgrounds.isEmpty()) {
return foregrounds;
}
if (foregrounds.isEmpty()) {
return backgrounds;
}
List<StyleRange> result = new ArrayList<>();
int bgIdx = 0;
for (StyleRange fg : foregrounds) {
int fgStart = fg.start;
int fgEnd = fg.start + fg.length;
int pos = fgStart;
while (pos < fgEnd && bgIdx < backgrounds.size()) {
StyleRange bg = backgrounds.get(bgIdx);
int bgStart = bg.start;
int bgEnd = bg.start + bg.length;
if (bgEnd <= pos) {
bgIdx++;
continue;
}
if (bgStart >= fgEnd) {
break;
}
if (bgStart > pos) {
result.add(createRange(fg, pos, bgStart - pos, null));
pos = bgStart;
}
int overlapEnd = Math.min(bgEnd, fgEnd);
result.add(createRange(fg, pos, overlapEnd - pos, bg.background));
pos = overlapEnd;
if (bgEnd <= fgEnd) {
bgIdx++;
}
}
if (pos < fgEnd) {
result.add(createRange(fg, pos, fgEnd - pos, null));
}
}
return result;
}

private static StyleRange createRange(StyleRange base, int start, int length, Color background) {
StyleRange r = (StyleRange) base.clone();
r.start = start;
r.length = length;
if (background != null) {
r.background = background;
}
return r;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.eclipse.team.tests.core.mapping.AllTeamMappingTests;
import org.eclipse.team.tests.ui.SaveableCompareEditorInputTest;
import org.eclipse.team.tests.ui.UnifiedDiffManagerTest;
import org.eclipse.team.tests.ui.UnifiedDiffTextTest;
import org.eclipse.team.tests.ui.synchronize.AllTeamSynchronizeTests;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
Expand All @@ -26,6 +27,7 @@
AllTeamSynchronizeTests.class, //
SaveableCompareEditorInputTest.class, //
UnifiedDiffManagerTest.class, //
UnifiedDiffTextTest.class, //
})
public class AllTeamUITests {
}
Loading
Loading