blob: 6470753f0f65de32dd8442f8996f16097a3e1847 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 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
*
*******************************************************************************/
package org.eclipse.dltk.internal.corext.util;
import org.eclipse.dltk.core.ISearchPatternProcessor;
import org.eclipse.dltk.core.ISearchPatternProcessor.ITypePattern;
import org.eclipse.dltk.core.search.IDLTKSearchConstants;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.SearchEngine;
import org.eclipse.dltk.core.search.SearchPattern;
import org.eclipse.dltk.core.search.TypeNameMatch;
import org.eclipse.dltk.internal.ui.util.StringMatcher;
import org.eclipse.dltk.ui.IDLTKUILanguageToolkit;
import org.eclipse.dltk.ui.dialogs.ITypeInfoFilterExtension;
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 final IDLTKSearchScope fSearchScope;
private final boolean fIsWorkspaceScope;
private int fElementKind;
private ITypeInfoFilterExtension fFilterExtension;
private TypeInfoRequestorAdapter fAdapter = new TypeInfoRequestorAdapter();
private PatternMatcher fPackageMatcher;
private PatternMatcher fNameMatcher;
private static final int TYPE_MODIFIERS = 0;
public TypeInfoFilter(IDLTKUILanguageToolkit uiToolkit, String text,
IDLTKSearchScope scope, int elementKind,
ITypeInfoFilterExtension extension,
ISearchPatternProcessor processor) {
fText = text;
fSearchScope = scope;
fIsWorkspaceScope = fSearchScope.equals(SearchEngine
.createWorkspaceScope(uiToolkit.getCoreToolkit()));
fElementKind = elementKind;
fFilterExtension = extension;
ITypePattern pattern = processor.parseType(text);
String simpleName = pattern.getSimpleName();
if (simpleName.length() == 0) {
simpleName = "*";
}
fNameMatcher = new PatternMatcher(simpleName, true);
if (pattern.getQualification() != null) {
fPackageMatcher = new PatternMatcher(
evaluatePackagePattern(pattern.getQualification()), true);
}
}
/*
* Transforms o.e.j to o*.e*.j*
*/
private String evaluatePackagePattern(String s) {
StringBuilder buf = new StringBuilder();
boolean hasWildCard = false;
int len = s.length();
for (int i = 0; i < len; i++) {
char ch = s.charAt(i);
if (ch == ISearchPatternProcessor.TYPE_SEPARATOR) {
if (!hasWildCard) {
buf.append('*');
}
hasWildCard = false;
} else if (ch == '*' || ch == '?') {
hasWildCard = true;
}
buf.append(ch);
}
if (!hasWildCard) {
if (len == 0) {
buf.append('?');
}
buf.append('*');
}
return buf.toString();
}
public String getText() {
return fText;
}
public boolean isSubFilter(String text) {
if (!fText.startsWith(text))
return false;
return fPackageMatcher == null;
}
public boolean isCamelCasePattern() {
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 int getPackageFlags() {
if (fPackageMatcher == null)
return SearchPattern.R_EXACT_MATCH;
return fPackageMatcher.getMatchKind();
}
public boolean matchesRawNamePattern(TypeNameMatch type) {
return Strings.startsWithIgnoreCase(type.getSimpleTypeName(),
fNameMatcher.getPattern());
}
public boolean matchesCachedResult(TypeNameMatch type) {
if (!(matchesPackage(type) && matchesFilterExtension(type)))
return false;
return matchesName(type);
}
public boolean matchesHistoryElement(TypeNameMatch type) {
if (!(matchesPackage(type) && matchesModifiers(type)
&& matchesScope(type) && matchesFilterExtension(type)))
return false;
return matchesName(type);
}
public boolean matchesFilterExtension(TypeNameMatch type) {
if (fFilterExtension == null)
return true;
fAdapter.setMatch(type);
return fFilterExtension.select(fAdapter);
}
private boolean matchesName(TypeNameMatch type) {
return fNameMatcher.matches(type.getSimpleTypeName());
}
private boolean matchesPackage(TypeNameMatch type) {
if (fPackageMatcher == null)
return true;
return fPackageMatcher.matches(type.getTypeContainerName());
}
private boolean matchesScope(TypeNameMatch type) {
if (fIsWorkspaceScope)
return true;
return fSearchScope.encloses(type.getType());
}
private boolean matchesModifiers(TypeNameMatch type) {
if (fElementKind == IDLTKSearchConstants.TYPE)
return true;
int modifiers = type.getModifiers() & TYPE_MODIFIERS;
switch (fElementKind) {
case IDLTKSearchConstants.TYPE:
return modifiers == 0;
}
return false;
}
}