/** * After a wildcard (* or space), search for the first non-wildcard pattern character in the name * starting from nameIndex and try to {@link #matchFragment(String, int, int, * com.intellij.psi.codeStyle.MinusculeMatcher.MatchingState)} for it. */ @Nullable private FList<TextRange> matchWildcards( @NotNull String name, int patternIndex, int nameIndex, MatchingState matchingState) { if (nameIndex < 0) { return null; } if (!isWildcard(patternIndex)) { if (patternIndex == myPattern.length) { return FList.emptyList(); } return matchFragment(name, patternIndex, nameIndex, matchingState); } do { patternIndex++; } while (isWildcard(patternIndex)); if (patternIndex == myPattern.length) { boolean space = isPatternChar(patternIndex - 1, ' '); // the trailing space should match if the pattern ends with the last word part, or only its // first hump character if (space && nameIndex != name.length() && (patternIndex < 2 || !NameUtil.isWordStart(myPattern[patternIndex - 2]))) { int spaceIndex = name.indexOf(' ', nameIndex); if (spaceIndex >= 0) { return FList.<TextRange>emptyList().prepend(TextRange.from(spaceIndex, 1)); } return null; } return FList.emptyList(); } FList<TextRange> ranges = matchFragment(name, patternIndex, nameIndex, matchingState); if (ranges != null) { return ranges; } return matchSkippingWords(name, patternIndex, nameIndex, true, matchingState); }
public static boolean processParents( @NotNull Artifact artifact, @NotNull PackagingElementResolvingContext context, @NotNull ParentElementProcessor processor, int maxLevel) { return processParents( artifact, context, processor, FList.<Pair<Artifact, CompositePackagingElement<?>>>emptyList(), maxLevel, new HashSet<Artifact>()); }
/** * Attempts to match an alphanumeric sequence of pattern (starting at patternIndex) to some * continuous substring of name, starting from nameIndex. */ private FList<TextRange> doMatchFragments( String name, int patternIndex, int nameIndex, MatchingState matchingState) { if (!isFirstCharMatching(name, nameIndex, patternIndex)) { return null; } // middle matches have to be at least of length 3, to prevent too many irrelevant matches int minFragment = isPatternChar(patternIndex - 1, '*') && !isWildcard(patternIndex + 1) && Character.isLetterOrDigit(name.charAt(nameIndex)) && !isWordStart(name, nameIndex) ? 3 : 1; int i = 1; boolean ignoreCase = myOptions != NameUtil.MatchingCaseSensitivity.ALL; while (nameIndex + i < name.length() && patternIndex + i < myPattern.length && charEquals( myPattern[patternIndex + i], patternIndex + i, name.charAt(nameIndex + i), ignoreCase)) { if (isUpperCase[patternIndex + i] && myHasHumps) { if (i < minFragment) { return null; } // when an uppercase pattern letter matches lowercase name letter, try to find an uppercase // (better) match further in the name if (myPattern[patternIndex + i] != name.charAt(nameIndex + i)) { int nextWordStart = indexOfWordStart(name, patternIndex + i, nameIndex + i); FList<TextRange> ranges = matchWildcards(name, patternIndex + i, nextWordStart, matchingState); if (ranges != null) { return prependRange(ranges, nameIndex, i); } // at least three consecutive uppercase letters shouldn't match lowercase if (i > 1 && isUpperCase[patternIndex + i - 1] && isUpperCase[patternIndex + i - 2]) { // but if there's a lowercase after them, it can match (in case shift was released a bit // later) if (nameIndex + i + 1 == name.length() || patternIndex + i + 1 < myPattern.length && !isLowerCase[patternIndex + i + 1]) { return null; } } } } i++; } // we've found the longest fragment matching pattern and name if (patternIndex + i >= myPattern.length) { return FList.<TextRange>emptyList().prepend(TextRange.from(nameIndex, i)); } // try to match the remainder of pattern with the remainder of name // it may not succeed with the longest matching fragment, then try shorter matches while (i >= minFragment || isWildcard(patternIndex + i)) { FList<TextRange> ranges = isWildcard(patternIndex + i) ? matchWildcards(name, patternIndex + i, nameIndex + i, matchingState) : matchSkippingWords(name, patternIndex + i, nameIndex + i, false, matchingState); if (ranges != null) { return prependRange(ranges, nameIndex, i); } i--; } return null; }