@@ -102,6 +102,19 @@ public class FilteredResourcesSelectionDialog extends FilteredItemsSelectionDial
102
102
private static final String SHOW_DERIVED = "ShowDerived" ; //$NON-NLS-1$
103
103
private static final String FILTER_BY_LOCATION = "FilterByLocation" ; //$NON-NLS-1$
104
104
105
+ private static final char START_SYMBOL = '>' ;
106
+
107
+ private static final char END_SYMBOL = '<' ;
108
+
109
+ private static final char BLANK = ' ' ;
110
+
111
+ // this is hard-coded, as a UI option is most probably not necessary
112
+ private final boolean autoInfixSearch = true ;
113
+
114
+ private int getDefaultMatchRules () {
115
+ return SearchPattern .DEFAULT_MATCH_RULES | (autoInfixSearch ? SearchPattern .RULE_SUBSTRING_MATCH : 0 );
116
+ }
117
+
105
118
private ShowDerivedResourcesAction showDerivedResourcesAction ;
106
119
107
120
private ResourceItemLabelProvider resourceItemLabelProvider ;
@@ -443,6 +456,7 @@ protected Comparator<IResource> getItemsComparator() {
443
456
444
457
if (pattern != null ) {
445
458
int patternDot = pattern .lastIndexOf ('.' );
459
+ // Prioritize names matching the whole pattern
446
460
String patternNoExtension = patternDot == -1 ? pattern : pattern .substring (0 , patternDot );
447
461
boolean m1 = patternNoExtension .equals (n1 );
448
462
boolean m2 = patternNoExtension .equals (n2 );
@@ -454,6 +468,21 @@ protected Comparator<IResource> getItemsComparator() {
454
468
return 1 ;
455
469
}
456
470
}
471
+ // Prioritize names starting with the pattern
472
+ char patternFirstChar = getFirstFileNameChar (pattern );
473
+ if (patternFirstChar != 0 ) {
474
+ patternFirstChar = Character .toLowerCase (patternFirstChar );
475
+ m1 = patternFirstChar == Character .toLowerCase (s1 .charAt (0 ));
476
+ m2 = patternFirstChar == Character .toLowerCase (s2 .charAt (0 ));
477
+ if (!m1 || !m2 ) {
478
+ if (m1 ) {
479
+ return -1 ;
480
+ }
481
+ if (m2 ) {
482
+ return 1 ;
483
+ }
484
+ }
485
+ }
457
486
}
458
487
459
488
int comparability = collator .compare (n1 , n2 );
@@ -495,6 +524,22 @@ protected Comparator<IResource> getItemsComparator() {
495
524
};
496
525
}
497
526
527
+ /**
528
+ * @param pattern
529
+ * @return the first character from the given string which <em>could</em> be
530
+ * considered a part of a file name. Returns <code>0</code> if there is
531
+ * no such character found.
532
+ */
533
+ private char getFirstFileNameChar (String pattern ) {
534
+ for (int i = 0 ; i < pattern .length (); i ++) {
535
+ char ch = pattern .charAt (i );
536
+ if (ch != '*' ) {
537
+ return ch ;
538
+ }
539
+ }
540
+ return 0 ;
541
+ }
542
+
498
543
/**
499
544
* Return the "distance" of the item from the root of the relative search
500
545
* container. Distances can be compared (smaller numbers are better). <br>
@@ -722,6 +767,9 @@ private List<Position> getMatchPositions(String string, String matching) {
722
767
}
723
768
724
769
// Pre-process the matching pattern
770
+ if (matching .charAt (0 ) == '>' ) {
771
+ matching = matching .substring (1 );
772
+ }
725
773
char lastChar = matching .charAt (matching .length () - 1 );
726
774
if (lastChar == ' ' || lastChar == '<' ) {
727
775
matching = matching .substring (0 , matching .length () - 1 );
@@ -756,8 +804,11 @@ private List<Position> getMatchPositions(String string, String matching) {
756
804
if (regionsDontMatch ) {
757
805
// We should get here only when CamelCase nor wildcard matching succeeded
758
806
// A simple comparison of the whole strings should succeed instead
759
- if (string .toLowerCase ().startsWith (matching .toLowerCase ())) {
760
- positions .add (new Position (0 , matching .length ()));
807
+ int matchingIndex = autoInfixSearch
808
+ ? string .toLowerCase ().indexOf (matching .toLowerCase ())
809
+ : (string .toLowerCase ().startsWith (matching .toLowerCase ()) ? 0 : -1 );
810
+ if (matchingIndex > -1 ) {
811
+ positions .add (new Position (matchingIndex , matching .length ()));
761
812
}
762
813
}
763
814
return positions ;
@@ -959,7 +1010,7 @@ protected class ResourceFilter extends ItemsFilter {
959
1010
* @param typeMask filter type mask. See {@link IResource#getType()} types.
960
1011
*/
961
1012
public ResourceFilter (IContainer container , boolean showDerived , int typeMask ) {
962
- super ();
1013
+ super (new SearchPattern ( getDefaultMatchRules ()) );
963
1014
this .filterContainer = container ;
964
1015
this .showDerived = showDerived ;
965
1016
this .filterTypeMask = typeMask ;
@@ -977,21 +1028,22 @@ public ResourceFilter(IContainer container, boolean showDerived, int typeMask) {
977
1028
private ResourceFilter (IContainer container , IContainer searchContainer , boolean showDerived , int typeMask ) {
978
1029
this (container , showDerived , typeMask );
979
1030
980
- String stringPattern = getPattern ();
981
- int matchRule = getMatchRule ();
1031
+ final String stringPattern = patternMatcher .getInitialPattern ();
982
1032
String filenamePattern ;
983
1033
984
1034
int sep = stringPattern .lastIndexOf (IPath .SEPARATOR );
985
1035
if (sep != -1 ) {
1036
+ // This means that we primarily check (via `patternMatcher`) just the resource
1037
+ // _name_ part and when there is some actual _container_ part (`sep > 0`), we
1038
+ // also do checks for that part (via `containerPattern` and optional
1039
+ // `relativeContainerPattern`).
986
1040
filenamePattern = stringPattern .substring (sep + 1 , stringPattern .length ());
987
- if ("*" .equals (filenamePattern )) //$NON-NLS-1$
988
- filenamePattern = "**" ; //$NON-NLS-1$
989
1041
990
1042
if (sep > 0 ) {
991
1043
if (filenamePattern .isEmpty ()) // relative patterns don't need a file name
992
1044
filenamePattern = "**" ; //$NON-NLS-1$
993
1045
994
- String containerPattern = stringPattern .substring (0 , sep );
1046
+ String containerPattern = stringPattern .substring (isMatchPrefix ( stringPattern ) ? 1 : 0 , sep );
995
1047
996
1048
if (searchContainer != null ) {
997
1049
relativeContainerPattern = new SearchPattern (
@@ -1001,6 +1053,8 @@ private ResourceFilter(IContainer container, IContainer searchContainer, boolean
1001
1053
}
1002
1054
1003
1055
if (!containerPattern .startsWith (Character .toString ('*' ))) {
1056
+ // bug 552418 - make the search always "root less", so that users don't need to
1057
+ // type the initial "*/"
1004
1058
if (!containerPattern .startsWith (Character .toString (IPath .SEPARATOR ))) {
1005
1059
containerPattern = IPath .SEPARATOR + containerPattern ;
1006
1060
}
@@ -1010,35 +1064,29 @@ private ResourceFilter(IContainer container, IContainer searchContainer, boolean
1010
1064
| SearchPattern .RULE_PREFIX_MATCH | SearchPattern .RULE_PATTERN_MATCH );
1011
1065
this .containerPattern .setPattern (containerPattern );
1012
1066
}
1013
- boolean isPrefixPattern = matchRule == SearchPattern .RULE_PREFIX_MATCH
1014
- || (matchRule == SearchPattern .RULE_PATTERN_MATCH && filenamePattern .endsWith ("*" )); //$NON-NLS-1$
1015
- if (!isPrefixPattern )
1016
- // Add '<' again as it was removed by SearchPattern
1017
- filenamePattern += '<' ;
1018
- else if (filenamePattern .endsWith ("*" ) && !filenamePattern .equals ("**" )) //$NON-NLS-1$ //$NON-NLS-2$
1019
- // Remove added '*' as the filename pattern might be a camel case pattern
1020
- filenamePattern = filenamePattern .substring (0 , filenamePattern .length () - 1 );
1067
+ if (isMatchPrefix (stringPattern )) {
1068
+ filenamePattern = '>' + filenamePattern ;
1069
+ }
1021
1070
patternMatcher .setPattern (filenamePattern );
1022
- // Update filenamePattern and matchRule as they might have changed
1023
- filenamePattern = getPattern ();
1024
- matchRule = getMatchRule ();
1025
1071
} else {
1026
1072
filenamePattern = stringPattern ;
1027
1073
}
1028
1074
1029
1075
int lastPatternDot = filenamePattern .lastIndexOf ('.' );
1030
1076
if (lastPatternDot != -1 ) {
1031
- if (matchRule != SearchPattern .RULE_EXACT_MATCH ) {
1032
- namePattern = new SearchPattern ();
1033
- namePattern .setPattern (filenamePattern .substring (0 , lastPatternDot ));
1034
- String extensionPatternStr = filenamePattern .substring (lastPatternDot + 1 );
1035
- // Add a '<' except this is a camel case pattern or a prefix pattern
1036
- if (matchRule != SearchPattern .RULE_CAMELCASE_MATCH && matchRule != SearchPattern .RULE_PREFIX_MATCH
1037
- && !extensionPatternStr .endsWith ("*" )) //$NON-NLS-1$
1038
- extensionPatternStr += '<' ;
1039
- extensionPattern = new SearchPattern ();
1040
- extensionPattern .setPattern (extensionPatternStr );
1077
+ // This means we primarily check resource name as _name_ and _extension_ part
1078
+ // and only when we don't succeed, we try the default whole-name check (via
1079
+ // `patternMatcher`).
1080
+ namePattern = new SearchPattern (getDefaultMatchRules ());
1081
+ String namePatternStr = filenamePattern .substring (0 , lastPatternDot );
1082
+ if (isMatchSuffix (stringPattern ) && !namePatternStr .endsWith ("*" )) { //$NON-NLS-1$
1083
+ // This means extension part will end with '<' (or ' ')
1084
+ // and we should apply the same for the name part.
1085
+ namePatternStr += "<" ; //$NON-NLS-1$
1041
1086
}
1087
+ namePattern .setPattern (namePatternStr );
1088
+ extensionPattern = new SearchPattern ();
1089
+ extensionPattern .setPattern (filenamePattern .substring (lastPatternDot + 1 ));
1042
1090
}
1043
1091
1044
1092
}
@@ -1218,4 +1266,29 @@ protected void storeItemToMemento(Object item, IMemento element) {
1218
1266
1219
1267
}
1220
1268
1269
+ /**
1270
+ * Returns whether prefix matching is enforced in the given search pattern.
1271
+ */
1272
+ private static boolean isMatchPrefix (String pattern ) {
1273
+ if (pattern .length () == 0 ) {
1274
+ return false ;
1275
+ }
1276
+
1277
+ char first = pattern .charAt (0 );
1278
+ return pattern .length () > 1 && first == START_SYMBOL ;
1279
+ }
1280
+
1281
+ /**
1282
+ * Returns whether suffix matching is enforced in the given search pattern.
1283
+ */
1284
+ private static boolean isMatchSuffix (String pattern ) {
1285
+ if (pattern .length () <= 1 ) {
1286
+ return false ;
1287
+ }
1288
+
1289
+ char last = pattern .charAt (pattern .length () - 1 );
1290
+ boolean matchPrefix = isMatchPrefix (pattern );
1291
+ return pattern .length () > (matchPrefix ? 2 : 1 ) && (last == END_SYMBOL || last == BLANK );
1292
+ }
1293
+
1221
1294
}
0 commit comments