Skip to content

Commit 2c59dfb

Browse files
jannisCodefedejeanne
authored andcommitted
Show multiline error message for invalid regex in searches when possible
When using a regular expression for a search, if there is enough information as to where the invalid character of the expression is then a multiline error message will be shown. The first line contains the regular expression and the second line contains an arrow (^) that points to the offending character.
1 parent 6af4673 commit 2c59dfb

File tree

1 file changed

+44
-10
lines changed

1 file changed

+44
-10
lines changed

bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919

2020
import org.eclipse.jface.fieldassist.ControlDecoration;
2121
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
22+
import org.eclipse.swt.graphics.GC;
2223
import org.eclipse.swt.graphics.Image;
24+
import org.eclipse.swt.widgets.Control;
2325

2426
/**
2527
* This class contains methods to validate and decorate search fields.
@@ -41,11 +43,10 @@ private SearchDecoration() {
4143
* the validation.
4244
*/
4345
public static boolean validateRegex(String regex, ControlDecoration targetDecoration) {
44-
String errorMessage = getValidationError(regex);
46+
String errorMessage = getValidationError(regex, targetDecoration.getControl());
4547
if (errorMessage.isEmpty()) {
4648
targetDecoration.hide();
4749
return true;
48-
4950
}
5051

5152
Image decorationImage = FieldDecorationRegistry.getDefault()
@@ -62,21 +63,54 @@ public static boolean validateRegex(String regex, ControlDecoration targetDecora
6263
* @return The appropriate error message if the regex is invalid or an empty
6364
* string if the regex is valid.
6465
*/
65-
private static String getValidationError(String regex) {
66+
private static String getValidationError(String regex, Control targetControl) {
6667
try {
6768
Pattern.compile(regex);
6869
return ""; //$NON-NLS-1$
6970
} catch (PatternSyntaxException e) {
70-
String message = e.getLocalizedMessage();
71+
return buildValidationErrorString(e, targetControl);
72+
}
73+
}
74+
75+
private static String buildValidationErrorString(PatternSyntaxException e, Control targetControl) {
76+
String description = e.getDescription();
77+
int errorIndex = e.getIndex();
78+
79+
if (errorIndex == -1) {
80+
return description;
81+
}
82+
83+
GC gc = new GC(targetControl);
84+
String pattern = e.getPattern();
7185

72-
// Only preserve the first line of the original error message.
73-
int i = 0;
74-
while (i < message.length() && "\n\r".indexOf(message.charAt(i)) == -1) { //$NON-NLS-1$
75-
i++;
76-
}
86+
StringBuilder validationErrorMessage = new StringBuilder();
7787

78-
return message.substring(0, i);
88+
validationErrorMessage.append(description);
89+
validationErrorMessage.append(" at index ").append(errorIndex).append(System.lineSeparator()); //$NON-NLS-1$
90+
validationErrorMessage.append(pattern).append(System.lineSeparator());
91+
92+
String stringToIndexString = pattern.substring(0, errorIndex + 1);
93+
String hairSpace = "\u200A"; //$NON-NLS-1$
94+
int hairSpaceWidth = gc.stringExtent(hairSpace).x;
95+
96+
int stringToIndex = gc.stringExtent(stringToIndexString).x;
97+
String lastCharacter = stringToIndexString.substring(stringToIndexString.length() - 1);
98+
99+
int widthLastChar = gc.stringExtent(lastCharacter).x;
100+
int upWidth = gc.stringExtent("^").x; //$NON-NLS-1$
101+
102+
double howFar = stringToIndex - widthLastChar / 2 - upWidth / 2;
103+
int currentWidth = 0;
104+
105+
while (currentWidth < howFar) {
106+
currentWidth += hairSpaceWidth;
107+
validationErrorMessage.append(hairSpace);
79108
}
109+
110+
validationErrorMessage.append("^"); //$NON-NLS-1$
111+
gc.dispose();
112+
113+
return validationErrorMessage.toString();
80114
}
81115

82116
}

0 commit comments

Comments
 (0)