mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
cleanup MinusculeMatcher
This commit is contained in:
@@ -23,7 +23,6 @@ import com.intellij.util.text.CharArrayUtil;
|
||||
import com.intellij.util.text.Matcher;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
import static com.intellij.psi.codeStyle.NameUtil.MatchingCaseSensitivity.*;
|
||||
@@ -40,115 +39,6 @@ public class MinusculeMatcher implements Matcher {
|
||||
myPattern = StringUtil.trimEnd(pattern, "* ").toCharArray();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FList<TextRange> matchName(String name, int patternIndex, int nameIndex) {
|
||||
if (patternIndex == myPattern.length) {
|
||||
return FList.emptyList();
|
||||
}
|
||||
if ('*' == myPattern[patternIndex]) {
|
||||
return skipChars(name, patternIndex, nameIndex, true);
|
||||
}
|
||||
if (nameIndex == name.length()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ('.' == myPattern[patternIndex] && name.charAt(nameIndex) != '.') {
|
||||
return skipChars(name, patternIndex, nameIndex, false);
|
||||
}
|
||||
|
||||
if (' ' == myPattern[patternIndex] && patternIndex != myPattern.length - 1) {
|
||||
return skipWords(name, patternIndex, nameIndex);
|
||||
}
|
||||
|
||||
if ((patternIndex == 0 || patternIndex == 1 && myPattern[0] == ' ' && nameIndex == 0) &&
|
||||
myOptions != NameUtil.MatchingCaseSensitivity.NONE && name.charAt(nameIndex) != myPattern[patternIndex]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (NameUtil.isWordSeparator(name.charAt(nameIndex))) {
|
||||
return skipSeparators(name, patternIndex, nameIndex);
|
||||
}
|
||||
|
||||
if (StringUtil.toLowerCase(name.charAt(nameIndex)) != StringUtil.toLowerCase(myPattern[patternIndex])) {
|
||||
if (Character.isDigit(name.charAt(nameIndex)) && nameIndex > 0 || (name.charAt(nameIndex) == '.' && name.indexOf('.', nameIndex + 1) > 0)) {
|
||||
return matchName(name, patternIndex, nameIndex + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (myOptions == ALL && name.charAt(nameIndex) != myPattern[patternIndex]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int nextStart = NameUtil.nextWord(name, nameIndex);
|
||||
|
||||
int lastUpper = NameUtil.isWordStart(myPattern[patternIndex]) ? 0 : -1;
|
||||
|
||||
int i = 1;
|
||||
while (true) {
|
||||
if (patternIndex + i == myPattern.length || i + nameIndex == nextStart) {
|
||||
break;
|
||||
}
|
||||
char p = myPattern[patternIndex + i];
|
||||
char w = name.charAt(i + nameIndex);
|
||||
if (lastUpper == i - 1 && NameUtil.isWordStart(p) && myOptions != ALL) {
|
||||
if (p == w) {
|
||||
lastUpper = i;
|
||||
}
|
||||
p = StringUtil.toLowerCase(p);
|
||||
}
|
||||
|
||||
if (myOptions != ALL) {
|
||||
w = StringUtil.toLowerCase(w);
|
||||
}
|
||||
if (w != p) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (isFinalSpaceMatch(name, patternIndex, nameIndex, nextStart, i)) {
|
||||
return FList.<TextRange>emptyList().prepend(TextRange.from(nameIndex, i));
|
||||
}
|
||||
|
||||
return matchAfterFragment(name, patternIndex, nameIndex, nextStart, lastUpper, i);
|
||||
}
|
||||
|
||||
private boolean isFinalSpaceMatch(String name, int patternIndex, int nameIndex, int nextStart, int i) {
|
||||
return nextStart == name.length() &&
|
||||
patternIndex + i == myPattern.length - 1 &&
|
||||
' ' == myPattern[patternIndex + i] &&
|
||||
(i == 1 && NameUtil.isWordStart(myPattern[patternIndex]) || i + nameIndex == name.length());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FList<TextRange> matchAfterFragment(String name, int patternIndex, int nameIndex, int nextStart, int lastUpper, int matchLen) {
|
||||
boolean star = patternIndex + matchLen < myPattern.length && myPattern[patternIndex + matchLen] == '*';
|
||||
if (lastUpper >= 1) {
|
||||
int nextNameIndex = star && matchLen == lastUpper ? nameIndex + lastUpper : nextStart;
|
||||
int nextPatternIndex = patternIndex + lastUpper + 1;
|
||||
FList<TextRange> ranges = star ? matchName(name, nextPatternIndex, nextNameIndex) : skipWords(name, nextPatternIndex, nextNameIndex);
|
||||
if (ranges != null) {
|
||||
return prependRange(ranges, nameIndex, lastUpper + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int trial = matchLen;
|
||||
while (trial > 0) {
|
||||
FList<TextRange> ranges = skipWords(name, patternIndex + trial, nextStart);
|
||||
if (ranges != null) {
|
||||
return prependRange(ranges, nameIndex, trial);
|
||||
}
|
||||
trial--;
|
||||
}
|
||||
|
||||
FList<TextRange> ranges = matchName(name, patternIndex + matchLen, nameIndex + matchLen);
|
||||
if (ranges != null) {
|
||||
return prependRange(ranges, nameIndex, matchLen);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static FList<TextRange> prependRange(FList<TextRange> ranges, int from, int length) {
|
||||
TextRange head = ranges.getHead();
|
||||
if (head != null && head.getStartOffset() == from + length) {
|
||||
@@ -157,123 +47,6 @@ public class MinusculeMatcher implements Matcher {
|
||||
return ranges.prepend(TextRange.from(from, length));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FList<TextRange> skipSeparators(String name, int patternIndex, int nameIndex) {
|
||||
int nextStart = NameUtil.nextWord(name, nameIndex);
|
||||
assert nextStart - nameIndex == 1 : "'" + name + "'" + nameIndex + " " + nextStart;
|
||||
char p = myPattern[patternIndex];
|
||||
if (NameUtil.isWordSeparator(p)) {
|
||||
if (myOptions != NameUtil.MatchingCaseSensitivity.NONE &&
|
||||
nameIndex == 0 && name.length() > 1 && patternIndex + 1 < myPattern.length &&
|
||||
NameUtil.isWordSeparator(name.charAt(1)) && !NameUtil.isWordSeparator(myPattern[patternIndex + 1])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final FList<TextRange> ranges = matchName(name, patternIndex + 1, nextStart);
|
||||
if (ranges != null) {
|
||||
return prependRange(ranges, nameIndex, 1);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return matchName(name, patternIndex, nextStart);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FList<TextRange> skipChars(String name, int patternIndex, int nameIndex, boolean maySkipNextChar) {
|
||||
boolean veryStart = patternIndex == 0;
|
||||
while ('*' == myPattern[patternIndex]) {
|
||||
patternIndex++;
|
||||
if (patternIndex == myPattern.length) {
|
||||
return FList.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
char nextChar = myPattern[patternIndex];
|
||||
boolean upper = Character.isUpperCase(myPattern[patternIndex]);
|
||||
|
||||
int fromIndex = nameIndex;
|
||||
while (true) {
|
||||
int next = StringUtil.indexOfIgnoreCase(name, nextChar, fromIndex);
|
||||
if (next < 0) {
|
||||
break;
|
||||
}
|
||||
if (next == 0 && myOptions != NameUtil.MatchingCaseSensitivity.NONE && name.charAt(next) != nextChar) {
|
||||
fromIndex = next + 1;
|
||||
continue;
|
||||
}
|
||||
if (upper && next > 0 && !Character.isUpperCase(name.charAt(next))) {
|
||||
fromIndex = next + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (veryStart && next > 0 && !NameUtil.isWordStart(name, next) && !NameUtil.isWordSeparator(nextChar)) {
|
||||
if (next == name.length() - 1) {
|
||||
return null;
|
||||
}
|
||||
if (patternIndex == myPattern.length - 1 ||
|
||||
Character.isLetter(myPattern[patternIndex + 1]) && (myPattern[patternIndex + 1] != name.charAt(next + 1) ||
|
||||
NameUtil.isWordStart(name, next + 1))) {
|
||||
fromIndex = next + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
FList<TextRange> ranges = matchName(name, patternIndex, next);
|
||||
if (ranges != null) {
|
||||
return ranges;
|
||||
}
|
||||
if (!maySkipNextChar) {
|
||||
return null;
|
||||
}
|
||||
fromIndex = next + 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FList<TextRange> skipWords(String name, int patternIndex, int nameIndex) {
|
||||
while (patternIndex < myPattern.length && ' ' == myPattern[patternIndex]) {
|
||||
patternIndex++;
|
||||
}
|
||||
if (patternIndex == myPattern.length) {
|
||||
return FList.emptyList();
|
||||
}
|
||||
if (nameIndex == name.length()) {
|
||||
return null;
|
||||
}
|
||||
if (myPattern[patternIndex] == '*') {
|
||||
return skipChars(name, patternIndex, nameIndex, true);
|
||||
}
|
||||
|
||||
if (nameIndex == 0 || NameUtil.isWordStart(name, nameIndex)) {
|
||||
FList<TextRange> ranges = matchName(name, patternIndex, nameIndex);
|
||||
if (ranges != null) {
|
||||
return ranges;
|
||||
}
|
||||
}
|
||||
|
||||
boolean separatorInPattern = !Character.isLetterOrDigit(myPattern[patternIndex]);
|
||||
int fromIndex = nameIndex;
|
||||
while (fromIndex < name.length()) {
|
||||
int next = separatorInPattern ? name.indexOf(myPattern[patternIndex], fromIndex) : NameUtil.nextWord(name, fromIndex);
|
||||
if (next < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
FList<TextRange> ranges = matchName(name, patternIndex, next);
|
||||
if (ranges != null) {
|
||||
return ranges;
|
||||
}
|
||||
fromIndex = next;
|
||||
if (separatorInPattern) {
|
||||
fromIndex++;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int matchingDegree(String name) {
|
||||
Iterable<TextRange> iterable = matchingFragments(name);
|
||||
if (iterable == null) return Integer.MIN_VALUE;
|
||||
@@ -351,22 +124,21 @@ public class MinusculeMatcher implements Matcher {
|
||||
|
||||
@Nullable
|
||||
public Iterable<TextRange> matchingFragments(String name) {
|
||||
if (name.isEmpty()) {
|
||||
return myPattern.length == 0 ? Collections.<TextRange>emptyList() : null;
|
||||
}
|
||||
|
||||
if (true) {
|
||||
return matchWildcards(name, 0, 0);
|
||||
}
|
||||
|
||||
return matchName(name, 0, 0);
|
||||
return matchWildcards(name, 0, 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FList<TextRange> matchWildcards(String name, int patternIndex, int nameIndex) {
|
||||
while (isWildcard(patternIndex)) {
|
||||
patternIndex++;
|
||||
if (nameIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
if (!isWildcard(patternIndex)) {
|
||||
return matchFragment(name, patternIndex, nameIndex);
|
||||
}
|
||||
|
||||
do {
|
||||
patternIndex++;
|
||||
} while (isWildcard(patternIndex));
|
||||
boolean space = isPatternChar(patternIndex - 1, ' ');
|
||||
if (patternIndex == myPattern.length) {
|
||||
if (space && nameIndex != name.length() && (patternIndex < 2 || !NameUtil.isWordStart(myPattern[patternIndex - 2]))) {
|
||||
@@ -375,26 +147,26 @@ public class MinusculeMatcher implements Matcher {
|
||||
return FList.emptyList();
|
||||
}
|
||||
|
||||
{
|
||||
FList<TextRange> ranges = matchFragment(name, patternIndex, nameIndex);
|
||||
if (ranges != null) {
|
||||
return ranges;
|
||||
}
|
||||
}
|
||||
|
||||
char p = myPattern[patternIndex];
|
||||
if (isWildcard(patternIndex - 1)) {
|
||||
{
|
||||
while (true) {
|
||||
nameIndex = space ? indexOfWordStart(name, p, nameIndex) : StringUtil.indexOfIgnoreCase(name, p, nameIndex + 1);
|
||||
if (nameIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
if (!Character.isUpperCase(p) || NameUtil.isWordStart(name, nameIndex)) {
|
||||
FList<TextRange> ranges = matchFragment(name, patternIndex, nameIndex);
|
||||
if (ranges != null) {
|
||||
return ranges;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
nameIndex = space ? indexOfWordStart(name, p, nameIndex) : StringUtil.indexOfIgnoreCase(name, p, nameIndex + 1);
|
||||
if (nameIndex < 0) return null;
|
||||
if (!Character.isUpperCase(p) || NameUtil.isWordStart(name, nameIndex)) {
|
||||
FList<TextRange> ranges = matchFragment(name, patternIndex, nameIndex);
|
||||
if (ranges != null) {
|
||||
return ranges;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return matchFragment(name, patternIndex, nameIndex);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -414,11 +186,9 @@ public class MinusculeMatcher implements Matcher {
|
||||
}
|
||||
if (myPattern[patternIndex + i] != name.charAt(nameIndex + i)) {
|
||||
int nextWordStart = indexOfWordStart(name, myPattern[patternIndex + i], nameIndex + i);
|
||||
if (nextWordStart >= 0) {
|
||||
FList<TextRange> ranges = matchWildcards(name, patternIndex + i, nextWordStart);
|
||||
if (ranges != null) {
|
||||
return prependRange(ranges, nameIndex, i);
|
||||
}
|
||||
FList<TextRange> ranges = matchWildcards(name, patternIndex + i, nextWordStart);
|
||||
if (ranges != null) {
|
||||
return prependRange(ranges, nameIndex, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,11 +200,9 @@ public class MinusculeMatcher implements Matcher {
|
||||
}
|
||||
while (i >= minFragment) {
|
||||
int nextWordStart = isWildcard(patternIndex + i) ? nameIndex + i : indexOfWordStart(name, myPattern[patternIndex + i], nameIndex + i);
|
||||
if (nextWordStart >= 0) {
|
||||
FList<TextRange> ranges = matchWildcards(name, patternIndex + i, nextWordStart);
|
||||
if (ranges != null) {
|
||||
return prependRange(ranges, nameIndex, i);
|
||||
}
|
||||
FList<TextRange> ranges = matchWildcards(name, patternIndex + i, nextWordStart);
|
||||
if (ranges != null) {
|
||||
return prependRange(ranges, nameIndex, i);
|
||||
}
|
||||
i--;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user