diff --git a/csl.api/src/org/netbeans/modules/csl/core/TypeAndSymbolProvider.java b/csl.api/src/org/netbeans/modules/csl/core/TypeAndSymbolProvider.java --- a/csl.api/src/org/netbeans/modules/csl/core/TypeAndSymbolProvider.java +++ b/csl.api/src/org/netbeans/modules/csl/core/TypeAndSymbolProvider.java @@ -270,6 +270,10 @@ return new Object [] { QuerySupport.Kind.CASE_INSENSITIVE_REGEXP, NameMatcherFactory.wildcardsToRegexp(text,true) }; case CAMEL_CASE: return new Object [] { QuerySupport.Kind.CAMEL_CASE, text }; + case FUZZY: + return new Object [] { QuerySupport.Kind.FUZZY, text }; + case CASE_INSENSITIVE_FUZZY: + return new Object [] { QuerySupport.Kind.CASE_INSENSITIVE_FUZZY, text }; default: throw new IllegalStateException("Can't translate " + searchType + " to QuerySupport.Kind"); //NOI18N } diff --git a/java.source/src/org/netbeans/api/java/source/ClassIndex.java b/java.source/src/org/netbeans/api/java/source/ClassIndex.java --- a/java.source/src/org/netbeans/api/java/source/ClassIndex.java +++ b/java.source/src/org/netbeans/api/java/source/ClassIndex.java @@ -183,7 +183,11 @@ * For example all these names NPE, NulPoEx, NULLPOInter leads to NullPointerException returned. * @since 0.28.0 */ - CAMEL_CASE_INSENSITIVE + CAMEL_CASE_INSENSITIVE, + + FUZZY, + + CASE_INSENSITIVE_FUZZY; }; diff --git a/java.source/src/org/netbeans/modules/java/source/usages/DocumentUtil.java b/java.source/src/org/netbeans/modules/java/source/usages/DocumentUtil.java --- a/java.source/src/org/netbeans/modules/java/source/usages/DocumentUtil.java +++ b/java.source/src/org/netbeans/modules/java/source/usages/DocumentUtil.java @@ -389,6 +389,8 @@ case CAMEL_CASE_INSENSITIVE: return Queries.QueryKind.CASE_INSENSITIVE_CAMEL_CASE; case REGEXP: return Queries.QueryKind.REGEXP; case CASE_INSENSITIVE_REGEXP: return Queries.QueryKind.CASE_INSENSITIVE_REGEXP; + case FUZZY: return Queries.QueryKind.FUZZY; + case CASE_INSENSITIVE_FUZZY: return Queries.QueryKind.CASE_INSENSITIVE_FUZZY; default: throw new IllegalArgumentException(); } } diff --git a/java.sourceui/src/org/netbeans/modules/java/source/ui/JavaSymbolProvider.java b/java.sourceui/src/org/netbeans/modules/java/source/ui/JavaSymbolProvider.java --- a/java.sourceui/src/org/netbeans/modules/java/source/ui/JavaSymbolProvider.java +++ b/java.sourceui/src/org/netbeans/modules/java/source/ui/JavaSymbolProvider.java @@ -170,6 +170,14 @@ _ident[0] = NameMatcherFactory.wildcardsToRegexp(_ident[0],true); _caseSensitive = false; break; + case FUZZY: + _kind = ClassIndex.NameKind.FUZZY; + _caseSensitive = true; + break; + case CASE_INSENSITIVE_FUZZY: + _kind = ClassIndex.NameKind.CASE_INSENSITIVE_FUZZY; + _caseSensitive = false; + break; default: throw new IllegalArgumentException(); } diff --git a/java.sourceui/src/org/netbeans/modules/java/source/ui/JavaTypeProvider.java b/java.sourceui/src/org/netbeans/modules/java/source/ui/JavaTypeProvider.java --- a/java.sourceui/src/org/netbeans/modules/java/source/ui/JavaTypeProvider.java +++ b/java.sourceui/src/org/netbeans/modules/java/source/ui/JavaTypeProvider.java @@ -174,6 +174,8 @@ case REGEXP: nameKind = ClassIndex.NameKind.REGEXP; break; case CASE_INSENSITIVE_REGEXP: nameKind = ClassIndex.NameKind.CASE_INSENSITIVE_REGEXP; break; case CAMEL_CASE: nameKind = ClassIndex.NameKind.CAMEL_CASE; break; + case FUZZY: nameKind = ClassIndex.NameKind.FUZZY; break; + case CASE_INSENSITIVE_FUZZY: nameKind = ClassIndex.NameKind.CASE_INSENSITIVE_FUZZY; break; default: throw new RuntimeException("Unexpected search type: " + searchType); } diff --git a/jumpto/src/org/netbeans/modules/jumpto/file/FileSearchAction.java b/jumpto/src/org/netbeans/modules/jumpto/file/FileSearchAction.java --- a/jumpto/src/org/netbeans/modules/jumpto/file/FileSearchAction.java +++ b/jumpto/src/org/netbeans/modules/jumpto/file/FileSearchAction.java @@ -200,16 +200,11 @@ if (exact) { //nameKind = panel.isCaseSensitive() ? QuerySupport.Kind.EXACT : QuerySupport.Kind.CASE_INSENSITIVE_EXACT; nameKind = QuerySupport.Kind.EXACT; - } - else if (wildcard != -1) { + } else if (wildcard != -1) { nameKind = panel.isCaseSensitive() ? QuerySupport.Kind.REGEXP : QuerySupport.Kind.CASE_INSENSITIVE_REGEXP; text = Utils.removeNonNeededWildCards(text); - } - else if ((Utils.isAllUpper(text) && text.length() > 1) || Utils.isCamelCase(text)) { - nameKind = QuerySupport.Kind.CAMEL_CASE; - } - else { - nameKind = panel.isCaseSensitive() ? QuerySupport.Kind.PREFIX : QuerySupport.Kind.CASE_INSENSITIVE_PREFIX; + } else { + nameKind = panel.isCaseSensitive() ? QuerySupport.Kind.FUZZY : QuerySupport.Kind.CASE_INSENSITIVE_FUZZY; } //Extract linenumber from search text diff --git a/jumpto/src/org/netbeans/modules/jumpto/file/Worker.java b/jumpto/src/org/netbeans/modules/jumpto/file/Worker.java --- a/jumpto/src/org/netbeans/modules/jumpto/file/Worker.java +++ b/jumpto/src/org/netbeans/modules/jumpto/file/Worker.java @@ -449,6 +449,10 @@ return org.netbeans.spi.jumpto.type.SearchType.PREFIX; case REGEXP: return org.netbeans.spi.jumpto.type.SearchType.REGEXP; + case FUZZY: + return org.netbeans.spi.jumpto.type.SearchType.FUZZY; + case CASE_INSENSITIVE_FUZZY: + return org.netbeans.spi.jumpto.type.SearchType.CASE_INSENSITIVE_FUZZY; default: throw new IllegalArgumentException(); } diff --git a/jumpto/src/org/netbeans/modules/jumpto/symbol/ContentProviderImpl.java b/jumpto/src/org/netbeans/modules/jumpto/symbol/ContentProviderImpl.java --- a/jumpto/src/org/netbeans/modules/jumpto/symbol/ContentProviderImpl.java +++ b/jumpto/src/org/netbeans/modules/jumpto/symbol/ContentProviderImpl.java @@ -542,12 +542,10 @@ if (exact) { //nameKind = isCaseSensitive ? SearchType.EXACT_NAME : SearchType.CASE_INSENSITIVE_EXACT_NAME; return SearchType.EXACT_NAME; - } else if ((Utils.isAllUpper(text) && text.length() > 1) || Utils.isCamelCase(text)) { - return SearchType.CAMEL_CASE; } else if (wildcard != -1) { return isCaseSensitive ? SearchType.REGEXP : SearchType.CASE_INSENSITIVE_REGEXP; } else { - return isCaseSensitive ? SearchType.PREFIX : SearchType.CASE_INSENSITIVE_PREFIX; + return isCaseSensitive ? SearchType.FUZZY : SearchType.CASE_INSENSITIVE_FUZZY; } } } diff --git a/jumpto/src/org/netbeans/modules/jumpto/type/GoToTypeAction.java b/jumpto/src/org/netbeans/modules/jumpto/type/GoToTypeAction.java --- a/jumpto/src/org/netbeans/modules/jumpto/type/GoToTypeAction.java +++ b/jumpto/src/org/netbeans/modules/jumpto/type/GoToTypeAction.java @@ -293,13 +293,6 @@ panel.isCaseSensitive() ? SearchType.EXACT_NAME : SearchType.CASE_INSENSITIVE_EXACT_NAME); - } else if ((Utils.isAllUpper(text) && text.length() > 1) || Utils.isCamelCase(text)) { - nameKinds = Arrays.asList( - new SearchType[] { - SearchType.CAMEL_CASE, - panel.isCaseSensitive() ? - SearchType.PREFIX : - SearchType.CASE_INSENSITIVE_PREFIX}); } else if (wildcard != -1) { nameKinds = Collections.singleton( panel.isCaseSensitive() ? @@ -309,8 +302,8 @@ } else { nameKinds = Collections.singleton( panel.isCaseSensitive() ? - SearchType.PREFIX : - SearchType.CASE_INSENSITIVE_PREFIX); + SearchType.FUZZY : + SearchType.CASE_INSENSITIVE_FUZZY); } // Compute in other thread diff --git a/jumpto/src/org/netbeans/spi/jumpto/support/NameMatcherFactory.java b/jumpto/src/org/netbeans/spi/jumpto/support/NameMatcherFactory.java --- a/jumpto/src/org/netbeans/spi/jumpto/support/NameMatcherFactory.java +++ b/jumpto/src/org/netbeans/spi/jumpto/support/NameMatcherFactory.java @@ -32,6 +32,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; +import org.netbeans.api.annotations.common.NonNull; import org.netbeans.spi.jumpto.type.SearchType; import org.openide.util.Parameters; @@ -181,6 +182,10 @@ return new CaseInsensitivePrefixNameMatcher(text); case CAMEL_CASE: return new CamelCaseNameMatcher(text); + case FUZZY: + return new RegExpNameMatcher(textToFuzzyRegexp(text, true), true); + case CASE_INSENSITIVE_FUZZY: + return new RegExpNameMatcher(textToFuzzyRegexp(text, false), false); default: throw new IllegalArgumentException("Unsupported type: " + type); //NOI18N } @@ -214,4 +219,27 @@ } return result; } + + @NonNull + private static String textToFuzzyRegexp(@NonNull final String text, final boolean caseSensitive) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < text.length();) { + char c = text.charAt(i); + if (!caseSensitive) { + c = Character.toLowerCase(c); + } + sb.append("\\Q"); //NOI18N + sb.append(c); + sb.append("\\E"); //NOI18N + i++; + if (i < text.length()) { + c = text.charAt(i); + sb.append("[^"); //NOI18N + sb.append(c); + sb.append("]"); //NOI18N + } + } + sb.append(".*"); //NOI18N + return sb.toString(); + } } diff --git a/jumpto/src/org/netbeans/spi/jumpto/type/SearchType.java b/jumpto/src/org/netbeans/spi/jumpto/type/SearchType.java --- a/jumpto/src/org/netbeans/spi/jumpto/type/SearchType.java +++ b/jumpto/src/org/netbeans/spi/jumpto/type/SearchType.java @@ -92,5 +92,9 @@ * A search using a case-insensitive * regular expression which should match the type name */ - CASE_INSENSITIVE_REGEXP + CASE_INSENSITIVE_REGEXP, + + FUZZY, + + CASE_INSENSITIVE_FUZZY; } diff --git a/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupport.java b/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupport.java --- a/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupport.java +++ b/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/support/QuerySupport.java @@ -414,7 +414,10 @@ */ CASE_INSENSITIVE_REGEXP, - CASE_INSENSITIVE_CAMEL_CASE; + CASE_INSENSITIVE_CAMEL_CASE, + + FUZZY, + CASE_INSENSITIVE_FUZZY; } /** @@ -780,6 +783,8 @@ case CASE_INSENSITIVE_REGEXP: return Queries.QueryKind.CASE_INSENSITIVE_REGEXP; case REGEXP: return Queries.QueryKind.REGEXP; case CASE_INSENSITIVE_CAMEL_CASE: return Queries.QueryKind.CASE_INSENSITIVE_CAMEL_CASE; + case FUZZY: return Queries.QueryKind.FUZZY; + case CASE_INSENSITIVE_FUZZY: return Queries.QueryKind.CASE_INSENSITIVE_FUZZY; default: throw new UnsupportedOperationException (kind.toString()); } } diff --git a/parsing.lucene/src/org/netbeans/modules/parsing/lucene/support/Queries.java b/parsing.lucene/src/org/netbeans/modules/parsing/lucene/support/Queries.java --- a/parsing.lucene/src/org/netbeans/modules/parsing/lucene/support/Queries.java +++ b/parsing.lucene/src/org/netbeans/modules/parsing/lucene/support/Queries.java @@ -112,7 +112,11 @@ /** * The given text is a case insensitive regular expression used to match the value. */ - CASE_INSENSITIVE_REGEXP; + CASE_INSENSITIVE_REGEXP, + + FUZZY, + + CASE_INSENSITIVE_FUZZY; } /** @@ -224,6 +228,20 @@ result.add(fq, Occur.SHOULD); return result; } + case FUZZY: + if (value.length() == 0) { + //Special case (all) handle in different way + return f.createAllDocsQuery(fieldName); + } else { + return f.createRegExpQuery(fieldName, createFuzzyRegExp(value, true), true); + } + case CASE_INSENSITIVE_FUZZY: + if (value.length() == 0) { + //Special case (all) handle in different way + return f.createAllDocsQuery(caseInsensitiveFieldName); + } else { + return f.createRegExpQuery(caseInsensitiveFieldName, createFuzzyRegExp(value, false), false); + } default: throw new UnsupportedOperationException (kind.toString()); } @@ -242,7 +260,30 @@ } while(index != -1); return sb.toString(); } - + + @NonNull + private static String createFuzzyRegExp(@NonNull final String query, final boolean caseSensitive) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < query.length();) { + char c = query.charAt(i); + if (!caseSensitive) { + c = Character.toLowerCase(c); + } + sb.append("\\Q"); //NOI18N + sb.append(c); + sb.append("\\E"); //NOI18N + i++; + if (i < query.length()) { + c = query.charAt(i); + sb.append("[^"); //NOI18N + sb.append(c); + sb.append("]*"); //NOI18N + } + } + sb.append(".*"); //NOI18N + return sb.toString(); + } + private static int findNextUpper(String text, int offset ) { for( int i = offset; i < text.length(); i++ ) { if ( Character.isUpperCase(text.charAt(i)) ) { @@ -371,20 +412,23 @@ } private static String getStartText(final String regexp) { - if (!Character.isJavaIdentifierStart(regexp.charAt(0))) { - return ""; //NOI18N - } final StringBuilder startBuilder = new StringBuilder (); - startBuilder.append(regexp.charAt(0)); - for (int i=1; i