1919
2020import org .eclipse .jface .fieldassist .ControlDecoration ;
2121import org .eclipse .jface .fieldassist .FieldDecorationRegistry ;
22+ import org .eclipse .swt .graphics .GC ;
2223import org .eclipse .swt .graphics .Image ;
2324
2425/**
@@ -41,11 +42,10 @@ private SearchDecoration() {
4142 * the validation.
4243 */
4344 public static boolean validateRegex (String regex , ControlDecoration targetDecoration ) {
44- String errorMessage = getValidationError (regex );
45+ String errorMessage = getValidationError (regex , targetDecoration . getControl () );
4546 if (errorMessage .isEmpty ()) {
4647 targetDecoration .hide ();
4748 return true ;
48-
4949 }
5050
5151 Image decorationImage = FieldDecorationRegistry .getDefault ()
@@ -62,21 +62,55 @@ public static boolean validateRegex(String regex, ControlDecoration targetDecora
6262 * @return The appropriate error message if the regex is invalid or an empty
6363 * string if the regex is valid.
6464 */
65- private static String getValidationError (String regex ) {
65+ private static String getValidationError (String regex , org .eclipse .swt .widgets .Control targetControl ) {
66+
6667 try {
6768 Pattern .compile (regex );
6869 return "" ; //$NON-NLS-1$
70+
6971 } catch (PatternSyntaxException e ) {
70- String message = e .getLocalizedMessage ();
72+ return buildValidationErrorString (e , targetControl );
73+ }
74+ }
75+
76+ private static String buildValidationErrorString (PatternSyntaxException e , org .eclipse .swt .widgets .Control targetControl ) {
77+ GC gc = new GC (targetControl );
78+
79+ String description = e .getDescription ();
80+ int errorIndex = e .getIndex ();
81+ String pattern = e .getPattern ();
82+
83+ if (errorIndex == -1 ) {
84+ return description ;
85+ }
86+ StringBuilder sBuilder = new StringBuilder ();
87+
88+ sBuilder .append (description );
89+ sBuilder .append (" at index " ).append (errorIndex ).append (System .lineSeparator ()); //$NON-NLS-1$
90+ sBuilder .append (pattern ).append (System .lineSeparator ());
91+
92+ String stringToIndexString = pattern .substring (0 , errorIndex + 1 );
93+ String buildString = "" ; //$NON-NLS-1$
94+ String hairSpace = "\u200A " ; //$NON-NLS-1$
95+
96+ int stringToIndex = gc .stringExtent (stringToIndexString ).x ;
97+ String lastCharacter = stringToIndexString .substring (stringToIndexString .length () - 1 );
7198
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- }
99+ int widthLastChar = gc .stringExtent (lastCharacter ).x ;
100+ int upWidth = gc .stringExtent ("^" ).x ; //$NON-NLS-1$
77101
78- return message .substring (0 , i );
102+ double howFar = stringToIndex - widthLastChar / 2 - upWidth / 2 ;
103+
104+ while (gc .stringExtent (buildString ).x < howFar ) {
105+ buildString += hairSpace ; // $NON-NLS-1$
79106 }
107+ sBuilder .append (buildString );
108+
109+ sBuilder .append ("^" ); //$NON-NLS-1$
110+ gc .dispose ();
111+
112+ return sBuilder .toString ();
80113 }
81114
115+
82116}
0 commit comments