blob: 14343d05730684aa71c67728ee41826023243037 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.util;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.internal.corext.util.TypeInfo.TypeInfoAdapter;
import org.eclipse.jdt.ui.dialogs.ITypeInfoFilterExtension;
import org.eclipse.jdt.internal.ui.util.StringMatcher;
public class TypeInfoFilter {
private static class PatternMatcher {
private String fPattern;
private int fMatchKind;
private StringMatcher fStringMatcher;
private static final char END_SYMBOL= '<';
private static final char ANY_STRING= '*';
private static final char BLANK= ' ';
public PatternMatcher(String pattern, boolean ignoreCase) {
this(pattern, SearchPattern.R_EXACT_MATCH | SearchPattern.R_PREFIX_MATCH |
SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CAMELCASE_MATCH);
}
public PatternMatcher(String pattern, int allowedModes) {
initializePatternAndMatchKind(pattern);
fMatchKind= fMatchKind & allowedModes;
if (fMatchKind == SearchPattern.R_PATTERN_MATCH) {
fStringMatcher= new StringMatcher(fPattern, true, false);
}
}
public String getPattern() {
return fPattern;
}
public int getMatchKind() {
return fMatchKind;
}
public boolean matches(String text) {
switch (fMatchKind) {
case SearchPattern.R_PATTERN_MATCH:
return fStringMatcher.match(text);
case SearchPattern.R_EXACT_MATCH:
return fPattern.equalsIgnoreCase(text);
case SearchPattern.R_CAMELCASE_MATCH:
if (SearchPattern.camelCaseMatch(fPattern, text)) {
return true;
}
// fall through to prefix match if camel case failed (bug 137244)
default:
return Strings.startsWithIgnoreCase(text, fPattern);
}
}
private void initializePatternAndMatchKind(String pattern) {
int length= pattern.length();
if (length == 0) {
fMatchKind= SearchPattern.R_EXACT_MATCH;
fPattern= pattern;
return;
}
char last= pattern.charAt(length - 1);
if (pattern.indexOf('*') != -1 || pattern.indexOf('?') != -1) {
fMatchKind= SearchPattern.R_PATTERN_MATCH;
switch (last) {
case END_SYMBOL:
fPattern= pattern.substring(0, length - 1);
break;
case BLANK:
fPattern= pattern.trim();
break;
case ANY_STRING:
fPattern= pattern;
break;
default:
fPattern= pattern + ANY_STRING;
}
return;
}
if (last == END_SYMBOL) {
fMatchKind= SearchPattern.R_EXACT_MATCH;
fPattern= pattern.substring(0, length - 1);
return;
}
if (last == BLANK) {
fMatchKind= SearchPattern.R_EXACT_MATCH;
fPattern= pattern.trim();
return;
}
if (SearchUtils.isCamelCasePattern(pattern)) {
fMatchKind= SearchPattern.R_CAMELCASE_MATCH;
fPattern= pattern;
return;
}
fMatchKind= SearchPattern.R_PREFIX_MATCH;
fPattern= pattern;
}
}
private String fText;
private IJavaSearchScope fSearchScope;
private boolean fIsWorkspaceScope;
private int fElementKind;
private ITypeInfoFilterExtension fFilterExtension;
private TypeInfoAdapter fAdapter= new TypeInfoAdapter();
private PatternMatcher fPackageMatcher;
private PatternMatcher fNameMatcher;
private static final int TYPE_MODIFIERS= Flags.AccEnum | Flags.AccAnnotation | Flags.AccInterface;
public TypeInfoFilter(String text, IJavaSearchScope scope, int elementKind, ITypeInfoFilterExtension extension) {
fText= text;
fSearchScope= scope;
fIsWorkspaceScope= fSearchScope.equals(SearchEngine.createWorkspaceScope());
fElementKind= elementKind;
fFilterExtension= extension;
int index= text.lastIndexOf("."); //$NON-NLS-1$
if (index == -1) {
fNameMatcher= new PatternMatcher(text, true);
} else {
fPackageMatcher= new PatternMatcher(text.substring(0, index),
SearchPattern.R_EXACT_MATCH | SearchPattern.R_PATTERN_MATCH);
String name= text.substring(index + 1);
if (name.length() == 0)
name= "*"; //$NON-NLS-1$
fNameMatcher= new PatternMatcher(name, true);
}
}
public String getText() {
return fText;
}
public boolean isSubFilter(String text) {
if (! fText.startsWith(text))
return false;
return fText.indexOf('.', text.length()) == -1;
}
public boolean isCamcelCasePattern() {
return fNameMatcher.getMatchKind() == SearchPattern.R_CAMELCASE_MATCH;
}
public String getPackagePattern() {
if (fPackageMatcher == null)
return null;
return fPackageMatcher.getPattern();
}
public String getNamePattern() {
return fNameMatcher.getPattern();
}
public int getSearchFlags() {
return fNameMatcher.getMatchKind();
}
public boolean matchesRawNamePattern(TypeInfo type) {
return Strings.startsWithIgnoreCase(type.getTypeName(), fNameMatcher.getPattern());
}
public boolean matchesCachedResult(TypeInfo type) {
if (!(matchesPackage(type) && matchesFilterExtension(type)))
return false;
return matchesName(type);
}
public boolean matchesHistoryElement(TypeInfo type) {
if (!(matchesPackage(type) && matchesModifiers(type) && matchesScope(type) && matchesFilterExtension(type)))
return false;
return matchesName(type);
}
public boolean matchesFilterExtension(TypeInfo type) {
if (fFilterExtension == null)
return true;
fAdapter.setInfo(type);
return fFilterExtension.select(fAdapter);
}
private boolean matchesName(TypeInfo type) {
return fNameMatcher.matches(type.getTypeName());
}
private boolean matchesPackage(TypeInfo type) {
if (fPackageMatcher == null)
return true;
// We should use the type container name here. However this
// require support from JDT/Core. See
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=120534
return fPackageMatcher.matches(type.getPackageName());
}
private boolean matchesScope(TypeInfo type) {
if (fIsWorkspaceScope)
return true;
return type.isEnclosed(fSearchScope);
}
private boolean matchesModifiers(TypeInfo type) {
if (fElementKind == IJavaSearchConstants.TYPE)
return true;
int modifiers= type.getModifiers() & TYPE_MODIFIERS;
switch (fElementKind) {
case IJavaSearchConstants.CLASS:
return modifiers == 0;
case IJavaSearchConstants.ANNOTATION_TYPE:
return Flags.isAnnotation(modifiers);
case IJavaSearchConstants.INTERFACE:
return Flags.isInterface(modifiers);
case IJavaSearchConstants.ENUM:
return Flags.isEnum(modifiers);
case IJavaSearchConstants.CLASS_AND_INTERFACE:
return modifiers == 0 || Flags.isInterface(modifiers);
case IJavaSearchConstants.CLASS_AND_ENUM:
return modifiers == 0 || Flags.isEnum(modifiers);
}
return false;
}
}