Skip to content

Commit

Permalink
Show multiline error message for invalid regex in searches when possible
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jannisCode authored and fedejeanne committed Oct 30, 2024
1 parent 6af4673 commit 2c59dfb
Showing 1 changed file with 44 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Control;

/**
* This class contains methods to validate and decorate search fields.
Expand All @@ -41,11 +43,10 @@ private SearchDecoration() {
* the validation.
*/
public static boolean validateRegex(String regex, ControlDecoration targetDecoration) {
String errorMessage = getValidationError(regex);
String errorMessage = getValidationError(regex, targetDecoration.getControl());
if (errorMessage.isEmpty()) {
targetDecoration.hide();
return true;

}

Image decorationImage = FieldDecorationRegistry.getDefault()
Expand All @@ -62,21 +63,54 @@ public static boolean validateRegex(String regex, ControlDecoration targetDecora
* @return The appropriate error message if the regex is invalid or an empty
* string if the regex is valid.
*/
private static String getValidationError(String regex) {
private static String getValidationError(String regex, Control targetControl) {
try {
Pattern.compile(regex);
return ""; //$NON-NLS-1$
} catch (PatternSyntaxException e) {
String message = e.getLocalizedMessage();
return buildValidationErrorString(e, targetControl);
}
}

private static String buildValidationErrorString(PatternSyntaxException e, Control targetControl) {
String description = e.getDescription();
int errorIndex = e.getIndex();

if (errorIndex == -1) {
return description;
}

GC gc = new GC(targetControl);
String pattern = e.getPattern();

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

return message.substring(0, i);
validationErrorMessage.append(description);
validationErrorMessage.append(" at index ").append(errorIndex).append(System.lineSeparator()); //$NON-NLS-1$
validationErrorMessage.append(pattern).append(System.lineSeparator());

String stringToIndexString = pattern.substring(0, errorIndex + 1);
String hairSpace = "\u200A"; //$NON-NLS-1$
int hairSpaceWidth = gc.stringExtent(hairSpace).x;

int stringToIndex = gc.stringExtent(stringToIndexString).x;
String lastCharacter = stringToIndexString.substring(stringToIndexString.length() - 1);

int widthLastChar = gc.stringExtent(lastCharacter).x;
int upWidth = gc.stringExtent("^").x; //$NON-NLS-1$

double howFar = stringToIndex - widthLastChar / 2 - upWidth / 2;
int currentWidth = 0;

while (currentWidth < howFar) {
currentWidth += hairSpaceWidth;
validationErrorMessage.append(hairSpace);
}

validationErrorMessage.append("^"); //$NON-NLS-1$
gc.dispose();

return validationErrorMessage.toString();
}

}

0 comments on commit 2c59dfb

Please sign in to comment.