mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-87938 Completion: extend 'middle-matching' by '*word*parts*' in completion
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
-Camel.java
|
||||
-Camel
|
||||
[getSomeHead():void]
|
||||
[doSomethingWithMyHead():void]
|
||||
getSomeArtHeader():void
|
||||
getSomeHead():void
|
||||
+5
-1
@@ -80,7 +80,11 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
}
|
||||
|
||||
public void testNoObjectMethodsAsFirstPart() throws Throwable { doTest(); }
|
||||
public void testGetClassLoader() throws Throwable { doTest(); }
|
||||
public void testGetClassLoader() throws Throwable {
|
||||
configure();
|
||||
selectItem(myItems[0]);
|
||||
checkResult();
|
||||
}
|
||||
public void testNewStaticProblem() throws Throwable { doTest(); }
|
||||
|
||||
public void testChainingPerformance() throws Throwable {
|
||||
|
||||
@@ -51,6 +51,11 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
assertMatches("AACl", "AAClass");
|
||||
assertMatches("ZZZ", "ZZZZZZZZZZ");
|
||||
}
|
||||
|
||||
public void testSkipWords() {
|
||||
assertMatches("nt", "NameUtilTest");
|
||||
assertDoesntMatch("ABCD", "AbstractButton.DISABLED_ICON_CHANGED_PROPERTY");
|
||||
}
|
||||
|
||||
public void testSimpleCasesWithFirstLowercased() throws Exception {
|
||||
assertMatches("N", "nameUtilTest");
|
||||
@@ -79,9 +84,9 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
|
||||
public void testXMLCompletion() throws Exception {
|
||||
assertDoesntMatch("N_T", "NameUtilTest");
|
||||
assertDoesntMatch("ORGS_ACC", "ORGS_POSITION_ACCOUNTABILITY");
|
||||
assertDoesntMatch("ORGS-ACC", "ORGS-POSITION_ACCOUNTABILITY");
|
||||
assertDoesntMatch("ORGS.ACC", "ORGS.POSITION_ACCOUNTABILITY");
|
||||
assertMatches("ORGS_ACC", "ORGS_POSITION_ACCOUNTABILITY");
|
||||
assertMatches("ORGS-ACC", "ORGS-POSITION_ACCOUNTABILITY");
|
||||
assertMatches("ORGS.ACC", "ORGS.POSITION_ACCOUNTABILITY");
|
||||
}
|
||||
|
||||
public void testStarFalsePositive() throws Exception {
|
||||
@@ -112,7 +117,7 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
assertDoesntMatch("ARS.j", "activity_report_summary.xml");
|
||||
assertDoesntMatch("ARS.j", "activity_report_summary_justsometingwrong.xml");
|
||||
|
||||
assertDoesntMatch("foo.goo", "foo.bar.goo");
|
||||
assertMatches("foo.goo", "foo.bar.goo");
|
||||
}
|
||||
|
||||
public void testSpaceForAnyWordsInBetween() {
|
||||
@@ -168,8 +173,8 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
public void testSkipDot() {
|
||||
assertMatches("ja", "jquery.autocomplete.js");
|
||||
assertMatches("ja.js", "jquery.autocomplete.js");
|
||||
assertDoesntMatch("jajs", "jquery.autocomplete.js");
|
||||
assertDoesntMatch("j.ajs", "jquery.autocomplete.js");
|
||||
assertMatches("jajs", "jquery.autocomplete.js");
|
||||
assertMatches("j.ajs", "jquery.autocomplete.js");
|
||||
}
|
||||
|
||||
public void testNoExtension() {
|
||||
@@ -192,11 +197,11 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
assertDoesntMatch("*inspection*.pro", "InspectionsInProgress.png");
|
||||
}
|
||||
|
||||
public void testIgnoreLeadingUnderscore() throws Exception {
|
||||
assertMatches("form", "_form.html.erb");
|
||||
public void testLeadingUnderscore() throws Exception {
|
||||
assertDoesntMatch("form", "_form.html.erb");
|
||||
assertMatches("_form", "_form.html.erb");
|
||||
assertMatches("_form", "__form");
|
||||
assertFalse(NameUtil.buildMatcher("_form", 1, true, true, false).matches("__form"));
|
||||
assertTrue(firstLetterMatcher("_form").matches("__form"));
|
||||
}
|
||||
|
||||
public void testLowerCaseWords() throws Exception {
|
||||
@@ -208,6 +213,8 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
}
|
||||
|
||||
public void testObjectiveCCases() throws Exception {
|
||||
assertMatches("h*:", "h:aaa");
|
||||
assertMatches("h:", "h:aaa");
|
||||
assertMatches("text:sh", "textField:shouldChangeCharactersInRange:replacementString:");
|
||||
assertMatches("abc", "aaa:bbb:ccc");
|
||||
assertMatches("textField:sh", "textField:shouldChangeCharactersInRange:replacementString:");
|
||||
@@ -293,7 +300,7 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
assertDoesntMatch("foo", "fxoo");
|
||||
assertMatches("foo", "fOo");
|
||||
assertMatches("foo", "fxOo");
|
||||
assertDoesntMatch("foo", "fXOo");
|
||||
assertMatches("foo", "fXOo");
|
||||
assertMatches("fOo", "foo");
|
||||
assertMatches("fOo", "FaOaOaXXXX");
|
||||
assertMatches("ncdfoe", "NoClassDefFoundException");
|
||||
@@ -338,7 +345,7 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
assertMatches("a@b", "a@bc");
|
||||
|
||||
assertMatches("a/text", "a/Text");
|
||||
assertDoesntMatch("a/text", "a/bbbText");
|
||||
assertMatches("a/text", "a/bbbText");
|
||||
}
|
||||
|
||||
public void testMinusculeFirstLetter() {
|
||||
@@ -459,7 +466,7 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
for (String s : CollectionFactory.ar("*", "*i", "*a", "*u", "T", "ti", longName, longName.substring(0, 20))) {
|
||||
matching.add(new MinusculeMatcher(s, NameUtil.MatchingCaseSensitivity.NONE));
|
||||
}
|
||||
for (String s : CollectionFactory.ar("A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "ta")) {
|
||||
for (String s : CollectionFactory.ar("A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "tag")) {
|
||||
nonMatching.add(new MinusculeMatcher(s, NameUtil.MatchingCaseSensitivity.NONE));
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
import static com.intellij.psi.codeStyle.NameUtil.MatchingCaseSensitivity.*;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
@@ -35,7 +37,7 @@ public class MinusculeMatcher implements Matcher {
|
||||
|
||||
public MinusculeMatcher(String pattern, NameUtil.MatchingCaseSensitivity options) {
|
||||
myOptions = options;
|
||||
myPattern = StringUtil.trimEnd(pattern, "* ").replaceAll(":", "\\*:").toCharArray();
|
||||
myPattern = StringUtil.trimEnd(pattern, "* ").toCharArray();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -74,7 +76,7 @@ public class MinusculeMatcher implements Matcher {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (myOptions == NameUtil.MatchingCaseSensitivity.ALL && name.charAt(nameIndex) != myPattern[patternIndex]) {
|
||||
if (myOptions == ALL && name.charAt(nameIndex) != myPattern[patternIndex]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -89,14 +91,14 @@ public class MinusculeMatcher implements Matcher {
|
||||
}
|
||||
char p = myPattern[patternIndex + i];
|
||||
char w = name.charAt(i + nameIndex);
|
||||
if (lastUpper == i - 1 && NameUtil.isWordStart(p) && myOptions != NameUtil.MatchingCaseSensitivity.ALL) {
|
||||
if (lastUpper == i - 1 && NameUtil.isWordStart(p) && myOptions != ALL) {
|
||||
if (p == w) {
|
||||
lastUpper = i;
|
||||
}
|
||||
p = StringUtil.toLowerCase(p);
|
||||
}
|
||||
|
||||
if (myOptions != NameUtil.MatchingCaseSensitivity.ALL) {
|
||||
if (myOptions != ALL) {
|
||||
w = StringUtil.toLowerCase(w);
|
||||
}
|
||||
if (w != p) {
|
||||
@@ -122,8 +124,10 @@ public class MinusculeMatcher implements Matcher {
|
||||
@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 >= 0) {
|
||||
FList<TextRange> ranges = matchName(name, patternIndex + lastUpper + 1, star && matchLen == lastUpper ? nameIndex + lastUpper : nextStart);
|
||||
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);
|
||||
}
|
||||
@@ -131,7 +135,7 @@ public class MinusculeMatcher implements Matcher {
|
||||
|
||||
int trial = matchLen;
|
||||
while (trial > 0) {
|
||||
FList<TextRange> ranges = matchName(name, patternIndex + trial, nextStart);
|
||||
FList<TextRange> ranges = skipWords(name, patternIndex + trial, nextStart);
|
||||
if (ranges != null) {
|
||||
return prependRange(ranges, nameIndex, trial);
|
||||
}
|
||||
@@ -230,11 +234,17 @@ public class MinusculeMatcher implements Matcher {
|
||||
|
||||
@Nullable
|
||||
private FList<TextRange> skipWords(String name, int patternIndex, int nameIndex) {
|
||||
while (' ' == myPattern[patternIndex]) {
|
||||
while (patternIndex < myPattern.length && ' ' == myPattern[patternIndex]) {
|
||||
patternIndex++;
|
||||
if (patternIndex == myPattern.length) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
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)) {
|
||||
@@ -244,7 +254,7 @@ public class MinusculeMatcher implements Matcher {
|
||||
}
|
||||
}
|
||||
|
||||
boolean separatorInPattern = NameUtil.isWordSeparator(myPattern[patternIndex]);
|
||||
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);
|
||||
@@ -340,9 +350,124 @@ public class MinusculeMatcher implements Matcher {
|
||||
return myPattern.length == 0 ? Collections.<TextRange>emptyList() : null;
|
||||
}
|
||||
|
||||
if (true) {
|
||||
return matchWildcards(name, 0, 0);
|
||||
}
|
||||
|
||||
return matchName(name, 0, 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FList<TextRange> matchWildcards(String name, int patternIndex, int nameIndex) {
|
||||
while (isWildcard(patternIndex)) {
|
||||
patternIndex++;
|
||||
}
|
||||
boolean space = isPatternChar(patternIndex - 1, ' ');
|
||||
if (patternIndex == myPattern.length) {
|
||||
if (space && nameIndex != name.length() && (patternIndex < 2 || !NameUtil.isWordStart(myPattern[patternIndex - 2]))) {
|
||||
return null;
|
||||
}
|
||||
return FList.emptyList();
|
||||
}
|
||||
|
||||
char p = myPattern[patternIndex];
|
||||
if (isWildcard(patternIndex - 1)) {
|
||||
{
|
||||
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
|
||||
private FList<TextRange> matchFragment(String name, int patternIndex, int nameIndex) {
|
||||
if (!isFirstCharMatching(name, nameIndex, myPattern[patternIndex])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int minFragment = isPatternChar(patternIndex - 1, '*') && Character.isLetterOrDigit(name.charAt(nameIndex)) && !NameUtil.isWordStart(name, nameIndex) ? 2 : 1;
|
||||
int i = 1;
|
||||
while (nameIndex + i < name.length() &&
|
||||
patternIndex + i < myPattern.length &&
|
||||
StringUtil.charsEqual(myPattern[patternIndex + i], name.charAt(nameIndex + i), myOptions != ALL)) {
|
||||
if (Character.isUpperCase(myPattern[patternIndex + i])) {
|
||||
if (i < minFragment) {
|
||||
return null;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (patternIndex + i >= myPattern.length) {
|
||||
return i >= minFragment ? FList.<TextRange>emptyList().prepend(TextRange.from(nameIndex, i)) : null;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
i--;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isFirstCharMatching(String name, int nameIndex, char p) {
|
||||
return nameIndex < name.length() && StringUtil.charsEqual(p, name.charAt(nameIndex),
|
||||
myOptions == FIRST_LETTER && nameIndex > 0 || myOptions == NONE);
|
||||
}
|
||||
|
||||
private boolean isWildcard(int patternIndex) {
|
||||
return isPatternChar(patternIndex, ' ') || isPatternChar(patternIndex, '*');
|
||||
}
|
||||
private boolean isPatternChar(int patternIndex, char c) {
|
||||
if (patternIndex < 0 || patternIndex >= myPattern.length) return false;
|
||||
return myPattern[patternIndex] == c;
|
||||
}
|
||||
|
||||
private static int indexOfWordStart(String name, char p, int startFrom) {
|
||||
if (p == '.' || NameUtil.isWordSeparator(p)) {
|
||||
return StringUtil.indexOfIgnoreCase(name, p, startFrom + 1);
|
||||
}
|
||||
if (startFrom >= name.length()) {
|
||||
return -1;
|
||||
}
|
||||
int nextWordStart = startFrom;
|
||||
while (true) {
|
||||
nextWordStart = NameUtil.nextWord(name, nextWordStart);
|
||||
if (nextWordStart >= name.length()) {
|
||||
return -1;
|
||||
}
|
||||
if (StringUtil.charsEqualIgnoreCase(p, name.charAt(nextWordStart))) {
|
||||
return nextWordStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MinusculeMatcher{" +
|
||||
|
||||
@@ -1,415 +1,415 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.codeStyle;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.util.text.StringUtilRt;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NameUtil {
|
||||
private static final Function<String,String> LOWERCASE_MAPPING = new Function<String, String>() {
|
||||
public String fun(final String s) {
|
||||
return s.toLowerCase();
|
||||
}
|
||||
};
|
||||
private static final int MAX_LENGTH = 40;
|
||||
|
||||
private NameUtil() {}
|
||||
|
||||
public static List<String> nameToWordsLowerCase(String name){
|
||||
return ContainerUtil.map(nameToWords(name), LOWERCASE_MAPPING);
|
||||
}
|
||||
|
||||
public static String[] nameToWords(String name){
|
||||
ArrayList<String> array = new ArrayList<String>();
|
||||
int index = 0;
|
||||
int wordStart;
|
||||
|
||||
while(index < name.length()){
|
||||
wordStart = index;
|
||||
int upperCaseCount = 0;
|
||||
int lowerCaseCount = 0;
|
||||
int digitCount = 0;
|
||||
int specialCount = 0;
|
||||
while(index < name.length()){
|
||||
char c = name.charAt(index);
|
||||
if (Character.isDigit(c)){
|
||||
if (upperCaseCount > 0 || lowerCaseCount > 0 || specialCount > 0) break;
|
||||
digitCount++;
|
||||
}
|
||||
else if (Character.isUpperCase(c)){
|
||||
if (lowerCaseCount > 0 || digitCount > 0 || specialCount > 0) break;
|
||||
upperCaseCount++;
|
||||
}
|
||||
else if (Character.isLowerCase(c)){
|
||||
if (digitCount > 0 || specialCount > 0) break;
|
||||
if (upperCaseCount > 1) {
|
||||
index--;
|
||||
break;
|
||||
}
|
||||
lowerCaseCount++;
|
||||
}
|
||||
else{
|
||||
if (upperCaseCount > 0 || lowerCaseCount > 0 || digitCount > 0) break;
|
||||
specialCount++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
String word = name.substring(wordStart, index);
|
||||
if (!StringUtil.isEmptyOrSpaces(word)) {
|
||||
array.add(word);
|
||||
}
|
||||
}
|
||||
return ArrayUtil.toStringArray(array);
|
||||
}
|
||||
|
||||
public static String buildRegexp(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower) {
|
||||
return buildRegexp(pattern, exactPrefixLen, allowToUpper, allowToLower, false, false);
|
||||
}
|
||||
|
||||
public static String buildRegexp(String pattern,
|
||||
int exactPrefixLen,
|
||||
boolean allowToUpper,
|
||||
boolean allowToLower,
|
||||
boolean lowerCaseWords,
|
||||
boolean forCompletion) {
|
||||
final int eol = pattern.indexOf('\n');
|
||||
if (eol != -1) {
|
||||
pattern = pattern.substring(0, eol);
|
||||
}
|
||||
if (pattern.length() >= MAX_LENGTH) {
|
||||
pattern = pattern.substring(0, MAX_LENGTH);
|
||||
}
|
||||
|
||||
@NonNls final StringBuilder buffer = new StringBuilder();
|
||||
boolean lastIsUppercase = false;
|
||||
boolean prevIsUppercase = false;
|
||||
final boolean endsWithSpace = !forCompletion && StringUtil.endsWithChar(pattern, ' ');
|
||||
if (!forCompletion) {
|
||||
pattern = pattern.trim();
|
||||
}
|
||||
exactPrefixLen = Math.min(exactPrefixLen, pattern.length());
|
||||
/*final boolean uppercaseOnly = containsOnlyUppercaseLetters(pattern.substring(exactPrefixLen));
|
||||
if (uppercaseOnly) {
|
||||
allowToLower = false;
|
||||
}*/
|
||||
if (exactPrefixLen > 0) {
|
||||
char c = pattern.charAt(exactPrefixLen - 1);
|
||||
prevIsUppercase = Character.isUpperCase(c) || Character.isDigit(c);
|
||||
}
|
||||
|
||||
for (int i = 0; i != exactPrefixLen; ++i) {
|
||||
final char c = pattern.charAt(i);
|
||||
if (Character.isLetterOrDigit(c)) {
|
||||
buffer.append(c);
|
||||
}
|
||||
else {
|
||||
// for standard RegExp engine
|
||||
// buffer.append("\\u");
|
||||
// buffer.append(Integer.toHexString(c + 0x20000).substring(1));
|
||||
|
||||
// for OROMATCHER RegExp engine
|
||||
buffer.append("\\").append(c);
|
||||
//buffer.append(Integer.toHexString(c + 0x20000).substring(2));
|
||||
}
|
||||
}
|
||||
|
||||
if (exactPrefixLen == 0) {
|
||||
buffer.append("_*"); // ignore leading underscores
|
||||
}
|
||||
|
||||
boolean firstIdentifierLetter = (exactPrefixLen == 0);
|
||||
//System.out.println("pattern = " + pattern);
|
||||
for (int i = exactPrefixLen; i < pattern.length(); i++) {
|
||||
final char c = pattern.charAt(i);
|
||||
lastIsUppercase = false;
|
||||
if (Character.isLetterOrDigit(c)) {
|
||||
prevIsUppercase = false;
|
||||
|
||||
// This logic allows to use uppercase letters only to catch the name like PDM for PsiDocumentManager
|
||||
if (Character.isUpperCase(c) || Character.isDigit(c)) {
|
||||
prevIsUppercase = true;
|
||||
lastIsUppercase = true;
|
||||
|
||||
buffer.append('(');
|
||||
|
||||
if (!firstIdentifierLetter) {
|
||||
buffer.append("[a-z\\s0-9\\$]*");
|
||||
}
|
||||
|
||||
buffer.append(c);
|
||||
if (allowToLower) {
|
||||
buffer.append('|');
|
||||
buffer.append(Character.toLowerCase(c));
|
||||
}
|
||||
if (!firstIdentifierLetter) {
|
||||
buffer.append("|[A-Za-z\\s0-9\\$]*[_-]+[");
|
||||
buffer.append(c);
|
||||
buffer.append(Character.toLowerCase(c));
|
||||
buffer.append("]");
|
||||
}
|
||||
buffer.append(')');
|
||||
}
|
||||
else if (Character.isLowerCase(c) && allowToUpper) {
|
||||
buffer.append('[');
|
||||
buffer.append(c);
|
||||
buffer.append(Character.toUpperCase(c));
|
||||
buffer.append(']');
|
||||
if (lowerCaseWords) {
|
||||
buffer.append("([a-z\\s0-9\\$]*[-_]+)?");
|
||||
}
|
||||
}
|
||||
else {
|
||||
buffer.append(c);
|
||||
}
|
||||
|
||||
firstIdentifierLetter = false;
|
||||
}
|
||||
else if (c == '*') {
|
||||
buffer.append(".*");
|
||||
firstIdentifierLetter = true;
|
||||
}
|
||||
else if (c == '.') {
|
||||
if (!firstIdentifierLetter) {
|
||||
buffer.append("[a-z\\s0-9\\$]*\\.");
|
||||
}
|
||||
else {
|
||||
buffer.append("\\.");
|
||||
}
|
||||
firstIdentifierLetter = true;
|
||||
}
|
||||
else if (c == ' ') {
|
||||
buffer.append("([a-z\\s0-9\\$_-]*[\\ _-]+)+");
|
||||
firstIdentifierLetter = true;
|
||||
}
|
||||
else {
|
||||
if (c == ':' || prevIsUppercase) {
|
||||
buffer.append("[A-Za-z\\s0-9\\$]*");
|
||||
}
|
||||
|
||||
firstIdentifierLetter = true;
|
||||
// for standard RegExp engine
|
||||
// buffer.append("\\u");
|
||||
// buffer.append(Integer.toHexString(c + 0x20000).substring(1));
|
||||
|
||||
// for OROMATCHER RegExp engine
|
||||
buffer.append("\\").append(c);
|
||||
//buffer.append(Integer.toHexString(c + 0x20000).substring(3));
|
||||
}
|
||||
}
|
||||
|
||||
if (!endsWithSpace) {
|
||||
buffer.append(".*");
|
||||
}
|
||||
else if (lastIsUppercase) {
|
||||
buffer.append("[a-z\\s0-9\\$]*");
|
||||
}
|
||||
|
||||
//System.out.println("rx = " + buffer.toString());
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits an identifier into words, separated with underscores or upper-case characters
|
||||
* (camel-case).
|
||||
*
|
||||
* @param name the identifier to split.
|
||||
* @return the array of strings into which the identifier has been split.
|
||||
*/
|
||||
public static String[] splitNameIntoWords(@NotNull String name) {
|
||||
final String[] underlineDelimited = name.split("_");
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (String word : underlineDelimited) {
|
||||
addAllWords(word, result);
|
||||
}
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
public static List<String> getSuggestionsByName(String name,
|
||||
String prefix,
|
||||
String suffix,
|
||||
boolean upperCaseStyle,
|
||||
boolean preferLongerNames, boolean isArray) {
|
||||
ArrayList<String> answer = new ArrayList<String>();
|
||||
String[] words = nameToWords(name);
|
||||
|
||||
for (int step = 0; step < words.length; step++) {
|
||||
int wordCount = preferLongerNames ? words.length - step : step + 1;
|
||||
|
||||
String startWord = words[words.length - wordCount];
|
||||
char c = startWord.charAt(0);
|
||||
if( c == '_' || !Character.isJavaIdentifierStart( c ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
answer.add(compoundSuggestion(prefix, upperCaseStyle, words, wordCount, startWord, c, isArray, false) + suffix);
|
||||
answer.add(compoundSuggestion(prefix, upperCaseStyle, words, wordCount, startWord, c, isArray, true) + suffix);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
private static String compoundSuggestion(String prefix,
|
||||
boolean upperCaseStyle,
|
||||
String[] words,
|
||||
int wordCount,
|
||||
String startWord,
|
||||
char c,
|
||||
boolean isArray,
|
||||
boolean skip_) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
buffer.append(prefix);
|
||||
|
||||
if (upperCaseStyle) {
|
||||
startWord = StringUtilRt.toUpperCase(startWord);
|
||||
}
|
||||
else {
|
||||
if (prefix.length() == 0 || StringUtil.endsWithChar(prefix, '_')) {
|
||||
startWord = startWord.toLowerCase();
|
||||
}
|
||||
else {
|
||||
startWord = Character.toUpperCase(c) + startWord.substring(1);
|
||||
}
|
||||
}
|
||||
buffer.append(startWord);
|
||||
|
||||
for (int i = words.length - wordCount + 1; i < words.length; i++) {
|
||||
String word = words[i];
|
||||
String prevWord = words[i - 1];
|
||||
if (upperCaseStyle) {
|
||||
word = StringUtilRt.toUpperCase(word);
|
||||
if (prevWord.charAt(prevWord.length() - 1) != '_' && word.charAt(0) != '_') {
|
||||
word = "_" + word;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (prevWord.charAt(prevWord.length() - 1) == '_') {
|
||||
word = word.toLowerCase();
|
||||
}
|
||||
|
||||
if (skip_) {
|
||||
if (word.equals("_")) continue;
|
||||
if (prevWord.equals("_")) {
|
||||
word = StringUtil.capitalize(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer.append(word);
|
||||
}
|
||||
|
||||
String suggestion = buffer.toString();
|
||||
if (isArray) {
|
||||
suggestion = StringUtil.pluralize(suggestion);
|
||||
if (upperCaseStyle) {
|
||||
suggestion = StringUtilRt.toUpperCase(suggestion);
|
||||
}
|
||||
}
|
||||
return suggestion;
|
||||
}
|
||||
|
||||
static boolean isWordStart(String text, int i) {
|
||||
if (isWordStart(text.charAt(i))) {
|
||||
return true;
|
||||
}
|
||||
if (!Character.isLetterOrDigit(text.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
if (i > 0 && (isWordSeparator(text.charAt(i - 1)) || text.charAt(i - 1) == '.')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean isWordStart(char p) {
|
||||
return Character.isUpperCase(p) || Character.isDigit(p);
|
||||
}
|
||||
|
||||
static int nextWord(String text, int start) {
|
||||
if (!Character.isLetterOrDigit(text.charAt(start))) {
|
||||
return start + 1;
|
||||
}
|
||||
|
||||
int i = start;
|
||||
while (i < text.length() && isWordStart(text, i)) {
|
||||
i++;
|
||||
}
|
||||
if (i > start + 1) {
|
||||
if (i == text.length() || !Character.isLetterOrDigit(text.charAt(i))) {
|
||||
return i;
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
while (i < text.length() && !isWordStart(text, i) && Character.isLetterOrDigit(text.charAt(i))) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private static void addAllWords(String text, List<String> result) {
|
||||
int start = 0;
|
||||
while (start < text.length()) {
|
||||
int next = nextWord(text, start);
|
||||
result.add(text.substring(start, next));
|
||||
start = next;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isWordSeparator(char c) {
|
||||
return Character.isWhitespace(c) || c == '_' || c == '-' || c == ':';
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use com.intellij.util.text.Matcher
|
||||
*/
|
||||
public interface Matcher {
|
||||
boolean matches(String name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
@Deprecated
|
||||
public static com.intellij.util.text.Matcher buildCompletionMatcher(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower) {
|
||||
MatchingCaseSensitivity options = !allowToLower && !allowToUpper ? MatchingCaseSensitivity.ALL : exactPrefixLen > 0 ? MatchingCaseSensitivity.FIRST_LETTER : MatchingCaseSensitivity.NONE;
|
||||
return buildMatcher(pattern, options);
|
||||
}
|
||||
|
||||
public static com.intellij.util.text.Matcher buildMatcher(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower) {
|
||||
MatchingCaseSensitivity options = !allowToLower && !allowToUpper ? MatchingCaseSensitivity.ALL : exactPrefixLen > 0 ? MatchingCaseSensitivity.FIRST_LETTER : MatchingCaseSensitivity.NONE;
|
||||
return buildMatcher(pattern, options);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
@Deprecated
|
||||
public static com.intellij.util.text.Matcher buildMatcher(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower, boolean lowerCaseWords) {
|
||||
MatchingCaseSensitivity options = !allowToLower && !allowToUpper ? MatchingCaseSensitivity.ALL : exactPrefixLen > 0 ? MatchingCaseSensitivity.FIRST_LETTER : MatchingCaseSensitivity.NONE;
|
||||
return buildMatcher(pattern, options);
|
||||
}
|
||||
|
||||
public static MinusculeMatcher buildMatcher(final String pattern, MatchingCaseSensitivity options) {
|
||||
return new MinusculeMatcher(pattern, options);
|
||||
}
|
||||
|
||||
public enum MatchingCaseSensitivity {
|
||||
NONE, FIRST_LETTER, ALL
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.codeStyle;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.util.text.StringUtilRt;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NameUtil {
|
||||
private static final Function<String,String> LOWERCASE_MAPPING = new Function<String, String>() {
|
||||
public String fun(final String s) {
|
||||
return s.toLowerCase();
|
||||
}
|
||||
};
|
||||
private static final int MAX_LENGTH = 40;
|
||||
|
||||
private NameUtil() {}
|
||||
|
||||
public static List<String> nameToWordsLowerCase(String name){
|
||||
return ContainerUtil.map(nameToWords(name), LOWERCASE_MAPPING);
|
||||
}
|
||||
|
||||
public static String[] nameToWords(String name){
|
||||
ArrayList<String> array = new ArrayList<String>();
|
||||
int index = 0;
|
||||
int wordStart;
|
||||
|
||||
while(index < name.length()){
|
||||
wordStart = index;
|
||||
int upperCaseCount = 0;
|
||||
int lowerCaseCount = 0;
|
||||
int digitCount = 0;
|
||||
int specialCount = 0;
|
||||
while(index < name.length()){
|
||||
char c = name.charAt(index);
|
||||
if (Character.isDigit(c)){
|
||||
if (upperCaseCount > 0 || lowerCaseCount > 0 || specialCount > 0) break;
|
||||
digitCount++;
|
||||
}
|
||||
else if (Character.isUpperCase(c)){
|
||||
if (lowerCaseCount > 0 || digitCount > 0 || specialCount > 0) break;
|
||||
upperCaseCount++;
|
||||
}
|
||||
else if (Character.isLowerCase(c)){
|
||||
if (digitCount > 0 || specialCount > 0) break;
|
||||
if (upperCaseCount > 1) {
|
||||
index--;
|
||||
break;
|
||||
}
|
||||
lowerCaseCount++;
|
||||
}
|
||||
else{
|
||||
if (upperCaseCount > 0 || lowerCaseCount > 0 || digitCount > 0) break;
|
||||
specialCount++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
String word = name.substring(wordStart, index);
|
||||
if (!StringUtil.isEmptyOrSpaces(word)) {
|
||||
array.add(word);
|
||||
}
|
||||
}
|
||||
return ArrayUtil.toStringArray(array);
|
||||
}
|
||||
|
||||
public static String buildRegexp(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower) {
|
||||
return buildRegexp(pattern, exactPrefixLen, allowToUpper, allowToLower, false, false);
|
||||
}
|
||||
|
||||
public static String buildRegexp(String pattern,
|
||||
int exactPrefixLen,
|
||||
boolean allowToUpper,
|
||||
boolean allowToLower,
|
||||
boolean lowerCaseWords,
|
||||
boolean forCompletion) {
|
||||
final int eol = pattern.indexOf('\n');
|
||||
if (eol != -1) {
|
||||
pattern = pattern.substring(0, eol);
|
||||
}
|
||||
if (pattern.length() >= MAX_LENGTH) {
|
||||
pattern = pattern.substring(0, MAX_LENGTH);
|
||||
}
|
||||
|
||||
@NonNls final StringBuilder buffer = new StringBuilder();
|
||||
boolean lastIsUppercase = false;
|
||||
boolean prevIsUppercase = false;
|
||||
final boolean endsWithSpace = !forCompletion && StringUtil.endsWithChar(pattern, ' ');
|
||||
if (!forCompletion) {
|
||||
pattern = pattern.trim();
|
||||
}
|
||||
exactPrefixLen = Math.min(exactPrefixLen, pattern.length());
|
||||
/*final boolean uppercaseOnly = containsOnlyUppercaseLetters(pattern.substring(exactPrefixLen));
|
||||
if (uppercaseOnly) {
|
||||
allowToLower = false;
|
||||
}*/
|
||||
if (exactPrefixLen > 0) {
|
||||
char c = pattern.charAt(exactPrefixLen - 1);
|
||||
prevIsUppercase = Character.isUpperCase(c) || Character.isDigit(c);
|
||||
}
|
||||
|
||||
for (int i = 0; i != exactPrefixLen; ++i) {
|
||||
final char c = pattern.charAt(i);
|
||||
if (Character.isLetterOrDigit(c)) {
|
||||
buffer.append(c);
|
||||
}
|
||||
else {
|
||||
// for standard RegExp engine
|
||||
// buffer.append("\\u");
|
||||
// buffer.append(Integer.toHexString(c + 0x20000).substring(1));
|
||||
|
||||
// for OROMATCHER RegExp engine
|
||||
buffer.append("\\").append(c);
|
||||
//buffer.append(Integer.toHexString(c + 0x20000).substring(2));
|
||||
}
|
||||
}
|
||||
|
||||
if (exactPrefixLen == 0) {
|
||||
buffer.append("_*"); // ignore leading underscores
|
||||
}
|
||||
|
||||
boolean firstIdentifierLetter = (exactPrefixLen == 0);
|
||||
//System.out.println("pattern = " + pattern);
|
||||
for (int i = exactPrefixLen; i < pattern.length(); i++) {
|
||||
final char c = pattern.charAt(i);
|
||||
lastIsUppercase = false;
|
||||
if (Character.isLetterOrDigit(c)) {
|
||||
prevIsUppercase = false;
|
||||
|
||||
// This logic allows to use uppercase letters only to catch the name like PDM for PsiDocumentManager
|
||||
if (Character.isUpperCase(c) || Character.isDigit(c)) {
|
||||
prevIsUppercase = true;
|
||||
lastIsUppercase = true;
|
||||
|
||||
buffer.append('(');
|
||||
|
||||
if (!firstIdentifierLetter) {
|
||||
buffer.append("[a-z\\s0-9\\$]*");
|
||||
}
|
||||
|
||||
buffer.append(c);
|
||||
if (allowToLower) {
|
||||
buffer.append('|');
|
||||
buffer.append(Character.toLowerCase(c));
|
||||
}
|
||||
if (!firstIdentifierLetter) {
|
||||
buffer.append("|[A-Za-z\\s0-9\\$]*[_-]+[");
|
||||
buffer.append(c);
|
||||
buffer.append(Character.toLowerCase(c));
|
||||
buffer.append("]");
|
||||
}
|
||||
buffer.append(')');
|
||||
}
|
||||
else if (Character.isLowerCase(c) && allowToUpper) {
|
||||
buffer.append('[');
|
||||
buffer.append(c);
|
||||
buffer.append(Character.toUpperCase(c));
|
||||
buffer.append(']');
|
||||
if (lowerCaseWords) {
|
||||
buffer.append("([a-z\\s0-9\\$]*[-_]+)?");
|
||||
}
|
||||
}
|
||||
else {
|
||||
buffer.append(c);
|
||||
}
|
||||
|
||||
firstIdentifierLetter = false;
|
||||
}
|
||||
else if (c == '*') {
|
||||
buffer.append(".*");
|
||||
firstIdentifierLetter = true;
|
||||
}
|
||||
else if (c == '.') {
|
||||
if (!firstIdentifierLetter) {
|
||||
buffer.append("[a-z\\s0-9\\$]*\\.");
|
||||
}
|
||||
else {
|
||||
buffer.append("\\.");
|
||||
}
|
||||
firstIdentifierLetter = true;
|
||||
}
|
||||
else if (c == ' ') {
|
||||
buffer.append("([a-z\\s0-9\\$_-]*[\\ _-]+)+");
|
||||
firstIdentifierLetter = true;
|
||||
}
|
||||
else {
|
||||
if (c == ':' || prevIsUppercase) {
|
||||
buffer.append("[A-Za-z\\s0-9\\$]*");
|
||||
}
|
||||
|
||||
firstIdentifierLetter = true;
|
||||
// for standard RegExp engine
|
||||
// buffer.append("\\u");
|
||||
// buffer.append(Integer.toHexString(c + 0x20000).substring(1));
|
||||
|
||||
// for OROMATCHER RegExp engine
|
||||
buffer.append("\\").append(c);
|
||||
//buffer.append(Integer.toHexString(c + 0x20000).substring(3));
|
||||
}
|
||||
}
|
||||
|
||||
if (!endsWithSpace) {
|
||||
buffer.append(".*");
|
||||
}
|
||||
else if (lastIsUppercase) {
|
||||
buffer.append("[a-z\\s0-9\\$]*");
|
||||
}
|
||||
|
||||
//System.out.println("rx = " + buffer.toString());
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits an identifier into words, separated with underscores or upper-case characters
|
||||
* (camel-case).
|
||||
*
|
||||
* @param name the identifier to split.
|
||||
* @return the array of strings into which the identifier has been split.
|
||||
*/
|
||||
public static String[] splitNameIntoWords(@NotNull String name) {
|
||||
final String[] underlineDelimited = name.split("_");
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (String word : underlineDelimited) {
|
||||
addAllWords(word, result);
|
||||
}
|
||||
return ArrayUtil.toStringArray(result);
|
||||
}
|
||||
|
||||
public static List<String> getSuggestionsByName(String name,
|
||||
String prefix,
|
||||
String suffix,
|
||||
boolean upperCaseStyle,
|
||||
boolean preferLongerNames, boolean isArray) {
|
||||
ArrayList<String> answer = new ArrayList<String>();
|
||||
String[] words = nameToWords(name);
|
||||
|
||||
for (int step = 0; step < words.length; step++) {
|
||||
int wordCount = preferLongerNames ? words.length - step : step + 1;
|
||||
|
||||
String startWord = words[words.length - wordCount];
|
||||
char c = startWord.charAt(0);
|
||||
if( c == '_' || !Character.isJavaIdentifierStart( c ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
answer.add(compoundSuggestion(prefix, upperCaseStyle, words, wordCount, startWord, c, isArray, false) + suffix);
|
||||
answer.add(compoundSuggestion(prefix, upperCaseStyle, words, wordCount, startWord, c, isArray, true) + suffix);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
private static String compoundSuggestion(String prefix,
|
||||
boolean upperCaseStyle,
|
||||
String[] words,
|
||||
int wordCount,
|
||||
String startWord,
|
||||
char c,
|
||||
boolean isArray,
|
||||
boolean skip_) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
buffer.append(prefix);
|
||||
|
||||
if (upperCaseStyle) {
|
||||
startWord = StringUtilRt.toUpperCase(startWord);
|
||||
}
|
||||
else {
|
||||
if (prefix.length() == 0 || StringUtil.endsWithChar(prefix, '_')) {
|
||||
startWord = startWord.toLowerCase();
|
||||
}
|
||||
else {
|
||||
startWord = Character.toUpperCase(c) + startWord.substring(1);
|
||||
}
|
||||
}
|
||||
buffer.append(startWord);
|
||||
|
||||
for (int i = words.length - wordCount + 1; i < words.length; i++) {
|
||||
String word = words[i];
|
||||
String prevWord = words[i - 1];
|
||||
if (upperCaseStyle) {
|
||||
word = StringUtilRt.toUpperCase(word);
|
||||
if (prevWord.charAt(prevWord.length() - 1) != '_' && word.charAt(0) != '_') {
|
||||
word = "_" + word;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (prevWord.charAt(prevWord.length() - 1) == '_') {
|
||||
word = word.toLowerCase();
|
||||
}
|
||||
|
||||
if (skip_) {
|
||||
if (word.equals("_")) continue;
|
||||
if (prevWord.equals("_")) {
|
||||
word = StringUtil.capitalize(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer.append(word);
|
||||
}
|
||||
|
||||
String suggestion = buffer.toString();
|
||||
if (isArray) {
|
||||
suggestion = StringUtil.pluralize(suggestion);
|
||||
if (upperCaseStyle) {
|
||||
suggestion = StringUtilRt.toUpperCase(suggestion);
|
||||
}
|
||||
}
|
||||
return suggestion;
|
||||
}
|
||||
|
||||
static boolean isWordStart(String text, int i) {
|
||||
if (isWordStart(text.charAt(i))) {
|
||||
return true;
|
||||
}
|
||||
if (!Character.isLetterOrDigit(text.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
if (i == 0 || !Character.isLetterOrDigit(text.charAt(i - 1))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean isWordStart(char p) {
|
||||
return Character.isUpperCase(p) || Character.isDigit(p);
|
||||
}
|
||||
|
||||
static int nextWord(String text, int start) {
|
||||
if (!Character.isLetterOrDigit(text.charAt(start))) {
|
||||
return start + 1;
|
||||
}
|
||||
|
||||
int i = start;
|
||||
while (i < text.length() && isWordStart(text, i)) {
|
||||
i++;
|
||||
}
|
||||
if (i > start + 1) {
|
||||
if (i == text.length() || !Character.isLetterOrDigit(text.charAt(i))) {
|
||||
return i;
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
while (i < text.length() && !isWordStart(text, i) && Character.isLetterOrDigit(text.charAt(i))) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private static void addAllWords(String text, List<String> result) {
|
||||
int start = 0;
|
||||
while (start < text.length()) {
|
||||
int next = nextWord(text, start);
|
||||
result.add(text.substring(start, next));
|
||||
start = next;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isWordSeparator(char c) {
|
||||
return Character.isWhitespace(c) || c == '_' || c == '-' || c == ':';
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use com.intellij.util.text.Matcher
|
||||
*/
|
||||
public interface Matcher {
|
||||
boolean matches(String name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
@Deprecated
|
||||
public static com.intellij.util.text.Matcher buildCompletionMatcher(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower) {
|
||||
MatchingCaseSensitivity options = !allowToLower && !allowToUpper ? MatchingCaseSensitivity.ALL : exactPrefixLen > 0 ? MatchingCaseSensitivity.FIRST_LETTER : MatchingCaseSensitivity.NONE;
|
||||
return buildMatcher(pattern, options);
|
||||
}
|
||||
|
||||
public static com.intellij.util.text.Matcher buildMatcher(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower) {
|
||||
MatchingCaseSensitivity options = !allowToLower && !allowToUpper ? MatchingCaseSensitivity.ALL : exactPrefixLen > 0 ? MatchingCaseSensitivity.FIRST_LETTER : MatchingCaseSensitivity.NONE;
|
||||
return buildMatcher(pattern, options);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
@Deprecated
|
||||
public static com.intellij.util.text.Matcher buildMatcher(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower, boolean lowerCaseWords) {
|
||||
MatchingCaseSensitivity options = !allowToLower && !allowToUpper ? MatchingCaseSensitivity.ALL : exactPrefixLen > 0 ? MatchingCaseSensitivity.FIRST_LETTER : MatchingCaseSensitivity.NONE;
|
||||
return buildMatcher(pattern, options);
|
||||
}
|
||||
|
||||
public static MinusculeMatcher buildMatcher(final String pattern, MatchingCaseSensitivity options) {
|
||||
return new MinusculeMatcher(pattern, options);
|
||||
}
|
||||
|
||||
public enum MatchingCaseSensitivity {
|
||||
NONE, FIRST_LETTER, ALL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
|
||||
}
|
||||
|
||||
public void testIdCompletion2() throws Throwable {
|
||||
doTestCompletionVariants("idcompl2.xml", "@android:id/text1", "@android:id/text2");
|
||||
doTestCompletionVariants("idcompl2.xml", "@android:id/text1", "@android:id/text2", "@android:id/inputExtractEditText", "@android:id/startSelectingText", "@android:id/stopSelectingText");
|
||||
}
|
||||
|
||||
public void testIdHighlighting() throws Throwable {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.android.dom;
|
||||
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
@@ -72,7 +73,11 @@ public class AndroidValueResourcesTest extends AndroidDomTest {
|
||||
}
|
||||
|
||||
public void testStyles2() throws Throwable {
|
||||
toTestCompletion("styles2.xml", "styles2_after.xml");
|
||||
VirtualFile file = copyFileToProject("styles2.xml");
|
||||
myFixture.configureFromExistingVirtualFile(file);
|
||||
myFixture.complete(CompletionType.BASIC);
|
||||
myFixture.type('\n');
|
||||
myFixture.checkResultByFile(testFolder + '/' + "styles2_after.xml");
|
||||
}
|
||||
|
||||
public void testStyles3() throws Throwable {
|
||||
@@ -155,7 +160,11 @@ public class AndroidValueResourcesTest extends AndroidDomTest {
|
||||
}
|
||||
|
||||
public void testStylesAttrNameWithoutPrefix() throws Throwable {
|
||||
doTestCompletion();
|
||||
VirtualFile file = copyFileToProject(getTestName(true) + ".xml");
|
||||
myFixture.configureFromExistingVirtualFile(file);
|
||||
myFixture.complete(CompletionType.BASIC);
|
||||
myFixture.type('\n');
|
||||
myFixture.checkResultByFile(testFolder + '/' + getTestName(true) + "_after.xml");
|
||||
}
|
||||
|
||||
public void testMoreTypes() throws Throwable {
|
||||
|
||||
+6
-1
@@ -76,7 +76,12 @@ class GrCompletionWithLibraryTest extends GroovyCompletionTestBase {
|
||||
public void testInjectMethodForMap() throws Throwable {doBasicTest();}
|
||||
public void testClosureDefaultParameterInEachMethod() throws Throwable {doBasicTest();}
|
||||
public void testEachMethodForRanges() throws Throwable {doBasicTest();}
|
||||
public void testEachMethodForEnumRanges() throws Throwable {doBasicTest();}
|
||||
public void testEachMethodForEnumRanges() throws Throwable {
|
||||
myFixture.configureByFile(getTestName(false) + ".groovy")
|
||||
myFixture.completeBasic()
|
||||
myFixture.type('\n')
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.groovy");
|
||||
}
|
||||
|
||||
public void testPrintlnSpace() { checkCompletion 'print<caret>', 'l ', "println <caret>" }
|
||||
public void testHashCodeSpace() { checkCompletion 'if ("".h<caret>', ' ', 'if ("".hashCode() <caret>' }
|
||||
|
||||
@@ -4,5 +4,6 @@ public String fooooo(){}
|
||||
|
||||
MyClass.fo<caret>
|
||||
-----
|
||||
findIndexOf
|
||||
forName
|
||||
forName
|
||||
@@ -284,6 +284,7 @@ public class XmlCompletionTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testEntityRefCompletion2() throws Exception {
|
||||
configureByFiles("28.xml", "28.ent");
|
||||
complete();
|
||||
type('\n');
|
||||
checkResultByFile("28_after.xml");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user