Copyright (c) 2000, 2019 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.jdt.core.search; import java.io.IOException; import java.util.regex.Pattern; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.compiler.*; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; import org.eclipse.jdt.internal.compiler.parser.Scanner; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; import org.eclipse.jdt.internal.core.LocalVariable; import org.eclipse.jdt.internal.core.index.EntryResult; import org.eclipse.jdt.internal.core.index.Index; import org.eclipse.jdt.internal.core.search.HierarchyScope; import org.eclipse.jdt.internal.core.search.IndexQueryRequestor; import org.eclipse.jdt.internal.core.search.JavaSearchScope; import org.eclipse.jdt.internal.core.search.StringOperation; import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants; import org.eclipse.jdt.internal.core.search.matching.*;
A search pattern defines how search results are found. Use SearchPattern.createPattern to create a search pattern.

Search patterns are used during the search phase to decode index entries that were added during the indexing phase (see SearchDocument.addIndexEntry(char[], char[])). When an index is queried, the index categories and keys to consider are retrieved from the search pattern using getIndexCategories() and getIndexKey(), as well as the match rule (see getMatchRule()). A blank pattern is then created (see getBlankPattern()). This blank pattern is used as a record as follows. For each index entry in the given index categories and that starts with the given key, the blank pattern is fed using decodeIndexKey(char[]). The original pattern is then asked if it matches the decoded key using matchesDecodedKey(SearchPattern). If it matches, a search document is created for this index entry using SearchParticipant.getDocument(String).

This class is intended to be sub-classed by clients. A default behavior is provided for each of the methods above, that clients can override if they wish.

See Also:
Since:3.0
/** * A search pattern defines how search results are found. Use <code>SearchPattern.createPattern</code> * to create a search pattern. * <p> * Search patterns are used during the search phase to decode index entries that were added during the indexing phase * (see {@link SearchDocument#addIndexEntry(char[], char[])}). When an index is queried, the * index categories and keys to consider are retrieved from the search pattern using {@link #getIndexCategories()} and * {@link #getIndexKey()}, as well as the match rule (see {@link #getMatchRule()}). A blank pattern is * then created (see {@link #getBlankPattern()}). This blank pattern is used as a record as follows. * For each index entry in the given index categories and that starts with the given key, the blank pattern is fed using * {@link #decodeIndexKey(char[])}. The original pattern is then asked if it matches the decoded key using * {@link #matchesDecodedKey(SearchPattern)}. If it matches, a search document is created for this index entry * using {@link SearchParticipant#getDocument(String)}. * * </p><p> * This class is intended to be sub-classed by clients. A default behavior is provided for each of the methods above, that * clients can override if they wish. * </p> * @see #createPattern(org.eclipse.jdt.core.IJavaElement, int) * @see #createPattern(String, int, int, int) * @since 3.0 */
public abstract class SearchPattern { // Rules for pattern matching: (exact, prefix, pattern) [ | case sensitive]
Match rule: The search pattern matches exactly the search result, that is, the source of the search result equals the search pattern.
/** * Match rule: The search pattern matches exactly the search result, * that is, the source of the search result equals the search pattern. */
public static final int R_EXACT_MATCH = 0;
Match rule: The search pattern is a prefix of the search result.
/** * Match rule: The search pattern is a prefix of the search result. */
public static final int R_PREFIX_MATCH = 0x0001;
Match rule: The search pattern contains one or more wild cards ('*' or '?'). A '*' wild-card can replace 0 or more characters in the search result. A '?' wild-card replaces exactly 1 character in the search result.
/** * Match rule: The search pattern contains one or more wild cards ('*' or '?'). * A '*' wild-card can replace 0 or more characters in the search result. * A '?' wild-card replaces exactly 1 character in the search result. */
public static final int R_PATTERN_MATCH = 0x0002;
Match rule: The search pattern contains a regular expression.

Warning: Implemented only for module declaration search. The support for this rule is not yet implemented for others

/** * Match rule: The search pattern contains a regular expression. * <p><b>Warning:</b> Implemented only for module declaration search. * The support for this rule is <b>not yet implemented for others</b></p> */
public static final int R_REGEXP_MATCH = 0x0004;
Match rule: The search pattern matches the search result only if cases are the same. Can be combined to previous rules, e.g. R_EXACT_MATCH | R_CASE_SENSITIVE
/** * Match rule: The search pattern matches the search result only if cases are the same. * Can be combined to previous rules, e.g. {@link #R_EXACT_MATCH} | {@link #R_CASE_SENSITIVE} */
public static final int R_CASE_SENSITIVE = 0x0008;
Match rule: The search pattern matches search results as raw/parameterized types/methods with same erasure. This mode has no effect on other java elements search.
Type search example:
  • pattern: List<Exception>
  • match: List<Object>
Method search example:
  • declaration: <T>foo(T t)
  • pattern: <Exception>foo(new Exception())
  • match: <Object>foo(new Object())
Can be combined to all other match rules, e.g. R_CASE_SENSITIVE | R_ERASURE_MATCH This rule is not activated by default, so raw types or parameterized types with same erasure will not be found for pattern List<String>, Note that with this pattern, the match selection will be only on the erasure even for parameterized types.
Since:3.1
/** * Match rule: The search pattern matches search results as raw/parameterized types/methods with same erasure. * This mode has no effect on other java elements search.<br> * Type search example: * <ul> * <li>pattern: <code>List&lt;Exception&gt;</code></li> * <li>match: <code>List&lt;Object&gt;</code></li> * </ul> * Method search example: * <ul> * <li>declaration: <code>&lt;T&gt;foo(T t)</code></li> * <li>pattern: <code>&lt;Exception&gt;foo(new Exception())</code></li> * <li>match: <code>&lt;Object&gt;foo(new Object())</code></li> * </ul> * Can be combined to all other match rules, e.g. {@link #R_CASE_SENSITIVE} | {@link #R_ERASURE_MATCH} * This rule is not activated by default, so raw types or parameterized types with same erasure will not be found * for pattern List&lt;String&gt;, * Note that with this pattern, the match selection will be only on the erasure even for parameterized types. * @since 3.1 */
public static final int R_ERASURE_MATCH = 0x0010;
Match rule: The search pattern matches search results as raw/parameterized types/methods with equivalent type parameters. This mode has no effect on other java elements search.
Type search example:
  • pattern: List<Exception>
  • match:
    • List<? extends Throwable>
    • List<? super RuntimeException>
    • List<?>
Method search example:
  • declaration: <T>foo(T t)
  • pattern: <Exception>foo(new Exception())
  • match:
    • <? extends Throwable>foo(new Exception())
    • <? super RuntimeException>foo(new Exception())
    • foo(new Exception())
Can be combined to all other match rules, e.g. R_CASE_SENSITIVE | R_EQUIVALENT_MATCH This rule is not activated by default, so raw types or equivalent parameterized types will not be found for pattern List<String>, This mode is overridden by R_ERASURE_MATCH as erasure matches obviously include equivalent ones. That means that pattern with rule set to R_EQUIVALENT_MATCH | R_ERASURE_MATCH will return same results than rule only set with R_ERASURE_MATCH.
Since:3.1
/** * Match rule: The search pattern matches search results as raw/parameterized types/methods with equivalent type parameters. * This mode has no effect on other java elements search.<br> * Type search example: * <ul> * <li>pattern: <code>List&lt;Exception&gt;</code></li> * <li>match: * <ul> * <li><code>List&lt;? extends Throwable&gt;</code></li> * <li><code>List&lt;? super RuntimeException&gt;</code></li> * <li><code>List&lt;?&gt;</code></li> * </ul> * </li> * </ul> * Method search example: * <ul> * <li>declaration: <code>&lt;T&gt;foo(T t)</code></li> * <li>pattern: <code>&lt;Exception&gt;foo(new Exception())</code></li> * <li>match: * <ul> * <li><code>&lt;? extends Throwable&gt;foo(new Exception())</code></li> * <li><code>&lt;? super RuntimeException&gt;foo(new Exception())</code></li> * <li><code>foo(new Exception())</code></li> * </ul> * </ul> * Can be combined to all other match rules, e.g. {@link #R_CASE_SENSITIVE} | {@link #R_EQUIVALENT_MATCH} * This rule is not activated by default, so raw types or equivalent parameterized types will not be found * for pattern List&lt;String&gt;, * This mode is overridden by {@link #R_ERASURE_MATCH} as erasure matches obviously include equivalent ones. * That means that pattern with rule set to {@link #R_EQUIVALENT_MATCH} | {@link #R_ERASURE_MATCH} * will return same results than rule only set with {@link #R_ERASURE_MATCH}. * @since 3.1 */
public static final int R_EQUIVALENT_MATCH = 0x0020;
Match rule: The search pattern matches exactly the search result, that is, the source of the search result equals the search pattern.
Since:3.1
/** * Match rule: The search pattern matches exactly the search result, * that is, the source of the search result equals the search pattern. * @since 3.1 */
public static final int R_FULL_MATCH = 0x0040;
Match rule: The search pattern contains a Camel Case expression.

Examples:

  • 'NPE' type string pattern will match 'NullPointerException' and 'NoPermissionException' types,
  • 'NuPoEx' type string pattern will only match 'NullPointerException' type.
This rule is not intended to be combined with any other match rule. In case of other match rule flags are combined with this one, then match rule validation will return a modified rule in order to perform a better appropriate search request (see validateMatchRule(String, int) for more details).

See Also:
Since:3.2
/** * Match rule: The search pattern contains a Camel Case expression. * <p> * Examples: * <ul> * <li>'NPE' type string pattern will match * 'NullPointerException' and 'NoPermissionException' types,</li> * <li>'NuPoEx' type string pattern will only match * 'NullPointerException' type.</li> * </ul> * * This rule is not intended to be combined with any other match rule. In case * of other match rule flags are combined with this one, then match rule validation * will return a modified rule in order to perform a better appropriate search request * (see {@link #validateMatchRule(String, int)} for more details). * <p> * @see #camelCaseMatch(String, String) for a detailed explanation of Camel * Case matching. * * @since 3.2 */
public static final int R_CAMELCASE_MATCH = 0x0080;
Match rule: The search pattern contains a Camel Case expression with a strict expected number of parts.
Examples:
  • 'HM' type string pattern will match 'HashMap' and 'HtmlMapper' types, but not 'HashMapEntry'
  • 'HMap' type string pattern will still match previous 'HashMap' and 'HtmlMapper' types, but not 'HighMagnitude'
This rule is not intended to be combined with any other match rule. In case of other match rule flags are combined with this one, then match rule validation will return a modified rule in order to perform a better appropriate search request (see validateMatchRule(String, int) for more details).

See Also:
Since:3.4
/** * Match rule: The search pattern contains a Camel Case expression with * a strict expected number of parts. * <br> * Examples: * <ul> * <li>'HM' type string pattern will match 'HashMap' and 'HtmlMapper' types, * but not 'HashMapEntry' * </li> * <li>'HMap' type string pattern will still match previous 'HashMap' and * 'HtmlMapper' types, but not 'HighMagnitude' * </li> * </ul> * * This rule is not intended to be combined with any other match rule. In case * of other match rule flags are combined with this one, then match rule validation * will return a modified rule in order to perform a better appropriate search request * (see {@link #validateMatchRule(String, int)} for more details). * <p> * @see CharOperation#camelCaseMatch(char[], char[], boolean) for a detailed * explanation of Camel Case matching. *<p> * @since 3.4 */
public static final int R_CAMELCASE_SAME_PART_COUNT_MATCH = 0x0100;
Match rule: The search pattern contains a substring expression in a case-insensitive way.

Examples:

  • 'bar' string pattern will match 'bar1', 'Bar' and 'removeBar' types,
This rule is not intended to be combined with any other match rule. In case of other match rule flags are combined with this one, then match rule validation will return a modified rule in order to perform a better appropriate search request (see validateMatchRule(String, int) for more details).

This is implemented only for code assist and not available for normal search.

Since:3.12
/** * Match rule: The search pattern contains a substring expression in a case-insensitive way. * <p> * Examples: * <ul> * <li>'bar' string pattern will match * 'bar1', 'Bar' and 'removeBar' types,</li> * </ul> * * This rule is not intended to be combined with any other match rule. In case * of other match rule flags are combined with this one, then match rule validation * will return a modified rule in order to perform a better appropriate search request * (see {@link #validateMatchRule(String, int)} for more details). * * <p> * This is implemented only for code assist and not available for normal search. * * @since 3.12 */
public static final int R_SUBSTRING_MATCH = 0x0200; private static final int MODE_MASK = R_EXACT_MATCH | R_PREFIX_MATCH | R_PATTERN_MATCH | R_REGEXP_MATCH | R_CAMELCASE_MATCH | R_CAMELCASE_SAME_PART_COUNT_MATCH; private int matchRule;
The focus element (used for reference patterns)
@noreferenceThis field is not intended to be referenced by clients.
/** * The focus element (used for reference patterns) * @noreference This field is not intended to be referenced by clients. */
public IJavaElement focus;
@noreferenceThis field is not intended to be referenced by clients.
/** * @noreference This field is not intended to be referenced by clients. */
public int kind;
@noreferenceThis field is not intended to be referenced by clients.
/** * @noreference This field is not intended to be referenced by clients. */
public boolean mustResolve = true;
Creates a search pattern with the rule to apply for matching index keys. It can be exact match, prefix match, pattern match or regexp match. Rule can also be combined with a case sensitivity flag.
Params:
/** * Creates a search pattern with the rule to apply for matching index keys. * It can be exact match, prefix match, pattern match or regexp match. * Rule can also be combined with a case sensitivity flag. * * @param matchRule one of following match rule * <ul> * <li>{@link #R_EXACT_MATCH}</li> * <li>{@link #R_PREFIX_MATCH}</li> * <li>{@link #R_PATTERN_MATCH}</li> * <li>{@link #R_REGEXP_MATCH}</li> * <li>{@link #R_CAMELCASE_MATCH}</li> * <li>{@link #R_CAMELCASE_SAME_PART_COUNT_MATCH}</li> * </ul> * which may be also combined with one of following flag: * <ul> * <li>{@link #R_CASE_SENSITIVE}</li> * <li>{@link #R_ERASURE_MATCH}</li> * <li>{@link #R_EQUIVALENT_MATCH}</li> * </ul> * For example, * <ul> * <li>{@link #R_EXACT_MATCH} | {@link #R_CASE_SENSITIVE}: if an exact * and case sensitive match is requested,</li> * <li>{@link #R_PREFIX_MATCH} if a case insensitive prefix match is requested</li> * <li>{@link #R_EXACT_MATCH} | {@link #R_ERASURE_MATCH}: if a case * insensitive and erasure match is requested.</li> * </ul> * Note that {@link #R_ERASURE_MATCH} or {@link #R_EQUIVALENT_MATCH} has no effect * on non-generic types/methods search. * <p> * Note also that default behavior for generic types/methods search is to find exact matches. */
public SearchPattern(int matchRule) { this.matchRule = matchRule; // Set full match implicit mode if ((matchRule & (R_EQUIVALENT_MATCH | R_ERASURE_MATCH )) == 0) { this.matchRule |= R_FULL_MATCH; } // reset other incompatible flags if ((matchRule & R_CAMELCASE_MATCH) != 0) { this.matchRule &= ~R_CAMELCASE_SAME_PART_COUNT_MATCH; this.matchRule &= ~R_PREFIX_MATCH; } else if ((matchRule & R_CAMELCASE_SAME_PART_COUNT_MATCH) != 0) { this.matchRule &= ~R_PREFIX_MATCH; } }
@noreferenceThis method is not intended to be referenced by clients.
@nooverrideThis method is not intended to be re-implemented or extended by clients.
/** * @noreference This method is not intended to be referenced by clients. * @nooverride This method is not intended to be re-implemented or extended by clients. */
public void acceptMatch(String relativePath, String containerPath, char separator, SearchPattern pattern, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope) { acceptMatch(relativePath, containerPath, separator, pattern, requestor, participant, scope, null); }
@noreferenceThis method is not intended to be referenced by clients.
@nooverrideThis method is not intended to be re-implemented or extended by clients.
/** * @noreference This method is not intended to be referenced by clients. * @nooverride This method is not intended to be re-implemented or extended by clients. */
public void acceptMatch(String relativePath, String containerPath, char separator, SearchPattern pattern, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor monitor) { if (scope instanceof JavaSearchScope) { JavaSearchScope javaSearchScope = (JavaSearchScope) scope; // Get document path access restriction from java search scope // Note that requestor has to verify if needed whether the document violates the access restriction or not AccessRuleSet access = javaSearchScope.getAccessRuleSet(relativePath, containerPath); if (access != JavaSearchScope.NOT_ENCLOSED) { // scope encloses the document path StringBuffer documentPath = new StringBuffer(containerPath.length() + 1 + relativePath.length()); documentPath.append(containerPath); documentPath.append(separator); documentPath.append(relativePath); if (!requestor.acceptIndexMatch(documentPath.toString(), pattern, participant, access)) throw new OperationCanceledException(); } } else { StringBuffer buffer = new StringBuffer(containerPath.length() + 1 + relativePath.length()); buffer.append(containerPath); buffer.append(separator); buffer.append(relativePath); String documentPath = buffer.toString(); boolean encloses = (scope instanceof HierarchyScope) ? ((HierarchyScope)scope).encloses(documentPath, monitor) : scope.encloses(documentPath); if (encloses) if (!requestor.acceptIndexMatch(documentPath, pattern, participant, null)) throw new OperationCanceledException(); } }
@noreferenceThis method is not intended to be referenced by clients.
@nooverrideThis method is not intended to be re-implemented or extended by clients.
/** * @noreference This method is not intended to be referenced by clients. * @nooverride This method is not intended to be re-implemented or extended by clients. */
public SearchPattern currentPattern() { return this; }
Answers true if the pattern matches the given name using CamelCase rules, or false otherwise. char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.

CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term. This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field names follow the lower CamelCase convention.

The pattern may contain lowercase characters, which will be matched in a case sensitive way. These characters must appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.

Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.

Using this method allows matching names to have more parts than the specified pattern (see camelCaseMatch(String, String, boolean)).
For instance, 'HM' , 'HaMa' and 'HMap' patterns will match 'HashMap', 'HatMapper' and also 'HashMapEntry'.

Examples:

  1. pattern = "NPE" name = NullPointerException / NoPermissionException result => true
  2. pattern = "NuPoEx" name = NullPointerException result => true
  3. pattern = "npe" name = NullPointerException result => false
  4. pattern = "IPL3" name = "IPerspectiveListener3" result => true
  5. pattern = "HM" name = "HashMapEntry" result => true
  6. pattern = "HMap" name = "HatMapper" result => true
Params:
  • pattern – the given pattern
  • name – the given name
See Also:
Returns:true if the pattern matches the given name, false otherwise
Since:3.2
/** * Answers true if the pattern matches the given name using CamelCase rules, or * false otherwise. char[] CamelCase matching does NOT accept explicit wild-cards * '*' and '?' and is inherently case sensitive. * <p> * CamelCase denotes the convention of writing compound names without spaces, * and capitalizing every term. This function recognizes both upper and lower * CamelCase, depending whether the leading character is capitalized or not. * The leading part of an upper CamelCase pattern is assumed to contain a * sequence of capitals which are appearing in the matching name; e.g. 'NPE' will * match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern * uses a lowercase first character. In Java, type names follow the upper * CamelCase convention, whereas method or field names follow the lower * CamelCase convention. * <p> * The pattern may contain lowercase characters, which will be matched in a case * sensitive way. These characters must appear in sequence in the name. * For instance, 'NPExcep' will match 'NullPointerException', but not * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not * 'NoPointerException'. * <p> * Digit characters are treated in a special way. They can be used in the pattern * but are not always considered as leading character. For instance, both * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'. * <p> * Using this method allows matching names to have more parts than the specified * pattern (see {@link #camelCaseMatch(String, String, boolean)}).<br> * For instance, 'HM' , 'HaMa' and 'HMap' patterns will match 'HashMap', * 'HatMapper' <b>and also</b> 'HashMapEntry'. * <p> * Examples: * <ol><li> pattern = "NPE" * name = NullPointerException / NoPermissionException * result => true</li> * <li> pattern = "NuPoEx" * name = NullPointerException * result => true</li> * <li> pattern = "npe" * name = NullPointerException * result => false</li> * <li> pattern = "IPL3" * name = "IPerspectiveListener3" * result => true</li> * <li> pattern = "HM" * name = "HashMapEntry" * result => true</li> * <li> pattern = "HMap" * name = "HatMapper" * result => true</li> * </ol> * * @see #camelCaseMatch(String, int, int, String, int, int, boolean) for algorithm * implementation * * @param pattern the given pattern * @param name the given name * @return true if the pattern matches the given name, false otherwise * @since 3.2 */
public static final boolean camelCaseMatch(String pattern, String name) { if (pattern == null) return true; // null pattern is equivalent to '*' if (name == null) return false; // null name cannot match return camelCaseMatch(pattern, 0, pattern.length(), name, 0, name.length(), false/*not the same count of parts*/); }
Answers true if the pattern matches the given name using CamelCase rules, or false otherwise. char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.

CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term. This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field names follow the lower CamelCase convention.

The pattern may contain lowercase characters, which will be matched in a case sensitive way. These characters must appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.

Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.

CamelCase can be restricted to match only the same count of parts. When this restriction is specified the given pattern and the given name must have exactly the same number of parts (i.e. the same number of uppercase characters).
For instance, 'HM' , 'HaMa' and 'HMap' patterns will match 'HashMap' and 'HatMapper' but not 'HashMapEntry'.

Examples:

  1. pattern = "NPE" name = NullPointerException / NoPermissionException result => true
  2. pattern = "NuPoEx" name = NullPointerException result => true
  3. pattern = "npe" name = NullPointerException result => false
  4. pattern = "IPL3" name = "IPerspectiveListener3" result => true
  5. pattern = "HM" name = "HashMapEntry" result => (samePartCount == false)
Params:
  • pattern – the given pattern
  • name – the given name
  • samePartCount – flag telling whether the pattern and the name should have the same count of parts or not.
      For example:
    • 'HM' type string pattern will match 'HashMap' and 'HtmlMapper' types, but not 'HashMapEntry'
    • 'HMap' type string pattern will still match previous 'HashMap' and 'HtmlMapper' types, but not 'HighMagnitude'
See Also:
  • for algorithm implementation
Returns:true if the pattern matches the given name, false otherwise
Since:3.4
/** * Answers true if the pattern matches the given name using CamelCase rules, or * false otherwise. char[] CamelCase matching does NOT accept explicit wild-cards * '*' and '?' and is inherently case sensitive. * <p> * CamelCase denotes the convention of writing compound names without spaces, * and capitalizing every term. This function recognizes both upper and lower * CamelCase, depending whether the leading character is capitalized or not. * The leading part of an upper CamelCase pattern is assumed to contain a * sequence of capitals which are appearing in the matching name; e.g. 'NPE' will * match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern * uses a lowercase first character. In Java, type names follow the upper * CamelCase convention, whereas method or field names follow the lower * CamelCase convention. * <p> * The pattern may contain lowercase characters, which will be matched in a case * sensitive way. These characters must appear in sequence in the name. * For instance, 'NPExcep' will match 'NullPointerException', but not * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not * 'NoPointerException'. * <p> * Digit characters are treated in a special way. They can be used in the pattern * but are not always considered as leading character. For instance, both * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'. * <p> * CamelCase can be restricted to match only the same count of parts. When this * restriction is specified the given pattern and the given name must have <b>exactly</b> * the same number of parts (i.e. the same number of uppercase characters).<br> * For instance, 'HM' , 'HaMa' and 'HMap' patterns will match 'HashMap' and * 'HatMapper' <b>but not</b> 'HashMapEntry'. * <p> * Examples: * <ol><li> pattern = "NPE" * name = NullPointerException / NoPermissionException * result => true</li> * <li> pattern = "NuPoEx" * name = NullPointerException * result => true</li> * <li> pattern = "npe" * name = NullPointerException * result => false</li> * <li> pattern = "IPL3" * name = "IPerspectiveListener3" * result => true</li> * <li> pattern = "HM" * name = "HashMapEntry" * result => (samePartCount == false)</li> * </ol> * * @see #camelCaseMatch(String, int, int, String, int, int, boolean) for algorithm * implementation * * @param pattern the given pattern * @param name the given name * @param samePartCount flag telling whether the pattern and the name should * have the same count of parts or not.<br> * &nbsp;&nbsp;For example: * <ul> * <li>'HM' type string pattern will match 'HashMap' and 'HtmlMapper' types, * but not 'HashMapEntry'</li> * <li>'HMap' type string pattern will still match previous 'HashMap' and * 'HtmlMapper' types, but not 'HighMagnitude'</li> * </ul> * @return true if the pattern matches the given name, false otherwise * @since 3.4 */
public static final boolean camelCaseMatch(String pattern, String name, boolean samePartCount) { if (pattern == null) return true; // null pattern is equivalent to '*' if (name == null) return false; // null name cannot match return camelCaseMatch(pattern, 0, pattern.length(), name, 0, name.length(), samePartCount); }
Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise. char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive. Can match only subset of name/pattern, considering end positions as non-inclusive. The sub-pattern is defined by the patternStart and patternEnd positions.

CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term. This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field names follow the lower CamelCase convention.

The pattern may contain lowercase characters, which will be matched in a case sensitive way. These characters must appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.

Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.

Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.

Using this method allows matching names to have more parts than the specified pattern (see camelCaseMatch(String, int, int, String, int, int, boolean)).
For instance, 'HM' , 'HaMa' and 'HMap' patterns will match 'HashMap', 'HatMapper' and also 'HashMapEntry'.

  1. pattern = "NPE" patternStart = 0 patternEnd = 3 name = NullPointerException nameStart = 0 nameEnd = 20 result => true
  2. pattern = "NPE" patternStart = 0 patternEnd = 3 name = NoPermissionException nameStart = 0 nameEnd = 21 result => true
  3. pattern = "NuPoEx" patternStart = 0 patternEnd = 6 name = NullPointerException nameStart = 0 nameEnd = 20 result => true
  4. pattern = "NuPoEx" patternStart = 0 patternEnd = 6 name = NoPermissionException nameStart = 0 nameEnd = 21 result => false
  5. pattern = "npe" patternStart = 0 patternEnd = 3 name = NullPointerException nameStart = 0 nameEnd = 20 result => false
  6. pattern = "IPL3" patternStart = 0 patternEnd = 3 name = "IPerspectiveListener3" nameStart = 0 nameEnd = 21 result => true
  7. pattern = "HM" patternStart = 0 patternEnd = 2 name = "HashMapEntry" nameStart = 0 nameEnd = 12 result => true
  8. pattern = "HMap" patternStart = 0 patternEnd = 4 name = "HatMapper" nameStart = 0 nameEnd = 9 result => true
Params:
  • pattern – the given pattern
  • patternStart – the start index of the pattern, inclusive
  • patternEnd – the end index of the pattern, exclusive
  • name – the given name
  • nameStart – the start index of the name, inclusive
  • nameEnd – the end index of the name, exclusive
Returns:true if a sub-pattern matches the sub-part of the given name, false otherwise
Since:3.2
/** * Answers true if a sub-pattern matches the sub-part of the given name using * CamelCase rules, or false otherwise. char[] CamelCase matching does NOT * accept explicit wild-cards '*' and '?' and is inherently case sensitive. * Can match only subset of name/pattern, considering end positions as non-inclusive. * The sub-pattern is defined by the patternStart and patternEnd positions. * <p> * CamelCase denotes the convention of writing compound names without spaces, * and capitalizing every term. This function recognizes both upper and lower * CamelCase, depending whether the leading character is capitalized or not. * The leading part of an upper CamelCase pattern is assumed to contain a * sequence of capitals which are appearing in the matching name; e.g. 'NPE' will * match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern * uses a lowercase first character. In Java, type names follow the upper * CamelCase convention, whereas method or field names follow the lower * CamelCase convention. * <p> * The pattern may contain lowercase characters, which will be matched in a case * sensitive way. These characters must appear in sequence in the name. * For instance, 'NPExcep' will match 'NullPointerException', but not * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not * 'NoPointerException'. * <p> * Digit characters are treated in a special way. They can be used in the pattern * but are not always considered as leading character. For instance, both * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'. * <p> * Digit characters are treated in a special way. They can be used in the pattern * but are not always considered as leading character. For instance, both * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'. * <p> * Using this method allows matching names to have more parts than the specified * pattern (see {@link #camelCaseMatch(String, int, int, String, int, int, boolean)}).<br> * For instance, 'HM' , 'HaMa' and 'HMap' patterns will match 'HashMap', * 'HatMapper' <b>and also</b> 'HashMapEntry'. * <ol> * <li> pattern = "NPE" * patternStart = 0 * patternEnd = 3 * name = NullPointerException * nameStart = 0 * nameEnd = 20 * result => true</li> * <li> pattern = "NPE" * patternStart = 0 * patternEnd = 3 * name = NoPermissionException * nameStart = 0 * nameEnd = 21 * result => true</li> * <li> pattern = "NuPoEx" * patternStart = 0 * patternEnd = 6 * name = NullPointerException * nameStart = 0 * nameEnd = 20 * result => true</li> * <li> pattern = "NuPoEx" * patternStart = 0 * patternEnd = 6 * name = NoPermissionException * nameStart = 0 * nameEnd = 21 * result => false</li> * <li> pattern = "npe" * patternStart = 0 * patternEnd = 3 * name = NullPointerException * nameStart = 0 * nameEnd = 20 * result => false</li> * <li> pattern = "IPL3" * patternStart = 0 * patternEnd = 3 * name = "IPerspectiveListener3" * nameStart = 0 * nameEnd = 21 * result => true</li> * <li> pattern = "HM" * patternStart = 0 * patternEnd = 2 * name = "HashMapEntry" * nameStart = 0 * nameEnd = 12 * result => true</li> * <li> pattern = "HMap" * patternStart = 0 * patternEnd = 4 * name = "HatMapper" * nameStart = 0 * nameEnd = 9 * result => true</li> * </ol> * * @param pattern the given pattern * @param patternStart the start index of the pattern, inclusive * @param patternEnd the end index of the pattern, exclusive * @param name the given name * @param nameStart the start index of the name, inclusive * @param nameEnd the end index of the name, exclusive * @return true if a sub-pattern matches the sub-part of the given name, false otherwise * @since 3.2 */
public static final boolean camelCaseMatch(String pattern, int patternStart, int patternEnd, String name, int nameStart, int nameEnd) { return camelCaseMatch(pattern, patternStart, patternEnd, name, nameStart, nameEnd, false/*not the same count of parts*/); }
Answers true if a sub-pattern matches the sub-part of the given name using CamelCase rules, or false otherwise. char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive. Can match only subset of name/pattern, considering end positions as non-inclusive. The sub-pattern is defined by the patternStart and patternEnd positions.

CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term. This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field names follow the lower CamelCase convention.

The pattern may contain lowercase characters, which will be matched in a case sensitive way. These characters must appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.

Digit characters are treated in a special way. They can be used in the pattern but are not always considered as leading character. For instance, both 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.

CamelCase can be restricted to match only the same count of parts. When this restriction is specified the given pattern and the given name must have exactly the same number of parts (i.e. the same number of uppercase characters).
For instance, 'HM' , 'HaMa' and 'HMap' patterns will match 'HashMap' and 'HatMapper' but not 'HashMapEntry'.

Examples:

  1. pattern = "NPE" patternStart = 0 patternEnd = 3 name = NullPointerException nameStart = 0 nameEnd = 20 result => true
  2. pattern = "NPE" patternStart = 0 patternEnd = 3 name = NoPermissionException nameStart = 0 nameEnd = 21 result => true
  3. pattern = "NuPoEx" patternStart = 0 patternEnd = 6 name = NullPointerException nameStart = 0 nameEnd = 20 result => true
  4. pattern = "NuPoEx" patternStart = 0 patternEnd = 6 name = NoPermissionException nameStart = 0 nameEnd = 21 result => false
  5. pattern = "npe" patternStart = 0 patternEnd = 3 name = NullPointerException nameStart = 0 nameEnd = 20 result => false
  6. pattern = "IPL3" patternStart = 0 patternEnd = 3 name = "IPerspectiveListener3" nameStart = 0 nameEnd = 21 result => true
  7. pattern = "HM" patternStart = 0 patternEnd = 2 name = "HashMapEntry" nameStart = 0 nameEnd = 12 result => (samePartCount == false)
Params:
  • pattern – the given pattern
  • patternStart – the start index of the pattern, inclusive
  • patternEnd – the end index of the pattern, exclusive
  • name – the given name
  • nameStart – the start index of the name, inclusive
  • nameEnd – the end index of the name, exclusive
  • samePartCount – flag telling whether the pattern and the name should have the same count of parts or not.
      For example:
    • 'HM' type string pattern will match 'HashMap' and 'HtmlMapper' types, but not 'HashMapEntry'
    • 'HMap' type string pattern will still match previous 'HashMap' and 'HtmlMapper' types, but not 'HighMagnitude'
See Also:
  • from which algorithm implementation has been entirely copied.
Returns:true if a sub-pattern matches the sub-part of the given name, false otherwise
Since:3.4
/** * Answers true if a sub-pattern matches the sub-part of the given name using * CamelCase rules, or false otherwise. char[] CamelCase matching does NOT * accept explicit wild-cards '*' and '?' and is inherently case sensitive. * Can match only subset of name/pattern, considering end positions as * non-inclusive. The sub-pattern is defined by the patternStart and patternEnd * positions. * <p> * CamelCase denotes the convention of writing compound names without spaces, * and capitalizing every term. This function recognizes both upper and lower * CamelCase, depending whether the leading character is capitalized or not. * The leading part of an upper CamelCase pattern is assumed to contain * a sequence of capitals which are appearing in the matching name; e.g. 'NPE' will * match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern * uses a lowercase first character. In Java, type names follow the upper * CamelCase convention, whereas method or field names follow the lower * CamelCase convention. * <p> * The pattern may contain lowercase characters, which will be matched in a case * sensitive way. These characters must appear in sequence in the name. * For instance, 'NPExcep' will match 'NullPointerException', but not * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not * 'NoPointerException'. * <p> * Digit characters are treated in a special way. They can be used in the pattern * but are not always considered as leading character. For instance, both * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'. * <p> * CamelCase can be restricted to match only the same count of parts. When this * restriction is specified the given pattern and the given name must have <b>exactly</b> * the same number of parts (i.e. the same number of uppercase characters).<br> * For instance, 'HM' , 'HaMa' and 'HMap' patterns will match 'HashMap' and * 'HatMapper' <b>but not</b> 'HashMapEntry'. * <p> * Examples: * <ol> * <li> pattern = "NPE" * patternStart = 0 * patternEnd = 3 * name = NullPointerException * nameStart = 0 * nameEnd = 20 * result => true</li> * <li> pattern = "NPE" * patternStart = 0 * patternEnd = 3 * name = NoPermissionException * nameStart = 0 * nameEnd = 21 * result => true</li> * <li> pattern = "NuPoEx" * patternStart = 0 * patternEnd = 6 * name = NullPointerException * nameStart = 0 * nameEnd = 20 * result => true</li> * <li> pattern = "NuPoEx" * patternStart = 0 * patternEnd = 6 * name = NoPermissionException * nameStart = 0 * nameEnd = 21 * result => false</li> * <li> pattern = "npe" * patternStart = 0 * patternEnd = 3 * name = NullPointerException * nameStart = 0 * nameEnd = 20 * result => false</li> * <li> pattern = "IPL3" * patternStart = 0 * patternEnd = 3 * name = "IPerspectiveListener3" * nameStart = 0 * nameEnd = 21 * result => true</li> * <li> pattern = "HM" * patternStart = 0 * patternEnd = 2 * name = "HashMapEntry" * nameStart = 0 * nameEnd = 12 * result => (samePartCount == false)</li> * </ol> * * @see CharOperation#camelCaseMatch(char[], int, int, char[], int, int, boolean) * from which algorithm implementation has been entirely copied. * * @param pattern the given pattern * @param patternStart the start index of the pattern, inclusive * @param patternEnd the end index of the pattern, exclusive * @param name the given name * @param nameStart the start index of the name, inclusive * @param nameEnd the end index of the name, exclusive * @param samePartCount flag telling whether the pattern and the name should * have the same count of parts or not.<br> * &nbsp;&nbsp;For example: * <ul> * <li>'HM' type string pattern will match 'HashMap' and 'HtmlMapper' types, * but not 'HashMapEntry'</li> * <li>'HMap' type string pattern will still match previous 'HashMap' and * 'HtmlMapper' types, but not 'HighMagnitude'</li> * </ul> * @return true if a sub-pattern matches the sub-part of the given name, false otherwise * @since 3.4 */
public static final boolean camelCaseMatch(String pattern, int patternStart, int patternEnd, String name, int nameStart, int nameEnd, boolean samePartCount) { return StringOperation.getCamelCaseMatchingRegions(pattern, patternStart, patternEnd, name, nameStart, nameEnd, samePartCount) != null; }
Answers all the regions in a given name matching a given pattern using a specified match rule.

Each of these regions is made of its starting index and its length in the given name. They are all concatenated in a single array of int which therefore always has an even length.

All returned regions are disjointed from each other. That means that the end of a region is always different than the start of the following one.
For example, if two regions are returned:
{ start1, length1, start2, length2 }
then start1+length1 will always be smaller than start2.

The possible comparison rules between the name and the pattern are:

Each of these rules may be combined with the case sensitive flag if the match comparison should respect the case.

Examples:

  1. pattern = "NPE" name = NullPointerException / NoPermissionException matchRule = R_CAMELCASE_MATCH result: { 0, 1, 4, 1, 11, 1 } / { 0, 1, 2, 1, 12, 1 }
  2. pattern = "NuPoEx" name = NullPointerException matchRule = R_CAMELCASE_MATCH result: { 0, 2, 4, 2, 11, 2 }
  3. pattern = "IPL3" name = "IPerspectiveListener3" matchRule = R_CAMELCASE_MATCH result: { 0, 2, 12, 1, 20, 1 }
  4. pattern = "HashME" name = "HashMapEntry" matchRule = R_CAMELCASE_MATCH result: { 0, 5, 7, 1 }
  5. pattern = "N???Po*Ex?eption" name = NullPointerException matchRule = R_PATTERN_MATCH | R_CASE_SENSITIVE result: { 0, 1, 4, 2, 11, 2, 14, 6 }
  6. pattern = "Ha*M*ent*" name = "HashMapEntry" matchRule = R_PATTERN_MATCH result: { 0, 2, 4, 1, 7, 3 }
Params:
See Also:
Returns:an array of int having two slots per returned regions (the first one is the region starting index and the second one is the region length or null if the given name does not match the given pattern).

The returned regions may be empty (new int[0]) if the pattern is null (whatever the match rule is). The returned regions will also be empty if the pattern is only made of '?' and/or '*' character(s) (e.g. '*', '?*', '???', etc.) when using a pattern match rule.

Since:3.5
/** * Answers all the regions in a given name matching a given pattern using * a specified match rule. * <p> * Each of these regions is made of its starting index and its length in the given * name. They are all concatenated in a single array of <code>int</code> * which therefore always has an even length. * </p><p> * All returned regions are disjointed from each other. That means that the end * of a region is always different than the start of the following one.<br> * For example, if two regions are returned:<br> * <code>{ start1, length1, start2, length2 }</code><br> * then <code>start1+length1</code> will always be smaller than * <code>start2</code>. * </p><p> * The possible comparison rules between the name and the pattern are: * <ul> * <li>{@link #R_EXACT_MATCH exact matching}</li> * <li>{@link #R_PREFIX_MATCH prefix matching}</li> * <li>{@link #R_PATTERN_MATCH pattern matching}</li> * <li>{@link #R_CAMELCASE_MATCH camel case matching}</li> * <li>{@link #R_CAMELCASE_SAME_PART_COUNT_MATCH camel case matching with same parts count}</li> * </ul> * Each of these rules may be combined with the * {@link #R_CASE_SENSITIVE case sensitive flag} if the match comparison * should respect the case. * <p> * Examples: * <ol><li> pattern = "NPE" * name = NullPointerException / NoPermissionException * matchRule = {@link #R_CAMELCASE_MATCH} * result: { 0, 1, 4, 1, 11, 1 } / { 0, 1, 2, 1, 12, 1 } </li> * <li> pattern = "NuPoEx" * name = NullPointerException * matchRule = {@link #R_CAMELCASE_MATCH} * result: { 0, 2, 4, 2, 11, 2 }</li> * <li> pattern = "IPL3" * name = "IPerspectiveListener3" * matchRule = {@link #R_CAMELCASE_MATCH} * result: { 0, 2, 12, 1, 20, 1 }</li> * <li> pattern = "HashME" * name = "HashMapEntry" * matchRule = {@link #R_CAMELCASE_MATCH} * result: { 0, 5, 7, 1 }</li> * <li> pattern = "N???Po*Ex?eption" * name = NullPointerException * matchRule = {@link #R_PATTERN_MATCH} | {@link #R_CASE_SENSITIVE} * result: { 0, 1, 4, 2, 11, 2, 14, 6 }</li> * <li> pattern = "Ha*M*ent*" * name = "HashMapEntry" * matchRule = {@link #R_PATTERN_MATCH} * result: { 0, 2, 4, 1, 7, 3 }</li> * </ol> * * @see #camelCaseMatch(String, String, boolean) for more details on the * camel case behavior * @see CharOperation#match(char[], char[], boolean) for more details on the * pattern match behavior * * @param pattern the given pattern. If <code>null</code>, * then an empty region (<code>new int[0]</code>) will be returned * showing that the name matches the pattern but no common * character has been found. * @param name the given name * @param matchRule the rule to apply for the comparison.<br> * The following values are accepted: * <ul> * <li>{@link #R_EXACT_MATCH}</li> * <li>{@link #R_PREFIX_MATCH}</li> * <li>{@link #R_PATTERN_MATCH}</li> * <li>{@link #R_CAMELCASE_MATCH}</li> * <li>{@link #R_CAMELCASE_SAME_PART_COUNT_MATCH}</li> * </ul> * <p> * Each of these valid values may be also combined with * the {@link #R_CASE_SENSITIVE} flag. * </p> * Some examples: * <ul> * <li>{@link #R_EXACT_MATCH} | {@link #R_CASE_SENSITIVE}: * if an exact case sensitive match is expected,</li> * <li>{@link #R_PREFIX_MATCH}: * if a case insensitive prefix match is expected,</li> * <li>{@link #R_CAMELCASE_MATCH}: * if a case insensitive camel case match is expected,</li> * <li>{@link #R_CAMELCASE_SAME_PART_COUNT_MATCH} * | {@link #R_CASE_SENSITIVE}: * if a case sensitive camel case with same parts count match * is expected,</li> * <li>etc.</li> * </ul> * @return an array of <code>int</code> having two slots per returned * regions (the first one is the region starting index and the second one * is the region length or <code>null</code> if the given name does not * match the given pattern). * <p> * The returned regions may be empty (<code>new int[0]</code>) if the * pattern is <code>null</code> (whatever the match rule is). The returned * regions will also be empty if the pattern is only made of <code>'?'</code> * and/or <code>'*'</code> character(s) (e.g. <code>'*'</code>, * <code>'?*'</code>, <code>'???'</code>, etc.) when using a pattern * match rule. * </p> * * @since 3.5 */
public static final int[] getMatchingRegions(String pattern, String name, int matchRule) { if (name == null) return null; final int nameLength = name.length(); if (pattern == null) { return new int[] { 0, nameLength }; } final int patternLength = pattern.length(); boolean countMatch = false; switch (matchRule) { case SearchPattern.R_EXACT_MATCH: if (patternLength == nameLength && pattern.equalsIgnoreCase(name)) { return new int[] { 0, patternLength }; } break; case SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE: if (patternLength == nameLength && pattern.equals(name)) { return new int[] { 0, patternLength }; } break; case SearchPattern.R_PREFIX_MATCH: if (patternLength <= nameLength && name.substring(0, patternLength).equalsIgnoreCase(pattern)) { return new int[] { 0, patternLength }; } break; case SearchPattern.R_PREFIX_MATCH | SearchPattern.R_CASE_SENSITIVE: if (name.startsWith(pattern)) { return new int[] { 0, patternLength }; } break; case SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH: countMatch = true; //$FALL-THROUGH$ case SearchPattern.R_CAMELCASE_MATCH: if (patternLength <= nameLength) { int[] regions = StringOperation.getCamelCaseMatchingRegions(pattern, 0, patternLength, name, 0, nameLength, countMatch); if (regions != null) return regions; if (name.substring(0, patternLength).equalsIgnoreCase(pattern)) { return new int[] { 0, patternLength }; } } break; case SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH | SearchPattern.R_CASE_SENSITIVE: countMatch = true; //$FALL-THROUGH$ case SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_CASE_SENSITIVE: if (patternLength <= nameLength) { return StringOperation.getCamelCaseMatchingRegions(pattern, 0, patternLength, name, 0, nameLength, countMatch); } break; case SearchPattern.R_PATTERN_MATCH: return StringOperation.getPatternMatchingRegions(pattern, 0, patternLength, name, 0, nameLength, false); case SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE: return StringOperation.getPatternMatchingRegions(pattern, 0, patternLength, name, 0, nameLength, true); case SearchPattern.R_SUBSTRING_MATCH: if (patternLength <= nameLength) { int next = CharOperation.indexOf(pattern.toCharArray(), name.toCharArray(), false); return next >= 0 ? new int[] {next, patternLength} : null; } break; } return null; }
Returns a search pattern that combines the given two patterns into an "and" pattern. The search result will match both the left pattern and the right pattern.
Params:
  • leftPattern – the left pattern
  • rightPattern – the right pattern
Returns:an "and" pattern
Deprecated:Unfortunately, this functionality is not fully supported yet (see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=142044" for more details). This might be done in a further version...
/** * Returns a search pattern that combines the given two patterns into an * "and" pattern. The search result will match both the left pattern and * the right pattern. * * @param leftPattern the left pattern * @param rightPattern the right pattern * @return an "and" pattern * @deprecated Unfortunately, this functionality is not fully supported yet * (see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=142044" for more details). * This might be done in a further version... */
public static SearchPattern createAndPattern(SearchPattern leftPattern, SearchPattern rightPattern) { return new AndPattern(leftPattern, rightPattern); } private static SearchPattern createFieldPattern(String patternString, int limitTo, int matchRule) { // use 1.7 as the source level as there are more valid tokens in 1.7 mode // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376673 Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_7/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/); scanner.setSource(patternString.toCharArray()); final int InsideDeclaringPart = 1; final int InsideType = 2; int lastToken = -1; String declaringType = null, fieldName = null; String type = null; int mode = InsideDeclaringPart; int token; try { token = scanner.getNextToken(); } catch (InvalidInputException e) { return null; } while (token != TerminalTokens.TokenNameEOF) { switch(mode) { // read declaring type and fieldName case InsideDeclaringPart : switch (token) { case TerminalTokens.TokenNameDOT: if (declaringType == null) { if (fieldName == null) return null; declaringType = fieldName; } else { String tokenSource = scanner.getCurrentTokenString(); declaringType += tokenSource + fieldName; } fieldName = null; break; case TerminalTokens.TokenNameWHITESPACE: if (!(TerminalTokens.TokenNameWHITESPACE == lastToken || TerminalTokens.TokenNameDOT == lastToken)) mode = InsideType; break; default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search]) if (fieldName == null) fieldName = scanner.getCurrentTokenString(); else fieldName += scanner.getCurrentTokenString(); } break; // read type case InsideType: switch (token) { case TerminalTokens.TokenNameWHITESPACE: break; default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search]) if (type == null) type = scanner.getCurrentTokenString(); else type += scanner.getCurrentTokenString(); } break; } lastToken = token; try { token = scanner.getNextToken(); } catch (InvalidInputException e) { return null; } } if (fieldName == null) return null; char[] fieldNameChars = fieldName.toCharArray(); if (fieldNameChars.length == 1 && fieldNameChars[0] == '*') fieldNameChars = null; char[] declaringTypeQualification = null, declaringTypeSimpleName = null; char[] typeQualification = null, typeSimpleName = null; // extract declaring type infos if (declaringType != null) { char[] declaringTypePart = declaringType.toCharArray(); int lastDotPosition = CharOperation.lastIndexOf('.', declaringTypePart); if (lastDotPosition >= 0) { declaringTypeQualification = CharOperation.subarray(declaringTypePart, 0, lastDotPosition); if (declaringTypeQualification.length == 1 && declaringTypeQualification[0] == '*') declaringTypeQualification = null; declaringTypeSimpleName = CharOperation.subarray(declaringTypePart, lastDotPosition+1, declaringTypePart.length); } else { declaringTypeSimpleName = declaringTypePart; } if (declaringTypeSimpleName.length == 1 && declaringTypeSimpleName[0] == '*') declaringTypeSimpleName = null; } // extract type infos if (type != null) { char[] typePart = type.toCharArray(); int lastDotPosition = CharOperation.lastIndexOf('.', typePart); if (lastDotPosition >= 0) { typeQualification = CharOperation.subarray(typePart, 0, lastDotPosition); if (typeQualification.length == 1 && typeQualification[0] == '*') { typeQualification = null; } else { // prefix with a '*' as the full qualification could be bigger (because of an import) typeQualification = CharOperation.concat(IIndexConstants.ONE_STAR, typeQualification); } typeSimpleName = CharOperation.subarray(typePart, lastDotPosition+1, typePart.length); } else { typeSimpleName = typePart; } if (typeSimpleName.length == 1 && typeSimpleName[0] == '*') typeSimpleName = null; } // Create field pattern return new FieldPattern( fieldNameChars, declaringTypeQualification, declaringTypeSimpleName, typeQualification, typeSimpleName, limitTo, matchRule); } private static SearchPattern createMethodOrConstructorPattern(String patternString, int limitTo, int matchRule, boolean isConstructor) { // use 1.7 as the source level as there are more valid tokens in 1.7 mode // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376673 Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_7/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/); scanner.setSource(patternString.toCharArray()); final int InsideSelector = 1; final int InsideTypeArguments = 2; final int InsideParameter = 3; final int InsideReturnType = 4; int lastToken = -1; String declaringType = null, selector = null, parameterType = null; String[] parameterTypes = null; char[][] typeArguments = null; String typeArgumentsString = null; int parameterCount = -1; String returnType = null; boolean foundClosingParenthesis = false; int mode = InsideSelector; int token, argCount = 0; try { token = scanner.getNextToken(); } catch (InvalidInputException e) { return null; } while (token != TerminalTokens.TokenNameEOF) { switch(mode) { // read declaring type and selector case InsideSelector : if (argCount == 0) { switch (token) { case TerminalTokens.TokenNameLESS: argCount++; if (selector == null || lastToken == TerminalTokens.TokenNameDOT) { typeArgumentsString = scanner.getCurrentTokenString(); mode = InsideTypeArguments; break; } if (declaringType == null) { declaringType = selector; } else { declaringType += '.' + selector; } declaringType += scanner.getCurrentTokenString(); selector = null; break; case TerminalTokens.TokenNameDOT: if (!isConstructor && typeArgumentsString != null) return null; // invalid syntax if (declaringType == null) { if (selector == null) return null; // invalid syntax declaringType = selector; } else if (selector != null) { declaringType += scanner.getCurrentTokenString() + selector; } selector = null; break; case TerminalTokens.TokenNameLPAREN: parameterTypes = new String[5]; parameterCount = 0; mode = InsideParameter; break; case TerminalTokens.TokenNameWHITESPACE: switch (lastToken) { case TerminalTokens.TokenNameWHITESPACE: case TerminalTokens.TokenNameDOT: case TerminalTokens.TokenNameGREATER: case TerminalTokens.TokenNameRIGHT_SHIFT: case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT: break; default: mode = InsideReturnType; break; } break; default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search]) if (selector == null) selector = scanner.getCurrentTokenString(); else selector += scanner.getCurrentTokenString(); break; } } else { if (declaringType == null) return null; // invalid syntax switch (token) { case TerminalTokens.TokenNameGREATER: case TerminalTokens.TokenNameRIGHT_SHIFT: case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT: argCount--; break; case TerminalTokens.TokenNameLESS: argCount++; break; } declaringType += scanner.getCurrentTokenString(); } break; // read type arguments case InsideTypeArguments: if (typeArgumentsString == null) return null; // invalid syntax typeArgumentsString += scanner.getCurrentTokenString(); switch (token) { case TerminalTokens.TokenNameGREATER: case TerminalTokens.TokenNameRIGHT_SHIFT: case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT: argCount--; if (argCount == 0) { String pseudoType = "Type"+typeArgumentsString; //$NON-NLS-1$ typeArguments = Signature.getTypeArguments(Signature.createTypeSignature(pseudoType, false).toCharArray()); mode = InsideSelector; } break; case TerminalTokens.TokenNameLESS: argCount++; break; } break; // read parameter types case InsideParameter : if (argCount == 0) { switch (token) { case TerminalTokens.TokenNameWHITESPACE: break; case TerminalTokens.TokenNameCOMMA: if (parameterType == null) return null; if (parameterTypes != null) { if (parameterTypes.length == parameterCount) System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount); parameterTypes[parameterCount++] = parameterType; } parameterType = null; break; case TerminalTokens.TokenNameRPAREN: foundClosingParenthesis = true; if (parameterType != null && parameterTypes != null) { if (parameterTypes.length == parameterCount) System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount); parameterTypes[parameterCount++] = parameterType; } mode = isConstructor ? InsideTypeArguments : InsideReturnType; break; case TerminalTokens.TokenNameLESS: argCount++; if (parameterType == null) return null; // invalid syntax // $FALL-THROUGH$ - fall through next case to add token default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search]) if (parameterType == null) parameterType = scanner.getCurrentTokenString(); else parameterType += scanner.getCurrentTokenString(); } } else { if (parameterType == null) return null; // invalid syntax switch (token) { case TerminalTokens.TokenNameGREATER: case TerminalTokens.TokenNameRIGHT_SHIFT: case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT: argCount--; break; case TerminalTokens.TokenNameLESS: argCount++; break; } parameterType += scanner.getCurrentTokenString(); } break; // read return type case InsideReturnType: if (argCount == 0) { switch (token) { case TerminalTokens.TokenNameWHITESPACE: break; case TerminalTokens.TokenNameLPAREN: parameterTypes = new String[5]; parameterCount = 0; mode = InsideParameter; break; case TerminalTokens.TokenNameLESS: argCount++; if (returnType == null) return null; // invalid syntax // $FALL-THROUGH$ - fall through next case to add token default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search]) if (returnType == null) returnType = scanner.getCurrentTokenString(); else returnType += scanner.getCurrentTokenString(); } } else { if (returnType == null) return null; // invalid syntax switch (token) { case TerminalTokens.TokenNameGREATER: case TerminalTokens.TokenNameRIGHT_SHIFT: case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT: argCount--; break; case TerminalTokens.TokenNameLESS: argCount++; break; } returnType += scanner.getCurrentTokenString(); } break; } lastToken = token; try { token = scanner.getNextToken(); } catch (InvalidInputException e) { return null; } } // parenthesis mismatch if (parameterCount>0 && !foundClosingParenthesis) return null; // type arguments mismatch if (argCount > 0) return null; char[] selectorChars = null; if (isConstructor) { // retrieve type for constructor patterns if (declaringType == null) declaringType = selector; else if (selector != null) declaringType += '.' + selector; } else { // get selector chars if (selector == null) return null; selectorChars = selector.toCharArray(); if (selectorChars.length == 1 && selectorChars[0] == '*') selectorChars = null; } char[] declaringTypeQualification = null, declaringTypeSimpleName = null; char[] returnTypeQualification = null, returnTypeSimpleName = null; char[][] parameterTypeQualifications = null, parameterTypeSimpleNames = null; // Signatures String declaringTypeSignature = null; String returnTypeSignature = null; String[] parameterTypeSignatures = null; // extract declaring type infos if (declaringType != null) { // get declaring type part and signature char[] declaringTypePart = null; try { declaringTypeSignature = Signature.createTypeSignature(declaringType, false); if (declaringTypeSignature.indexOf(Signature.C_GENERIC_START) < 0) { declaringTypePart = declaringType.toCharArray(); } else { declaringTypePart = Signature.toCharArray(Signature.getTypeErasure(declaringTypeSignature.toCharArray())); } } catch (IllegalArgumentException iae) { // declaring type is invalid return null; } int lastDotPosition = CharOperation.lastIndexOf('.', declaringTypePart); if (lastDotPosition >= 0) { declaringTypeQualification = CharOperation.subarray(declaringTypePart, 0, lastDotPosition); if (declaringTypeQualification.length == 1 && declaringTypeQualification[0] == '*') declaringTypeQualification = null; declaringTypeSimpleName = CharOperation.subarray(declaringTypePart, lastDotPosition+1, declaringTypePart.length); } else { declaringTypeSimpleName = declaringTypePart; } if (declaringTypeSimpleName.length == 1 && declaringTypeSimpleName[0] == '*') declaringTypeSimpleName = null; } // extract parameter types infos if (parameterCount >= 0) { parameterTypeQualifications = new char[parameterCount][]; parameterTypeSimpleNames = new char[parameterCount][]; parameterTypeSignatures = new String[parameterCount]; for (int i = 0; i < parameterCount; i++) { // get parameter type part and signature char[] parameterTypePart = null; try { if (parameterTypes != null) { parameterTypeSignatures[i] = Signature.createTypeSignature(parameterTypes[i], false); if (parameterTypeSignatures[i].indexOf(Signature.C_GENERIC_START) < 0) { parameterTypePart = parameterTypes[i].toCharArray(); } else { parameterTypePart = Signature.toCharArray(Signature.getTypeErasure(parameterTypeSignatures[i].toCharArray())); } } } catch (IllegalArgumentException iae) { // string is not a valid type syntax return null; } int lastDotPosition = parameterTypePart==null ? -1 : CharOperation.lastIndexOf('.', parameterTypePart); if (parameterTypePart != null && lastDotPosition >= 0) { parameterTypeQualifications[i] = CharOperation.subarray(parameterTypePart, 0, lastDotPosition); if (parameterTypeQualifications[i].length == 1 && parameterTypeQualifications[i][0] == '*') { parameterTypeQualifications[i] = null; } else { // prefix with a '*' as the full qualification could be bigger (because of an import) parameterTypeQualifications[i] = CharOperation.concat(IIndexConstants.ONE_STAR, parameterTypeQualifications[i]); } parameterTypeSimpleNames[i] = CharOperation.subarray(parameterTypePart, lastDotPosition+1, parameterTypePart.length); } else { parameterTypeQualifications[i] = null; parameterTypeSimpleNames[i] = parameterTypePart; } if (parameterTypeSimpleNames[i].length == 1 && parameterTypeSimpleNames[i][0] == '*') parameterTypeSimpleNames[i] = null; } } // extract return type infos if (returnType != null) { // get return type part and signature char[] returnTypePart = null; try { returnTypeSignature = Signature.createTypeSignature(returnType, false); if (returnTypeSignature.indexOf(Signature.C_GENERIC_START) < 0) { returnTypePart = returnType.toCharArray(); } else { returnTypePart = Signature.toCharArray(Signature.getTypeErasure(returnTypeSignature.toCharArray())); } } catch (IllegalArgumentException iae) { // declaring type is invalid return null; } int lastDotPosition = CharOperation.lastIndexOf('.', returnTypePart); if (lastDotPosition >= 0) { returnTypeQualification = CharOperation.subarray(returnTypePart, 0, lastDotPosition); if (returnTypeQualification.length == 1 && returnTypeQualification[0] == '*') { returnTypeQualification = null; } else { // because of an import returnTypeQualification = CharOperation.concat(IIndexConstants.ONE_STAR, returnTypeQualification); } returnTypeSimpleName = CharOperation.subarray(returnTypePart, lastDotPosition+1, returnTypePart.length); } else { returnTypeSimpleName = returnTypePart; } if (returnTypeSimpleName.length == 1 && returnTypeSimpleName[0] == '*') returnTypeSimpleName = null; } // Create method/constructor pattern if (isConstructor) { return new ConstructorPattern( declaringTypeSimpleName, declaringTypeQualification, declaringTypeSignature, parameterTypeQualifications, parameterTypeSimpleNames, parameterTypeSignatures, typeArguments, limitTo, matchRule); } else { return new MethodPattern( selectorChars, declaringTypeQualification, declaringTypeSimpleName, declaringTypeSignature, returnTypeQualification, returnTypeSimpleName, returnTypeSignature, parameterTypeQualifications, parameterTypeSimpleNames, parameterTypeSignatures, typeArguments, limitTo, matchRule); } } private static SearchPattern createModulePattern(String patternString, int limitTo, int matchRule) { return new ModulePattern(patternString.toCharArray(), limitTo, matchRule); }
Returns a search pattern that combines the given two patterns into an "or" pattern. The search result will match either the left pattern or the right pattern.
Params:
  • leftPattern – the left pattern
  • rightPattern – the right pattern
Returns:an "or" pattern
/** * Returns a search pattern that combines the given two patterns into an * "or" pattern. The search result will match either the left pattern or the * right pattern. * * @param leftPattern the left pattern * @param rightPattern the right pattern * @return an "or" pattern */
public static SearchPattern createOrPattern(SearchPattern leftPattern, SearchPattern rightPattern) { return new OrPattern(leftPattern, rightPattern); } private static SearchPattern createPackagePattern(String patternString, int limitTo, int matchRule) { switch (limitTo) { case IJavaSearchConstants.DECLARATIONS : return new PackageDeclarationPattern(patternString.toCharArray(), matchRule); case IJavaSearchConstants.REFERENCES : return new PackageReferencePattern(patternString.toCharArray(), matchRule); case IJavaSearchConstants.ALL_OCCURRENCES : return new OrPattern( new PackageDeclarationPattern(patternString.toCharArray(), matchRule), new PackageReferencePattern(patternString.toCharArray(), matchRule) ); } return null; }
Returns a search pattern based on a given string pattern. The string patterns support '*' wild-cards. The remaining parameters are used to narrow down the type of expected results.
Examples:
  • search for case insensitive references to Object: createSearchPattern("Object", IJavaSearchConstants.TYPE, IJavaSearchConstants.REFERENCES, false);
  • search for case sensitive references to exact Object() constructor: createSearchPattern("java.lang.Object()", IJavaSearchConstants.CONSTRUCTOR, IJavaSearchConstants.REFERENCES, true);
  • search for implementers of java.lang.Runnable: createSearchPattern("java.lang.Runnable", IJavaSearchConstants.TYPE, IJavaSearchConstants.IMPLEMENTORS, true);
Params:
  • stringPattern – the given pattern
    • Type patterns have the following syntax:

      [qualification '.']typeName ['<' typeArguments '>']

      Examples:

      • java.lang.Object
      • Runnable
      • List<String>

      Type arguments can be specified to search for references to parameterized types using following syntax:

      '<' { [ '?' {'extends'|'super'} ] type ( ',' [ '?' {'extends'|'super'} ] type )* | '?' } '>'

      Note that:
      • '*' is not valid inside type arguments definition <>
      • '?' is treated as a wildcard when it is inside <> (i.e. it must be put on first position of the type argument)
      Since 3.14 for Java 9, Type Declaration Patterns can have module names also embedded with the following syntax

      [moduleName1[,moduleName2,..]]/[qualification '.']typeName ['<' typeArguments '>']

      Unnamed modules can also be included and are represented either by an absence of module name implicitly or explicitly by specifying ALL-UNNAMED for module name. Module graph search is also supported with the limitTo option set to IJavaSearchConstants.MODULE_GRAPH. In the module graph case, the given type is searched in all the modules required directly as well as indirectly by the given module(s).

      Note that whitespaces are ignored in between module names. It is an error to give multiple module separators - in such cases a null pattern will be returned.

      Examples:

      • java.base/java.lang.Object
      • mod.one, mod.two/pack.X find declaration in the list of given modules.
      • /pack.X find in the unnamed module.
      • ALL-UNNAMED/pack.X find in the unnamed module.

    • Method patterns have the following syntax:

      [declaringType '.'] ['<' typeArguments '>'] methodName ['(' parameterTypes ')'] [returnType]

      Type arguments have the same syntax as explained in the type patterns section.

      Examples:

      • java.lang.Runnable.run() void
      • main(*)
      • <String>toArray(String[])
    • Constructor patterns have the following syntax:

      ['<' typeArguments '>'] [declaringQualification '.'] typeName ['(' parameterTypes ')']

      Type arguments have the same syntax as explained in the type patterns section.

      Note that the constructor name should not be entered as it is always the same as the type name.

      Examples:

      • java.lang.Object()
      • Test(*)
      • <Exception>Sample(Exception)

    • Field patterns have the following syntax:

      [declaringType '.'] fieldName [fieldType]

      Examples:

      • java.lang.String.serialVersionUID long
      • field*
    • Package patterns have the following syntax:

      packageNameSegment {'.' packageNameSegment}

      Examples:

      • java.lang
      • org.e*.jdt.c*e
  • searchFor – determines the nature of the searched elements
  • limitTo – determines the nature of the expected matches
  • matchRule – one of the following match rules , which may be also combined with one of the following flags: For example,

    Note that R_ERASURE_MATCH or R_EQUIVALENT_MATCH has no effect on non-generic types/methods search.

    Note that R_REGEXP_MATCH is supported since 3.14 for the special case of DECLARATIONS search of MODULE

    Note also that the default behavior for generic types/methods search is to find exact matches.

Returns:a search pattern on the given string pattern, or null if the string pattern is ill-formed
/** * Returns a search pattern based on a given string pattern. The string patterns support '*' wild-cards. * The remaining parameters are used to narrow down the type of expected results. * * <br> * Examples: * <ul> * <li>search for case insensitive references to <code>Object</code>: * <code>createSearchPattern("Object", IJavaSearchConstants.TYPE, IJavaSearchConstants.REFERENCES, false);</code></li> * <li>search for case sensitive references to exact <code>Object()</code> constructor: * <code>createSearchPattern("java.lang.Object()", IJavaSearchConstants.CONSTRUCTOR, IJavaSearchConstants.REFERENCES, true);</code></li> * <li>search for implementers of <code>java.lang.Runnable</code>: * <code>createSearchPattern("java.lang.Runnable", IJavaSearchConstants.TYPE, IJavaSearchConstants.IMPLEMENTORS, true);</code></li> * </ul> * @param stringPattern the given pattern * <ul> * <li>Type patterns have the following syntax: * <p><b><code>[qualification '.']typeName ['&lt;' typeArguments '&gt;']</code></b></p> * <p>Examples:</p> * <ul> * <li><code>java.lang.Object</code></li> * <li><code>Runnable</code></li> * <li><code>List&lt;String&gt;</code></li> * </ul> * <p> * Type arguments can be specified to search for references to parameterized types * using following syntax:</p><p> * <b><code>'&lt;' { [ '?' {'extends'|'super'} ] type ( ',' [ '?' {'extends'|'super'} ] type )* | '?' } '&gt;'</code></b> * </p><div style="font-style:italic;"> * Note that: * <ul> * <li>'*' is not valid inside type arguments definition &lt;&gt;</li> * <li>'?' is treated as a wildcard when it is inside &lt;&gt; (i.e. it must be put on first position of the type argument)</li> * </ul> * </div> * Since 3.14 for Java 9, Type Declaration Patterns can have module names also embedded with the following syntax * <p><b><code>[moduleName1[,moduleName2,..]]/[qualification '.']typeName ['&lt;' typeArguments '&gt;']</code></b> * </p> * <p> * Unnamed modules can also be included and are represented either by an absence of module name implicitly * or explicitly by specifying ALL-UNNAMED for module name. * Module graph search is also supported with the limitTo option set to <code>IJavaSearchConstants.MODULE_GRAPH</code>. * In the module graph case, the given type is searched in all the modules required directly as well * as indirectly by the given module(s). * </p> * <p> * Note that whitespaces are ignored in between module names. It is an error to give multiple module separators - in such * cases a null pattern will be returned. * </p> * <p>Examples:</p> * <ul> * <li><code>java.base/java.lang.Object</code></li> * <li><code>mod.one, mod.two/pack.X</code> find declaration in the list of given modules.</li> * <li><code>/pack.X</code> find in the unnamed module.</li> * <li><code>ALL-UNNAMED/pack.X</code> find in the unnamed module.</li> * </ul> * <p> * </li> * <li>Method patterns have the following syntax: * <p><b><code>[declaringType '.'] ['&lt;' typeArguments '&gt;'] methodName ['(' parameterTypes ')'] [returnType]</code></b></p> * <p>Type arguments have the same syntax as explained in the type patterns section.</p> * <p>Examples:</p> * <ul> * <li><code>java.lang.Runnable.run() void</code></li> * <li><code>main(*)</code></li> * <li><code>&lt;String&gt;toArray(String[])</code></li> * </ul> * </li> * <li>Constructor patterns have the following syntax: * <p><b><code>['&lt;' typeArguments '&gt;'] [declaringQualification '.'] typeName ['(' parameterTypes ')']</code></b></p> * <p>Type arguments have the same syntax as explained in the type patterns section.</p> * <p><i>Note that the constructor name should not be entered as it is always the same as the type name.</i></p> * <p>Examples:</p> * <ul> * <li><code>java.lang.Object()</code></li> * <li><code>Test(*)</code></li> * <li><code>&lt;Exception&gt;Sample(Exception)</code></li> * </ul> * <br> * </li> * <li>Field patterns have the following syntax: * <p><b><code>[declaringType '.'] fieldName [fieldType]</code></b></p> * <p>Examples:</p> * <ul> * <li><code>java.lang.String.serialVersionUID long</code></li> * <li><code>field*</code></li> * </ul> * </li> * <li>Package patterns have the following syntax: * <p><b><code>packageNameSegment {'.' packageNameSegment}</code></b></p> * <p>Examples:</p> * <ul> * <li><code>java.lang</code></li> * <li><code>org.e*.jdt.c*e</code></li> * </ul> * </li> * </ul> * @param searchFor determines the nature of the searched elements * <ul> * <li>{@link IJavaSearchConstants#CLASS}: only look for classes</li> * <li>{@link IJavaSearchConstants#INTERFACE}: only look for interfaces</li> * <li>{@link IJavaSearchConstants#ENUM}: only look for enumeration</li> * <li>{@link IJavaSearchConstants#ANNOTATION_TYPE}: only look for annotation type</li> * <li>{@link IJavaSearchConstants#CLASS_AND_ENUM}: only look for classes and enumerations</li> * <li>{@link IJavaSearchConstants#CLASS_AND_INTERFACE}: only look for classes and interfaces</li> * <li>{@link IJavaSearchConstants#TYPE}: look for all types (i.e. classes, interfaces, enum and annotation types)</li> * <li>{@link IJavaSearchConstants#FIELD}: look for fields</li> * <li>{@link IJavaSearchConstants#METHOD}: look for methods</li> * <li>{@link IJavaSearchConstants#CONSTRUCTOR}: look for constructors</li> * <li>{@link IJavaSearchConstants#PACKAGE}: look for packages</li> * <li>{@link IJavaSearchConstants#MODULE}: look for modules</li> * </ul> * @param limitTo determines the nature of the expected matches * <ul> * <li>{@link IJavaSearchConstants#DECLARATIONS DECLARATIONS}: will search declarations matching * with the corresponding element. In case the element is a method, declarations of matching * methods in sub-types will also be found, allowing to find declarations of abstract methods, etc.<br> * Note that additional flags {@link IJavaSearchConstants#IGNORE_DECLARING_TYPE IGNORE_DECLARING_TYPE} and * {@link IJavaSearchConstants#IGNORE_RETURN_TYPE IGNORE_RETURN_TYPE} are ignored for string patterns. * This is due to the fact that client may omit to define them in string pattern to have same behavior. * </li> * <li>{@link IJavaSearchConstants#REFERENCES REFERENCES}: will search references to the given element.</li> * <li>{@link IJavaSearchConstants#ALL_OCCURRENCES ALL_OCCURRENCES}: will search for either declarations or * references as specified above. * </li> * <li>{@link IJavaSearchConstants#IMPLEMENTORS IMPLEMENTORS}: for types, will find all types * which directly implement/extend a given interface. * Note that types may be only classes or only interfaces if {@link IJavaSearchConstants#CLASS CLASS} or * {@link IJavaSearchConstants#INTERFACE INTERFACE} is respectively used instead of {@link IJavaSearchConstants#TYPE TYPE}. * </li> * <li>{@link IJavaSearchConstants#MODULE_GRAPH MODULE_GRAPH}: for types with a module prefix, * will find all types present in required modules (directly or indirectly required) ie * in any module present in the module graph of the given module. * </li> * <li>All other fine grain constants defined in the <b>limitTo</b> category * of the {@link IJavaSearchConstants} are also accepted nature: * <table> * <tr> * <th>Fine grain constant * <th>Meaning * <tr> * <td>{@link IJavaSearchConstants#FIELD_DECLARATION_TYPE_REFERENCE FIELD_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used as the type of a field declaration. * <tr> * <td>{@link IJavaSearchConstants#LOCAL_VARIABLE_DECLARATION_TYPE_REFERENCE LOCAL_VARIABLE_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used as the type of a local variable declaration. * <tr> * <td>{@link IJavaSearchConstants#PARAMETER_DECLARATION_TYPE_REFERENCE PARAMETER_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used as the type of a method parameter declaration. * <tr> * <td>{@link IJavaSearchConstants#SUPERTYPE_TYPE_REFERENCE SUPERTYPE_TYPE_REFERENCE} * <td>Return only type references used as a super type or as a super interface. * <tr> * <td>{@link IJavaSearchConstants#THROWS_CLAUSE_TYPE_REFERENCE THROWS_CLAUSE_TYPE_REFERENCE} * <td>Return only type references used in a throws clause. * <tr> * <td>{@link IJavaSearchConstants#CAST_TYPE_REFERENCE CAST_TYPE_REFERENCE} * <td>Return only type references used in a cast expression. * <tr> * <td>{@link IJavaSearchConstants#CATCH_TYPE_REFERENCE CATCH_TYPE_REFERENCE} * <td>Return only type references used in a catch header. * <tr> * <td>{@link IJavaSearchConstants#CLASS_INSTANCE_CREATION_TYPE_REFERENCE CLASS_INSTANCE_CREATION_TYPE_REFERENCE} * <td>Return only type references used in class instance creation. * <tr> * <td>{@link IJavaSearchConstants#RETURN_TYPE_REFERENCE RETURN_TYPE_REFERENCE} * <td>Return only type references used as a method return type. * <tr> * <td>{@link IJavaSearchConstants#IMPORT_DECLARATION_TYPE_REFERENCE IMPORT_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used in an import declaration. * <tr> * <td>{@link IJavaSearchConstants#ANNOTATION_TYPE_REFERENCE ANNOTATION_TYPE_REFERENCE} * <td>Return only type references used as an annotation. * <tr> * <td>{@link IJavaSearchConstants#TYPE_ARGUMENT_TYPE_REFERENCE TYPE_ARGUMENT_TYPE_REFERENCE} * <td>Return only type references used as a type argument in a parameterized type or a parameterized method. * <tr> * <td>{@link IJavaSearchConstants#TYPE_VARIABLE_BOUND_TYPE_REFERENCE TYPE_VARIABLE_BOUND_TYPE_REFERENCE} * <td>Return only type references used as a type variable bound. * <tr> * <td>{@link IJavaSearchConstants#WILDCARD_BOUND_TYPE_REFERENCE WILDCARD_BOUND_TYPE_REFERENCE} * <td>Return only type references used as a wildcard bound. * <tr> * <td>{@link IJavaSearchConstants#INSTANCEOF_TYPE_REFERENCE INSTANCEOF_TYPE_REFERENCE} * <td>Return only type references used as a type of an <code>instanceof</code> expression. * <tr> * <td>{@link IJavaSearchConstants#SUPER_REFERENCE SUPER_REFERENCE} * <td>Return only super field accesses or super method invocations (e.g. using the <code>super</code> qualifier). * <tr> * <td>{@link IJavaSearchConstants#QUALIFIED_REFERENCE QUALIFIED_REFERENCE} * <td>Return only qualified field accesses or qualified method invocations. * <tr> * <td>{@link IJavaSearchConstants#THIS_REFERENCE THIS_REFERENCE} * <td>Return only primary field accesses or primary method invocations (e.g. using the <code>this</code> qualifier). * <tr> * <td>{@link IJavaSearchConstants#IMPLICIT_THIS_REFERENCE IMPLICIT_THIS_REFERENCE} * <td>Return only field accesses or method invocations without any qualification. * <tr> * <td>{@link IJavaSearchConstants#METHOD_REFERENCE_EXPRESSION METHOD_REFERENCE_EXPRESSION} * <td>Return only method reference expressions (e.g. <code>A :: foo</code>). * </table> * </li> * </ul> * @param matchRule one of the following match rules * <ul> * <li>{@link #R_EXACT_MATCH}</li> * <li>{@link #R_PREFIX_MATCH}</li> * <li>{@link #R_PATTERN_MATCH}</li> * <li>{@link #R_CAMELCASE_MATCH}</li> * <li>{@link #R_CAMELCASE_SAME_PART_COUNT_MATCH}</li> * </ul> * , which may be also combined with one of the following flags: * <ul> * <li>{@link #R_CASE_SENSITIVE}</li> * <li>{@link #R_ERASURE_MATCH}</li> * <li>{@link #R_EQUIVALENT_MATCH}</li> * </ul> * For example, * <ul> * <li>{@link #R_EXACT_MATCH} | {@link #R_CASE_SENSITIVE}: if an exact * and case sensitive match is requested,</li> * <li>{@link #R_PREFIX_MATCH} if a case insensitive prefix match is requested</li> * <li>{@link #R_EXACT_MATCH} | {@link #R_ERASURE_MATCH}: if a case * insensitive and erasure match is requested.</li> * </ul> * <p>Note that {@link #R_ERASURE_MATCH} or {@link #R_EQUIVALENT_MATCH} has no effect * on non-generic types/methods search.</p> * * <p>Note that {@link #R_REGEXP_MATCH} is supported since 3.14 for the special case of * {@link IJavaSearchConstants#DECLARATIONS DECLARATIONS} search of * {@link IJavaSearchConstants#MODULE MODULE}</p> * <p> * Note also that the default behavior for generic types/methods search is to find exact matches.</p> * @return a search pattern on the given string pattern, or <code>null</code> if the string pattern is ill-formed */
public static SearchPattern createPattern(String stringPattern, int searchFor, int limitTo, int matchRule) { if (stringPattern == null || stringPattern.length() == 0) return null; if ((matchRule = validateMatchRule(stringPattern, searchFor, limitTo, matchRule)) == -1) { return null; } // Ignore additional nature flags limitTo &= ~(IJavaSearchConstants.IGNORE_DECLARING_TYPE+IJavaSearchConstants.IGNORE_RETURN_TYPE); switch (searchFor) { case IJavaSearchConstants.CLASS: return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.CLASS_SUFFIX); case IJavaSearchConstants.CLASS_AND_INTERFACE: return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.CLASS_AND_INTERFACE_SUFFIX); case IJavaSearchConstants.CLASS_AND_ENUM: return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.CLASS_AND_ENUM_SUFFIX); case IJavaSearchConstants.INTERFACE: return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.INTERFACE_SUFFIX); case IJavaSearchConstants.INTERFACE_AND_ANNOTATION: return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.INTERFACE_AND_ANNOTATION_SUFFIX); case IJavaSearchConstants.ENUM: return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.ENUM_SUFFIX); case IJavaSearchConstants.ANNOTATION_TYPE: return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.ANNOTATION_TYPE_SUFFIX); case IJavaSearchConstants.TYPE: return createTypePattern(stringPattern, limitTo, matchRule, IIndexConstants.TYPE_SUFFIX); case IJavaSearchConstants.METHOD: return createMethodOrConstructorPattern(stringPattern, limitTo, matchRule, false/*not a constructor*/); case IJavaSearchConstants.CONSTRUCTOR: return createMethodOrConstructorPattern(stringPattern, limitTo, matchRule, true/*constructor*/); case IJavaSearchConstants.FIELD: return createFieldPattern(stringPattern, limitTo, matchRule); case IJavaSearchConstants.PACKAGE: return createPackagePattern(stringPattern, limitTo, matchRule); case IJavaSearchConstants.MODULE : return createModulePattern(stringPattern, limitTo, matchRule); } return null; }
Returns a search pattern based on a given Java element. The pattern is used to trigger the appropriate search.
Note that for generic searches, the returned pattern consider R_ERASURE_MATCH matches. If other kind of generic matches (i.e. R_EXACT_MATCH or R_EQUIVALENT_MATCH) are expected, createPattern(IJavaElement, int, int) method need to be used instead with the explicit match rule specified.
The pattern can be parameterized as follows:
Params:
  • element – the Java element the search pattern is based on
  • limitTo – determines the nature of the expected matches
    • DECLARATIONS: will search declarations matching with the corresponding element. In case the element is a method, declarations of matching methods in sub-types will also be found, allowing to find declarations of abstract methods, etc. Some additional flags may be specified while searching declaration:
      • IGNORE_DECLARING_TYPE: declaring type will be ignored during the search.
        For example using following test case:
                         class A { A method() { return null; } }
                         class B extends A { B method() { return null; } }
                         class C { A method() { return null; } }
        				
        search for method declaration with this flag will return 2 matches: in A and in C
      • IGNORE_RETURN_TYPE: return type will be ignored during the search.
        Using same example, search for method declaration with this flag will return 2 matches: in A and in B.
      Note that these two flags may be combined and both declaring and return types can be ignored during the search. Then, using same example, search for method declaration with these 2 flags will return 3 matches: in A, in B and in C
    • REFERENCES: will search references to the given element.
    • ALL_OCCURRENCES: will search for either declarations or references as specified above.
    • All other fine grain constants defined in the limitTo category of the IJavaSearchConstants are also accepted nature:
      Fine grain constant Meaning
      FIELD_DECLARATION_TYPE_REFERENCE Return only type references used as the type of a field declaration.
      LOCAL_VARIABLE_DECLARATION_TYPE_REFERENCE Return only type references used as the type of a local variable declaration.
      PARAMETER_DECLARATION_TYPE_REFERENCE Return only type references used as the type of a method parameter declaration.
      SUPERTYPE_TYPE_REFERENCE Return only type references used as a super type or as a super interface.
      THROWS_CLAUSE_TYPE_REFERENCE Return only type references used in a throws clause.
      CAST_TYPE_REFERENCE Return only type references used in a cast expression.
      CATCH_TYPE_REFERENCE Return only type references used in a catch header.
      CLASS_INSTANCE_CREATION_TYPE_REFERENCE Return only type references used in class instance creation.
      RETURN_TYPE_REFERENCE Return only type references used as a method return type.
      IMPORT_DECLARATION_TYPE_REFERENCE Return only type references used in an import declaration.
      ANNOTATION_TYPE_REFERENCE Return only type references used as an annotation.
      TYPE_ARGUMENT_TYPE_REFERENCE Return only type references used as a type argument in a parameterized type or a parameterized method.
      TYPE_VARIABLE_BOUND_TYPE_REFERENCE Return only type references used as a type variable bound.
      WILDCARD_BOUND_TYPE_REFERENCE Return only type references used as a wildcard bound.
      INSTANCEOF_TYPE_REFERENCE Return only type references used as a type of an instanceof expression.
      SUPER_REFERENCE Return only super field accesses or super method invocations (e.g. using the super qualifier).
      QUALIFIED_REFERENCE Return only qualified field accesses or qualified method invocations.
      THIS_REFERENCE Return only primary field accesses or primary method invocations (e.g. using the this qualifier).
      IMPLICIT_THIS_REFERENCE Return only field accesses or method invocations without any qualification.
      METHOD_REFERENCE_EXPRESSION Return only method reference expressions (e.g. A :: foo).
Returns:a search pattern for a Java element or null if the given element is ill-formed
/** * Returns a search pattern based on a given Java element. * The pattern is used to trigger the appropriate search. * <br> * Note that for generic searches, the returned pattern consider {@link #R_ERASURE_MATCH} matches. * If other kind of generic matches (i.e. {@link #R_EXACT_MATCH} or {@link #R_EQUIVALENT_MATCH}) * are expected, {@link #createPattern(IJavaElement, int, int)} method need to be used instead with * the explicit match rule specified. * <br> * The pattern can be parameterized as follows: * * @param element the Java element the search pattern is based on * @param limitTo determines the nature of the expected matches * <ul> * <li>{@link IJavaSearchConstants#DECLARATIONS DECLARATIONS}: will search declarations matching * with the corresponding element. In case the element is a method, declarations of matching * methods in sub-types will also be found, allowing to find declarations of abstract methods, etc. * Some additional flags may be specified while searching declaration: * <ul> * <li>{@link IJavaSearchConstants#IGNORE_DECLARING_TYPE IGNORE_DECLARING_TYPE}: declaring type will be ignored * during the search.<br> * For example using following test case: * <pre> * class A { A method() { return null; } } * class B extends A { B method() { return null; } } * class C { A method() { return null; } } * </pre> * search for <code>method</code> declaration with this flag * will return 2 matches: in A and in C * </li> * <li>{@link IJavaSearchConstants#IGNORE_RETURN_TYPE IGNORE_RETURN_TYPE}: return type will be ignored * during the search.<br> * Using same example, search for <code>method</code> declaration with this flag * will return 2 matches: in A and in B. * </li> * </ul> * Note that these two flags may be combined and both declaring and return types can be ignored * during the search. Then, using same example, search for <code>method</code> declaration * with these 2 flags will return 3 matches: in A, in B and in C * </li> * <li>{@link IJavaSearchConstants#REFERENCES REFERENCES}: will search references to the given element.</li> * <li>{@link IJavaSearchConstants#ALL_OCCURRENCES ALL_OCCURRENCES}: will search for either declarations or * references as specified above. * </li> * <li>All other fine grain constants defined in the <b>limitTo</b> category * of the {@link IJavaSearchConstants} are also accepted nature: * <table> * <tr> * <th>Fine grain constant * <th>Meaning * <tr> * <td>{@link IJavaSearchConstants#FIELD_DECLARATION_TYPE_REFERENCE FIELD_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used as the type of a field declaration. * <tr> * <td>{@link IJavaSearchConstants#LOCAL_VARIABLE_DECLARATION_TYPE_REFERENCE LOCAL_VARIABLE_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used as the type of a local variable declaration. * <tr> * <td>{@link IJavaSearchConstants#PARAMETER_DECLARATION_TYPE_REFERENCE PARAMETER_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used as the type of a method parameter declaration. * <tr> * <td>{@link IJavaSearchConstants#SUPERTYPE_TYPE_REFERENCE SUPERTYPE_TYPE_REFERENCE} * <td>Return only type references used as a super type or as a super interface. * <tr> * <td>{@link IJavaSearchConstants#THROWS_CLAUSE_TYPE_REFERENCE THROWS_CLAUSE_TYPE_REFERENCE} * <td>Return only type references used in a throws clause. * <tr> * <td>{@link IJavaSearchConstants#CAST_TYPE_REFERENCE CAST_TYPE_REFERENCE} * <td>Return only type references used in a cast expression. * <tr> * <td>{@link IJavaSearchConstants#CATCH_TYPE_REFERENCE CATCH_TYPE_REFERENCE} * <td>Return only type references used in a catch header. * <tr> * <td>{@link IJavaSearchConstants#CLASS_INSTANCE_CREATION_TYPE_REFERENCE CLASS_INSTANCE_CREATION_TYPE_REFERENCE} * <td>Return only type references used in class instance creation. * <tr> * <td>{@link IJavaSearchConstants#RETURN_TYPE_REFERENCE RETURN_TYPE_REFERENCE} * <td>Return only type references used as a method return type. * <tr> * <td>{@link IJavaSearchConstants#IMPORT_DECLARATION_TYPE_REFERENCE IMPORT_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used in an import declaration. * <tr> * <td>{@link IJavaSearchConstants#ANNOTATION_TYPE_REFERENCE ANNOTATION_TYPE_REFERENCE} * <td>Return only type references used as an annotation. * <tr> * <td>{@link IJavaSearchConstants#TYPE_ARGUMENT_TYPE_REFERENCE TYPE_ARGUMENT_TYPE_REFERENCE} * <td>Return only type references used as a type argument in a parameterized type or a parameterized method. * <tr> * <td>{@link IJavaSearchConstants#TYPE_VARIABLE_BOUND_TYPE_REFERENCE TYPE_VARIABLE_BOUND_TYPE_REFERENCE} * <td>Return only type references used as a type variable bound. * <tr> * <td>{@link IJavaSearchConstants#WILDCARD_BOUND_TYPE_REFERENCE WILDCARD_BOUND_TYPE_REFERENCE} * <td>Return only type references used as a wildcard bound. * <tr> * <td>{@link IJavaSearchConstants#INSTANCEOF_TYPE_REFERENCE INSTANCEOF_TYPE_REFERENCE} * <td>Return only type references used as a type of an <code>instanceof</code> expression. * <tr> * <td>{@link IJavaSearchConstants#SUPER_REFERENCE SUPER_REFERENCE} * <td>Return only super field accesses or super method invocations (e.g. using the <code>super</code> qualifier). * <tr> * <td>{@link IJavaSearchConstants#QUALIFIED_REFERENCE QUALIFIED_REFERENCE} * <td>Return only qualified field accesses or qualified method invocations. * <tr> * <td>{@link IJavaSearchConstants#THIS_REFERENCE THIS_REFERENCE} * <td>Return only primary field accesses or primary method invocations (e.g. using the <code>this</code> qualifier). * <tr> * <td>{@link IJavaSearchConstants#IMPLICIT_THIS_REFERENCE IMPLICIT_THIS_REFERENCE} * <td>Return only field accesses or method invocations without any qualification. * <tr> * <td>{@link IJavaSearchConstants#METHOD_REFERENCE_EXPRESSION METHOD_REFERENCE_EXPRESSION} * <td>Return only method reference expressions (e.g. <code>A :: foo</code>). * </table> * </li> * </ul> * @return a search pattern for a Java element or <code>null</code> if the given element is ill-formed */
public static SearchPattern createPattern(IJavaElement element, int limitTo) { return createPattern(element, limitTo, R_EXACT_MATCH | R_CASE_SENSITIVE | R_ERASURE_MATCH); }
Returns a search pattern based on a given Java element. The pattern is used to trigger the appropriate search, and can be parameterized as follows:
Params:
Returns:a search pattern for a Java element or null if the given element is ill-formed
Since:3.1
/** * Returns a search pattern based on a given Java element. * The pattern is used to trigger the appropriate search, and can be parameterized as follows: * * @param element the Java element the search pattern is based on * @param limitTo determines the nature of the expected matches * <ul> * <li>{@link IJavaSearchConstants#DECLARATIONS DECLARATIONS}: will search declarations matching * with the corresponding element. In case the element is a method, declarations of matching * methods in sub-types will also be found, allowing to find declarations of abstract methods, etc. * Some additional flags may be specified while searching declaration: * <ul> * <li>{@link IJavaSearchConstants#IGNORE_DECLARING_TYPE IGNORE_DECLARING_TYPE}: declaring type will be ignored * during the search.<br> * For example using following test case: * <pre> * class A { A method() { return null; } } * class B extends A { B method() { return null; } } * class C { A method() { return null; } } * </pre> * search for <code>method</code> declaration with this flag * will return 2 matches: in A and in C * </li> * <li>{@link IJavaSearchConstants#IGNORE_RETURN_TYPE IGNORE_RETURN_TYPE}: return type will be ignored * during the search.<br> * Using same example, search for <code>method</code> declaration with this flag * will return 2 matches: in A and in B. * </li> * </ul> * Note that these two flags may be combined and both declaring and return types can be ignored * during the search. Then, using same example, search for <code>method</code> declaration * with these 2 flags will return 3 matches: in A, in B and in C * </li> * <li>{@link IJavaSearchConstants#REFERENCES REFERENCES}: will search references to the given element.</li> * <li>{@link IJavaSearchConstants#ALL_OCCURRENCES ALL_OCCURRENCES}: will search for either declarations or * references as specified above. * </li> * <li>All other fine grain constants defined in the <b>limitTo</b> category * of the {@link IJavaSearchConstants} are also accepted nature: * <table> * <tr> * <th>Fine grain constant * <th>Meaning * <tr> * <td>{@link IJavaSearchConstants#FIELD_DECLARATION_TYPE_REFERENCE FIELD_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used as the type of a field declaration. * <tr> * <td>{@link IJavaSearchConstants#LOCAL_VARIABLE_DECLARATION_TYPE_REFERENCE LOCAL_VARIABLE_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used as the type of a local variable declaration. * <tr> * <td>{@link IJavaSearchConstants#PARAMETER_DECLARATION_TYPE_REFERENCE PARAMETER_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used as the type of a method parameter declaration. * <tr> * <td>{@link IJavaSearchConstants#SUPERTYPE_TYPE_REFERENCE SUPERTYPE_TYPE_REFERENCE} * <td>Return only type references used as a super type or as a super interface. * <tr> * <td>{@link IJavaSearchConstants#THROWS_CLAUSE_TYPE_REFERENCE THROWS_CLAUSE_TYPE_REFERENCE} * <td>Return only type references used in a throws clause. * <tr> * <td>{@link IJavaSearchConstants#CAST_TYPE_REFERENCE CAST_TYPE_REFERENCE} * <td>Return only type references used in a cast expression. * <tr> * <td>{@link IJavaSearchConstants#CATCH_TYPE_REFERENCE CATCH_TYPE_REFERENCE} * <td>Return only type references used in a catch header. * <tr> * <td>{@link IJavaSearchConstants#CLASS_INSTANCE_CREATION_TYPE_REFERENCE CLASS_INSTANCE_CREATION_TYPE_REFERENCE} * <td>Return only type references used in class instance creation. * <tr> * <td>{@link IJavaSearchConstants#RETURN_TYPE_REFERENCE RETURN_TYPE_REFERENCE} * <td>Return only type references used as a method return type. * <tr> * <td>{@link IJavaSearchConstants#IMPORT_DECLARATION_TYPE_REFERENCE IMPORT_DECLARATION_TYPE_REFERENCE} * <td>Return only type references used in an import declaration. * <tr> * <td>{@link IJavaSearchConstants#ANNOTATION_TYPE_REFERENCE ANNOTATION_TYPE_REFERENCE} * <td>Return only type references used as an annotation. * <tr> * <td>{@link IJavaSearchConstants#TYPE_ARGUMENT_TYPE_REFERENCE TYPE_ARGUMENT_TYPE_REFERENCE} * <td>Return only type references used as a type argument in a parameterized type or a parameterized method. * <tr> * <td>{@link IJavaSearchConstants#TYPE_VARIABLE_BOUND_TYPE_REFERENCE TYPE_VARIABLE_BOUND_TYPE_REFERENCE} * <td>Return only type references used as a type variable bound. * <tr> * <td>{@link IJavaSearchConstants#WILDCARD_BOUND_TYPE_REFERENCE WILDCARD_BOUND_TYPE_REFERENCE} * <td>Return only type references used as a wildcard bound. * <tr> * <td>{@link IJavaSearchConstants#INSTANCEOF_TYPE_REFERENCE INSTANCEOF_TYPE_REFERENCE} * <td>Return only type references used as a type of an <code>instanceof</code> expression. * <tr> * <td>{@link IJavaSearchConstants#SUPER_REFERENCE SUPER_REFERENCE} * <td>Return only super field accesses or super method invocations (e.g. using the <code>super</code> qualifier). * <tr> * <td>{@link IJavaSearchConstants#QUALIFIED_REFERENCE QUALIFIED_REFERENCE} * <td>Return only qualified field accesses or qualified method invocations. * <tr> * <td>{@link IJavaSearchConstants#THIS_REFERENCE THIS_REFERENCE} * <td>Return only primary field accesses or primary method invocations (e.g. using the <code>this</code> qualifier). * <tr> * <td>{@link IJavaSearchConstants#IMPLICIT_THIS_REFERENCE IMPLICIT_THIS_REFERENCE} * <td>Return only field accesses or method invocations without any qualification. * <tr> * <td>{@link IJavaSearchConstants#METHOD_REFERENCE_EXPRESSION METHOD_REFERENCE_EXPRESSION} * <td>Return only method reference expressions (e.g. <code>A :: foo</code>). * </table> * </li> * </ul> * @param matchRule one of the following match rules: * <ul> * <li>{@link #R_EXACT_MATCH}</li> * <li>{@link #R_PREFIX_MATCH}</li> * <li>{@link #R_PATTERN_MATCH}</li> * <li>{@link #R_CAMELCASE_MATCH}</li> * <li>{@link #R_CAMELCASE_SAME_PART_COUNT_MATCH}</li> * </ul> * , which may be also combined with one of the following flags: * <ul> * <li>{@link #R_CASE_SENSITIVE}</li> * <li>{@link #R_ERASURE_MATCH}</li> * <li>{@link #R_EQUIVALENT_MATCH}</li> * </ul> * For example, * <ul> * <li>{@link #R_EXACT_MATCH} | {@link #R_CASE_SENSITIVE}: if an exact * and case sensitive match is requested,</li> * <li>{@link #R_PREFIX_MATCH} if a case insensitive prefix match is requested</li> * <li>{@link #R_EXACT_MATCH} | {@link #R_ERASURE_MATCH}: if a case * insensitive and erasure match is requested.</li> * </ul> * Note that {@link #R_ERASURE_MATCH} or {@link #R_EQUIVALENT_MATCH} has no effect * on non-generic types/methods search. * <p> * Note also that default behavior for generic types/methods search is to find exact matches. * @return a search pattern for a Java element or <code>null</code> if the given element is ill-formed * @since 3.1 */
public static SearchPattern createPattern(IJavaElement element, int limitTo, int matchRule) { SearchPattern searchPattern = null; int lastDot; boolean ignoreDeclaringType = false; boolean ignoreReturnType = false; int maskedLimitTo = limitTo & ~(IJavaSearchConstants.IGNORE_DECLARING_TYPE+IJavaSearchConstants.IGNORE_RETURN_TYPE); if (maskedLimitTo == IJavaSearchConstants.DECLARATIONS || maskedLimitTo == IJavaSearchConstants.ALL_OCCURRENCES) { ignoreDeclaringType = (limitTo & IJavaSearchConstants.IGNORE_DECLARING_TYPE) != 0; ignoreReturnType = (limitTo & IJavaSearchConstants.IGNORE_RETURN_TYPE) != 0; } if ((matchRule = validateMatchRule(null, matchRule)) == -1) { return null; } char[] declaringSimpleName = null; char[] declaringQualification = null; switch (element.getElementType()) { case IJavaElement.FIELD : IField field = (IField) element; if (!ignoreDeclaringType) { IType declaringClass = field.getDeclaringType(); declaringSimpleName = declaringClass.getElementName().toCharArray(); declaringQualification = declaringClass.getPackageFragment().getElementName().toCharArray(); char[][] enclosingNames = enclosingTypeNames(declaringClass); if (enclosingNames.length > 0) { declaringQualification = CharOperation.concat(declaringQualification, CharOperation.concatWith(enclosingNames, '.'), '.'); } } char[] name = field.getElementName().toCharArray(); char[] typeSimpleName = null; char[] typeQualification = null; String typeSignature = null; if (!ignoreReturnType) { try { typeSignature = field.getTypeSignature(); char[] signature = typeSignature.toCharArray(); char[] typeErasure = Signature.toCharArray(Signature.getTypeErasure(signature)); CharOperation.replace(typeErasure, '$', '.'); if ((lastDot = CharOperation.lastIndexOf('.', typeErasure)) == -1) { typeSimpleName = typeErasure; } else { typeSimpleName = CharOperation.subarray(typeErasure, lastDot + 1, typeErasure.length); typeQualification = CharOperation.subarray(typeErasure, 0, lastDot); if (!field.isBinary()) { // prefix with a '*' as the full qualification could be bigger (because of an import) typeQualification = CharOperation.concat(IIndexConstants.ONE_STAR, typeQualification); } } } catch (JavaModelException e) { return null; } } // Create field pattern searchPattern = new FieldPattern( name, declaringQualification, declaringSimpleName, typeQualification, typeSimpleName, typeSignature, limitTo, matchRule); break; case IJavaElement.IMPORT_DECLARATION : String elementName = element.getElementName(); lastDot = elementName.lastIndexOf('.'); if (lastDot == -1) return null; // invalid import declaration IImportDeclaration importDecl = (IImportDeclaration)element; if (importDecl.isOnDemand()) { searchPattern = createPackagePattern(elementName.substring(0, lastDot), maskedLimitTo, matchRule); } else { searchPattern = createTypePattern( elementName.substring(lastDot+1).toCharArray(), elementName.substring(0, lastDot).toCharArray(), null, null, null, maskedLimitTo, matchRule); } break; case IJavaElement.LOCAL_VARIABLE : LocalVariable localVar = (LocalVariable) element; searchPattern = new LocalVariablePattern(localVar, limitTo, matchRule); break; case IJavaElement.TYPE_PARAMETER: ITypeParameter typeParam = (ITypeParameter) element; boolean findParamDeclarations = true; boolean findParamReferences = true; switch (maskedLimitTo) { case IJavaSearchConstants.DECLARATIONS : findParamReferences = false; break; case IJavaSearchConstants.REFERENCES : findParamDeclarations = false; break; } searchPattern = new TypeParameterPattern( findParamDeclarations, findParamReferences, typeParam, matchRule); break; case IJavaElement.METHOD : IMethod method = (IMethod) element; boolean isConstructor; try { isConstructor = method.isConstructor(); } catch (JavaModelException e) { return null; } IType declaringClass = method.getDeclaringType(); if (ignoreDeclaringType) { if (isConstructor) declaringSimpleName = declaringClass.getElementName().toCharArray(); } else { declaringSimpleName = declaringClass.getElementName().toCharArray(); declaringQualification = declaringClass.getPackageFragment().getElementName().toCharArray(); char[][] enclosingNames = enclosingTypeNames(declaringClass); if (enclosingNames.length > 0) { declaringQualification = CharOperation.concat(declaringQualification, CharOperation.concatWith(enclosingNames, '.'), '.'); } } char[] selector = method.getElementName().toCharArray(); char[] returnSimpleName = null; char[] returnQualification = null; String returnSignature = null; if (!ignoreReturnType) { try { returnSignature = method.getReturnType(); char[] signature = returnSignature.toCharArray(); char[] returnErasure = Signature.toCharArray(Signature.getTypeErasure(signature)); CharOperation.replace(returnErasure, '$', '.'); if ((lastDot = CharOperation.lastIndexOf('.', returnErasure)) == -1) { returnSimpleName = returnErasure; } else { returnSimpleName = CharOperation.subarray(returnErasure, lastDot + 1, returnErasure.length); returnQualification = CharOperation.subarray(returnErasure, 0, lastDot); if (!method.isBinary()) { // prefix with a '*' as the full qualification could be bigger (because of an import) CharOperation.concat(IIndexConstants.ONE_STAR, returnQualification); } } } catch (JavaModelException e) { return null; } } String[] parameterTypes = method.getParameterTypes(); int paramCount = parameterTypes.length; char[][] parameterSimpleNames = new char[paramCount][]; char[][] parameterQualifications = new char[paramCount][]; String[] parameterSignatures = new String[paramCount]; for (int i = 0; i < paramCount; i++) { parameterSignatures[i] = parameterTypes[i]; char[] signature = parameterSignatures[i].toCharArray(); char[] paramErasure = Signature.toCharArray(Signature.getTypeErasure(signature)); CharOperation.replace(paramErasure, '$', '.'); if ((lastDot = CharOperation.lastIndexOf('.', paramErasure)) == -1) { parameterSimpleNames[i] = paramErasure; parameterQualifications[i] = null; } else { parameterSimpleNames[i] = CharOperation.subarray(paramErasure, lastDot + 1, paramErasure.length); parameterQualifications[i] = CharOperation.subarray(paramErasure, 0, lastDot); if (!method.isBinary()) { // prefix with a '*' as the full qualification could be bigger (because of an import) CharOperation.concat(IIndexConstants.ONE_STAR, parameterQualifications[i]); } } } // Create method/constructor pattern if (isConstructor) { searchPattern = new ConstructorPattern( declaringSimpleName, declaringQualification, parameterQualifications, parameterSimpleNames, parameterSignatures, method, limitTo, matchRule); } else { searchPattern = new MethodPattern( selector, declaringQualification, declaringSimpleName, returnQualification, returnSimpleName, returnSignature, parameterQualifications, parameterSimpleNames, parameterSignatures, method, limitTo, matchRule); } break; case IJavaElement.TYPE : IType type = (IType)element; searchPattern = createTypePattern( type.getElementName().toCharArray(), type.getPackageFragment().getElementName().toCharArray(), ignoreDeclaringType ? null : enclosingTypeNames(type), null, type, maskedLimitTo, matchRule); break; case IJavaElement.PACKAGE_DECLARATION : case IJavaElement.PACKAGE_FRAGMENT : searchPattern = createPackagePattern(element.getElementName(), maskedLimitTo, matchRule); break; case IJavaElement.JAVA_MODULE : searchPattern = createModulePattern(element.getElementName(), maskedLimitTo, matchRule); break; } if (searchPattern != null) MatchLocator.setFocus(searchPattern, element); return searchPattern; } private static SearchPattern createTypePattern(char[] simpleName, char[] packageName, char[][] enclosingTypeNames, String typeSignature, IType type, int limitTo, int matchRule) { switch (limitTo) { case IJavaSearchConstants.DECLARATIONS : return new TypeDeclarationPattern( packageName, enclosingTypeNames, simpleName, IIndexConstants.TYPE_SUFFIX, matchRule); case IJavaSearchConstants.REFERENCES : if (type != null) { return new TypeReferencePattern( CharOperation.concatWith(packageName, enclosingTypeNames, '.'), simpleName, type, matchRule); } return new TypeReferencePattern( CharOperation.concatWith(packageName, enclosingTypeNames, '.'), simpleName, typeSignature, matchRule); case IJavaSearchConstants.IMPLEMENTORS : return new SuperTypeReferencePattern( CharOperation.concatWith(packageName, enclosingTypeNames, '.'), simpleName, SuperTypeReferencePattern.ONLY_SUPER_INTERFACES, matchRule); case IJavaSearchConstants.ALL_OCCURRENCES : return new OrPattern( new TypeDeclarationPattern( packageName, enclosingTypeNames, simpleName, IIndexConstants.TYPE_SUFFIX, matchRule), (type != null) ? new TypeReferencePattern( CharOperation.concatWith(packageName, enclosingTypeNames, '.'), simpleName, type, matchRule) : new TypeReferencePattern( CharOperation.concatWith(packageName, enclosingTypeNames, '.'), simpleName, typeSignature, matchRule) ); default: if (type != null) { return new TypeReferencePattern( CharOperation.concatWith(packageName, enclosingTypeNames, '.'), simpleName, type, limitTo, matchRule); } } return null; } private static SearchPattern createTypePattern(String patternString, int limitTo, int matchRule, char indexSuffix) { String[] arr = patternString.split(String.valueOf(IIndexConstants.SEPARATOR)); String moduleName = null; if (arr.length == 2) { moduleName = arr[0]; patternString = arr[1]; } char[] patModName = moduleName != null ? moduleName.toCharArray() : null; // use 1.7 as the source level as there are more valid tokens in 1.7 mode // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376673 Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_7/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/); scanner.setSource(patternString.toCharArray()); String type = null; int token; try { token = scanner.getNextToken(); } catch (InvalidInputException e) { return null; } int argCount = 0; while (token != TerminalTokens.TokenNameEOF) { if (argCount == 0) { switch (token) { case TerminalTokens.TokenNameWHITESPACE: break; case TerminalTokens.TokenNameLESS: argCount++; // $FALL-THROUGH$ - fall through default case to add token to type default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search]) if (type == null) type = scanner.getCurrentTokenString(); else type += scanner.getCurrentTokenString(); } } else { switch (token) { case TerminalTokens.TokenNameGREATER: case TerminalTokens.TokenNameRIGHT_SHIFT: case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT: argCount--; break; case TerminalTokens.TokenNameLESS: argCount++; break; } if (type == null) return null; // invalid syntax type += scanner.getCurrentTokenString(); } try { token = scanner.getNextToken(); } catch (InvalidInputException e) { return null; } } if (type == null) return null; String typeSignature = null; char[] qualificationChars = null, typeChars = null; // get type part and signature char[] typePart = null; try { typeSignature = Signature.createTypeSignature(type, false); if (typeSignature.indexOf(Signature.C_GENERIC_START) < 0) { typePart = type.toCharArray(); } else { typePart = Signature.toCharArray(Signature.getTypeErasure(typeSignature.toCharArray())); } } catch (IllegalArgumentException iae) { // string is not a valid type syntax return null; } // get qualification name int lastDotPosition = CharOperation.lastIndexOf('.', typePart); if (lastDotPosition >= 0) { qualificationChars = CharOperation.subarray(typePart, 0, lastDotPosition); if (qualificationChars.length == 1 && qualificationChars[0] == '*') qualificationChars = null; typeChars = CharOperation.subarray(typePart, lastDotPosition+1, typePart.length); } else { typeChars = typePart; } if (typeChars.length == 1 && typeChars[0] == '*') { typeChars = null; } boolean modGraph = false; switch (limitTo) { case IJavaSearchConstants.MODULE_GRAPH : modGraph = true; //$FALL-THROUGH$ case IJavaSearchConstants.DECLARATIONS : // cannot search for explicit member types TypeDeclarationPattern typeDeclarationPattern = new QualifiedTypeDeclarationPattern(patModName, qualificationChars, typeChars, indexSuffix, matchRule); typeDeclarationPattern.moduleGraph = modGraph; return typeDeclarationPattern; case IJavaSearchConstants.REFERENCES : return new TypeReferencePattern(qualificationChars, typeChars, typeSignature, indexSuffix, matchRule); case IJavaSearchConstants.IMPLEMENTORS : return new SuperTypeReferencePattern(qualificationChars, typeChars, SuperTypeReferencePattern.ONLY_SUPER_INTERFACES, indexSuffix, matchRule); case IJavaSearchConstants.ALL_OCCURRENCES : return new OrPattern( new QualifiedTypeDeclarationPattern(patModName, qualificationChars, typeChars, indexSuffix, matchRule),// cannot search for explicit member types new TypeReferencePattern(qualificationChars, typeChars, typeSignature, indexSuffix, matchRule)); default: return new TypeReferencePattern(qualificationChars, typeChars, typeSignature, limitTo, indexSuffix, matchRule); } }
Returns the enclosing type names of the given type.
/** * Returns the enclosing type names of the given type. */
private static char[][] enclosingTypeNames(IType type) { IJavaElement parent = type.getParent(); switch (parent.getElementType()) { case IJavaElement.CLASS_FILE: if (parent instanceof IModularClassFile) return null; // For a binary type, the parent is not the enclosing type, but the declaring type is. // (see bug 20532 Declaration of member binary type not found) IType declaringType = type.getDeclaringType(); if (declaringType == null) return CharOperation.NO_CHAR_CHAR; return CharOperation.arrayConcat( enclosingTypeNames(declaringType), declaringType.getElementName().toCharArray()); case IJavaElement.COMPILATION_UNIT: return CharOperation.NO_CHAR_CHAR; case IJavaElement.FIELD: case IJavaElement.INITIALIZER: case IJavaElement.METHOD: IType declaringClass = ((IMember) parent).getDeclaringType(); return CharOperation.arrayConcat( enclosingTypeNames(declaringClass), new char[][] {declaringClass.getElementName().toCharArray(), IIndexConstants.ONE_STAR}); case IJavaElement.TYPE: return CharOperation.arrayConcat( enclosingTypeNames((IType)parent), parent.getElementName().toCharArray()); default: return null; } }
Decode the given index key in this pattern. The decoded index key is used by matchesDecodedKey(SearchPattern) to find out if the corresponding index entry should be considered.

This method should be re-implemented in subclasses that need to decode an index key.

Params:
  • key – the given index key
/** * Decode the given index key in this pattern. The decoded index key is used by * {@link #matchesDecodedKey(SearchPattern)} to find out if the corresponding index entry * should be considered. * <p> * This method should be re-implemented in subclasses that need to decode an index key. * </p> * * @param key the given index key */
public void decodeIndexKey(char[] key) { // called from findIndexMatches(), override as necessary }
Query a given index for matching entries. Assumes the sender has opened the index and will close when finished.
@noreferenceThis method is not intended to be referenced by clients.
@nooverrideThis method is not intended to be re-implemented or extended by clients.
/** * Query a given index for matching entries. Assumes the sender has opened the index and will close when finished. * * @noreference This method is not intended to be referenced by clients. * @nooverride This method is not intended to be re-implemented or extended by clients. */
public void findIndexMatches(Index index, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor monitor) throws IOException { if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException(); try { index.startQuery(); SearchPattern pattern = currentPattern(); EntryResult[] entries = pattern.queryIn(index); if (entries == null) return; SearchPattern decodedResult = pattern.getBlankPattern(); String containerPath = index.containerPath; char separator = index.separator; for (int i = 0, l = entries.length; i < l; i++) { if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException(); EntryResult entry = entries[i]; decodedResult.decodeIndexKey(entry.getWord()); if (pattern.matchesDecodedKey(decodedResult)) { // TODO (kent) some clients may not need the document names String[] names = entry.getDocumentNames(index); for (int j = 0, n = names.length; j < n; j++) acceptMatch(names[j], containerPath, separator, decodedResult, requestor, participant, scope, monitor); } } } finally { index.stopQuery(); } }
Returns a blank pattern that can be used as a record to decode an index key.

Implementors of this method should return a new search pattern that is going to be used to decode index keys.

See Also:
Returns:a new blank pattern
/** * Returns a blank pattern that can be used as a record to decode an index key. * <p> * Implementors of this method should return a new search pattern that is going to be used * to decode index keys. * </p> * * @return a new blank pattern * @see #decodeIndexKey(char[]) */
public abstract SearchPattern getBlankPattern();
Returns a key to find in relevant index categories, if null then all index entries are matched. The key will be matched according to some match rule. These potential matches will be further narrowed by the match locator, but precise match locating can be expensive, and index query should be as accurate as possible so as to eliminate obvious false hits.

This method should be re-implemented in subclasses that need to narrow down the index query.

Returns:an index key from this pattern, or null if all index entries are matched.
/** * Returns a key to find in relevant index categories, if null then all index entries are matched. * The key will be matched according to some match rule. These potential matches * will be further narrowed by the match locator, but precise match locating can be expensive, * and index query should be as accurate as possible so as to eliminate obvious false hits. * <p> * This method should be re-implemented in subclasses that need to narrow down the * index query. * </p> * * @return an index key from this pattern, or <code>null</code> if all index entries are matched. */
public char[] getIndexKey() { return null; // called from queryIn(), override as necessary }
Returns an array of index categories to consider for this index query. These potential matches will be further narrowed by the match locator, but precise match locating can be expensive, and index query should be as accurate as possible so as to eliminate obvious false hits.

This method should be re-implemented in subclasses that need to narrow down the index query.

Returns:an array of index categories
/** * Returns an array of index categories to consider for this index query. * These potential matches will be further narrowed by the match locator, but precise * match locating can be expensive, and index query should be as accurate as possible * so as to eliminate obvious false hits. * <p> * This method should be re-implemented in subclasses that need to narrow down the * index query. * </p> * * @return an array of index categories */
public char[][] getIndexCategories() { return CharOperation.NO_CHAR_CHAR; // called from queryIn(), override as necessary }
Returns the rule to apply for matching index keys. Can be exact match, prefix match, pattern match or regexp match. Rule can also be combined with a case sensitivity flag.
Returns:one of R_EXACT_MATCH, R_PREFIX_MATCH, R_PATTERN_MATCH, R_REGEXP_MATCH combined with R_CASE_SENSITIVE, e.g. R_EXACT_MATCH | R_CASE_SENSITIVE if an exact and case sensitive match is requested, or R_PREFIX_MATCH if a prefix non case sensitive match is requested.
/** * Returns the rule to apply for matching index keys. Can be exact match, prefix match, pattern match or regexp match. * Rule can also be combined with a case sensitivity flag. * * @return one of R_EXACT_MATCH, R_PREFIX_MATCH, R_PATTERN_MATCH, R_REGEXP_MATCH combined with R_CASE_SENSITIVE, * e.g. R_EXACT_MATCH | R_CASE_SENSITIVE if an exact and case sensitive match is requested, * or R_PREFIX_MATCH if a prefix non case sensitive match is requested. */
public final int getMatchRule() { return this.matchRule; }
@noreferenceThis method is not intended to be referenced by clients.
@nooverrideThis method is not intended to be re-implemented or extended by clients.
/** * @noreference This method is not intended to be referenced by clients. * @nooverride This method is not intended to be re-implemented or extended by clients. */
public boolean isPolymorphicSearch() { return false; }
Returns whether this pattern matches the given pattern (representing a decoded index key).

This method should be re-implemented in subclasses that need to narrow down the index query.

Params:
  • decodedPattern – a pattern representing a decoded index key
Returns:whether this pattern matches the given pattern
/** * Returns whether this pattern matches the given pattern (representing a decoded index key). * <p> * This method should be re-implemented in subclasses that need to narrow down the * index query. * </p> * * @param decodedPattern a pattern representing a decoded index key * @return whether this pattern matches the given pattern */
public boolean matchesDecodedKey(SearchPattern decodedPattern) { return true; // called from findIndexMatches(), override as necessary if index key is encoded }
Returns whether the given name matches the given pattern.

This method should be re-implemented in subclasses that need to define how a name matches a pattern.

Params:
  • pattern – the given pattern, or null to represent "*"
  • name – the given name
Returns:whether the given name matches the given pattern
/** * Returns whether the given name matches the given pattern. * <p> * This method should be re-implemented in subclasses that need to define how * a name matches a pattern. * </p> * * @param pattern the given pattern, or <code>null</code> to represent "*" * @param name the given name * @return whether the given name matches the given pattern */
public boolean matchesName(char[] pattern, char[] name) { if (pattern == null) return true; // null is as if it was "*" if (name != null) { boolean isCaseSensitive = (this.matchRule & R_CASE_SENSITIVE) != 0; int matchMode = this.matchRule & MODE_MASK; boolean emptyPattern = pattern.length == 0; if (emptyPattern && (this.matchRule & R_PREFIX_MATCH) != 0) return true; boolean sameLength = pattern.length == name.length; boolean canBePrefix = name.length >= pattern.length; boolean matchFirstChar = !isCaseSensitive || emptyPattern || (name.length > 0 && pattern[0] == name[0]); switch (matchMode) { case R_EXACT_MATCH : if (sameLength && matchFirstChar) { return CharOperation.equals(pattern, name, isCaseSensitive); } break; case R_PREFIX_MATCH : if (canBePrefix && matchFirstChar) { return CharOperation.prefixEquals(pattern, name, isCaseSensitive); } break; case R_PATTERN_MATCH : if (!isCaseSensitive) pattern = CharOperation.toLowerCase(pattern); return CharOperation.match(pattern, name, isCaseSensitive); case SearchPattern.R_CAMELCASE_MATCH: if (matchFirstChar && CharOperation.camelCaseMatch(pattern, name, false)) { return true; } // only test case insensitive as CamelCase already verified prefix case sensitive if (!isCaseSensitive && matchFirstChar && CharOperation.prefixEquals(pattern, name, false)) { return true; } break; case SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH: return matchFirstChar && CharOperation.camelCaseMatch(pattern, name, true); case R_REGEXP_MATCH : return Pattern.matches(new String(pattern), new String(name)); } } return false; }
Validate compatibility between given string pattern and match rule.
In certain circumstances described in the table below, the returned match rule is modified in order to provide a more efficient search pattern:
  1. when the R_REGEXP_MATCH flag is set, then the pattern is rejected as this kind of match is not supported yet and -1 is returned).
  2. when the string pattern has no pattern characters (e.g. '*' or '?') and the pattern match flag is set (i.e. the match rule has the R_PATTERN_MATCH flag), then the pattern match flag is reset.
    Reversely, when the string pattern has pattern characters and the pattern match flag is not set, then the pattern match flag is set.
  3. when the R_PATTERN_MATCH flag is set then, other R_PREFIX_MATCH, R_CAMELCASE_MATCH or R_CAMELCASE_SAME_PART_COUNT_MATCH flags are reset if they are tentatively combined.
  4. when the R_CAMELCASE_MATCH flag is set, then other R_PREFIX_MATCH or R_CAMELCASE_SAME_PART_COUNT_MATCH flags are reset if they are tentatively combined.
    Reversely, if the string pattern cannot be a camel case pattern (i.e. contains invalid Java identifier characters or does not have at least two uppercase characters - one for method camel case patterns), then the CamelCase match flag is replaced with a prefix match flag.
  5. when the R_CAMELCASE_SAME_PART_COUNT_MATCH flag is set, then (R_PREFIX_MATCH flag is reset if it's tentatively combined.
    Reversely, if the string pattern cannot be a camel case pattern (i.e. contains invalid Java identifier characters or does not have at least two uppercase characters - one for method camel case patterns), then the CamelCase part count match flag is reset.
Note: the rules are validated in the documented order. For example, it means that as soon as the string pattern contains one pattern character, the pattern match flag will be set and all other match flags reset: validation of rule 2) followed by rule 3)...

Params:
  • stringPattern – The string pattern
  • matchRule – The match rule
Returns:Optimized valid match rule or -1 if an incompatibility was detected.
Since:3.2
/** * Validate compatibility between given string pattern and match rule. *<br> * In certain circumstances described in the table below, the returned match rule is * modified in order to provide a more efficient search pattern: * <ol> * <li>when the {@link #R_REGEXP_MATCH} flag is set, then <b>the pattern is * rejected</b> as this kind of match is not supported yet and <code>-1</code> * is returned). * </li> * <li>when the string pattern has <u>no</u> pattern characters (e.g. '*' or '?') * and the pattern match flag is set (i.e. the match rule has the {@link #R_PATTERN_MATCH} * flag), then <b>the pattern match flag is reset</b>.<br> * Reversely, when the string pattern has pattern characters and the pattern * match flag is <u>not</u> set, then <b>the pattern match flag is set</b>. * </li> * <li>when the {@link #R_PATTERN_MATCH} flag is set then, <b>other * {@link #R_PREFIX_MATCH}, {@link #R_CAMELCASE_MATCH} or * {@link #R_CAMELCASE_SAME_PART_COUNT_MATCH} flags are reset</b> * if they are tentatively combined. * </li> * <li>when the {@link #R_CAMELCASE_MATCH} flag is set, then <b>other * {@link #R_PREFIX_MATCH} or {@link #R_CAMELCASE_SAME_PART_COUNT_MATCH} * flags are reset</b> if they are tentatively combined.<br> * Reversely, if the string pattern cannot be a camel case pattern (i.e. contains * invalid Java identifier characters or does not have at least two uppercase * characters - one for method camel case patterns), then <b>the CamelCase * match flag is replaced with a prefix match flag</b>. * </li> * <li>when the {@link #R_CAMELCASE_SAME_PART_COUNT_MATCH} flag is set, * then <b>({@link #R_PREFIX_MATCH} flag is reset</b> if it's tentatively * combined.<br> * Reversely, if the string pattern cannot be a camel case pattern (i.e. contains * invalid Java identifier characters or does not have at least two uppercase * characters - one for method camel case patterns), then <b>the CamelCase * part count match flag is reset</b>. * </li> * </ol> * <i>Note: the rules are validated in the documented order. For example, it means * that as soon as the string pattern contains one pattern character, the pattern * match flag will be set and all other match flags reset: validation of rule 2) * followed by rule 3)...</i> *<p> * * @param stringPattern The string pattern * @param matchRule The match rule * @return Optimized valid match rule or -1 if an incompatibility was detected. * @since 3.2 */
public static int validateMatchRule(String stringPattern, int matchRule) { // Verify Regexp match rule if ((matchRule & R_REGEXP_MATCH) != 0) { // regexp is not supported yet return -1; // need to enable for module declaration } // Verify Pattern match rule if (stringPattern != null) { int starIndex = stringPattern.indexOf('*'); int questionIndex = stringPattern.indexOf('?'); if (starIndex < 0 && questionIndex < 0) { // reset pattern match flag if any matchRule &= ~R_PATTERN_MATCH; } else { // force Pattern rule matchRule |= R_PATTERN_MATCH; } } if ((matchRule & R_PATTERN_MATCH) != 0) { // reset other incompatible flags matchRule &= ~R_CAMELCASE_MATCH; matchRule &= ~R_CAMELCASE_SAME_PART_COUNT_MATCH; matchRule &= ~R_PREFIX_MATCH; return matchRule; } // Verify Camel Case if ((matchRule & R_CAMELCASE_MATCH) != 0) { // reset other incompatible flags matchRule &= ~R_CAMELCASE_SAME_PART_COUNT_MATCH; matchRule &= ~R_PREFIX_MATCH; // validate camel case rule and modify it if not valid boolean validCamelCase = validateCamelCasePattern(stringPattern); if (!validCamelCase) { matchRule &= ~R_CAMELCASE_MATCH; matchRule |= R_PREFIX_MATCH; } return matchRule; } // Verify Camel Case with same count of parts if ((matchRule & R_CAMELCASE_SAME_PART_COUNT_MATCH) != 0) { // reset other incompatible flags matchRule &= ~R_PREFIX_MATCH; // validate camel case rule and modify it if not valid boolean validCamelCase = validateCamelCasePattern(stringPattern); if (!validCamelCase) { matchRule &= ~R_CAMELCASE_SAME_PART_COUNT_MATCH; } return matchRule; } // Return the validated match rule (modified if necessary) return matchRule; } // enabling special cases (read regular expressions) based on searchFor and limitTo private static int validateMatchRule(String stringPattern, int searchFor, int limitTo, int matchRule) { if (searchFor == IJavaSearchConstants.MODULE && limitTo == IJavaSearchConstants.DECLARATIONS && matchRule == SearchPattern.R_REGEXP_MATCH) return matchRule; return validateMatchRule(stringPattern, matchRule); } /* * Validate pattern for a camel case match rule * @return */ private static boolean validateCamelCasePattern(String stringPattern) { if (stringPattern == null) return true; // verify sting pattern validity int length = stringPattern.length(); boolean validCamelCase = true; boolean lowerCamelCase = false; int uppercase = 0; for (int i=0; i<length && validCamelCase; i++) { char ch = stringPattern.charAt(i); validCamelCase = i==0 ? ScannerHelper.isJavaIdentifierStart(ch) : ScannerHelper.isJavaIdentifierPart(ch); // at least one uppercase character is need in CamelCase pattern // (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=136313) if (ScannerHelper.isUpperCase(ch)) uppercase++; if (i==0) lowerCamelCase = uppercase == 0; } if (validCamelCase) { validCamelCase = lowerCamelCase ? uppercase > 0 : uppercase > 1 ; } return validCamelCase; }
@noreferenceThis method is not intended to be referenced by clients.
@nooverrideThis method is not intended to be re-implemented or extended by clients.
/** * @noreference This method is not intended to be referenced by clients. * @nooverride This method is not intended to be re-implemented or extended by clients. */
public EntryResult[] queryIn(Index index) throws IOException { return index.query(getIndexCategories(), getIndexKey(), getMatchRule()); }
See Also:
  • toString.toString()
/** * @see java.lang.Object#toString() */
@Override public String toString() { return "SearchPattern"; //$NON-NLS-1$ } }