diff --git a/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java b/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java index 47e4e148356..9066ec2b82a 100644 --- a/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java +++ b/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java @@ -19,6 +19,7 @@ import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; /** @@ -41,11 +42,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() @@ -62,21 +62,55 @@ 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, org.eclipse.swt.widgets.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, org.eclipse.swt.widgets.Control targetControl) { + GC gc = new GC(targetControl); + + String description = e.getDescription(); + int errorIndex = e.getIndex(); + String pattern = e.getPattern(); + + if (errorIndex == -1) { + return description; + } + StringBuilder sBuilder = new StringBuilder(); + + sBuilder.append(description); + sBuilder.append(" at index ").append(errorIndex).append(System.lineSeparator()); //$NON-NLS-1$ + sBuilder.append(pattern).append(System.lineSeparator()); + + String stringToIndexString = pattern.substring(0, errorIndex + 1); + String buildString = ""; //$NON-NLS-1$ + String hairSpace = "\u200A"; //$NON-NLS-1$ + + int stringToIndex = gc.stringExtent(stringToIndexString).x; + String lastCharacter = stringToIndexString.substring(stringToIndexString.length() - 1); - // 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++; - } + int widthLastChar = gc.stringExtent(lastCharacter).x; + int upWidth = gc.stringExtent("^").x; //$NON-NLS-1$ - return message.substring(0, i); + double howFar = stringToIndex - widthLastChar / 2 - upWidth / 2; + + while (gc.stringExtent(buildString).x < howFar) { + buildString += hairSpace; // $NON-NLS-1$ } + sBuilder.append(buildString); + + sBuilder.append("^"); //$NON-NLS-1$ + gc.dispose(); + + return sBuilder.toString(); } + } \ No newline at end of file