Proper checking for a qualified name

When i18n plugin is enabled, it looks for classes like "java.lang.Object...)" while highlighting annotations.xml

EA-43709 - IAE: NameUtils.requireIdentifier
This commit is contained in:
Andrey Breslav
2013-03-30 17:20:42 +04:00
parent 4c3f8ff633
commit d42a9f37a3
5 changed files with 59 additions and 11 deletions
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.name;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -70,12 +69,6 @@ public class FqName extends FqNameBase {
return qualifiedName.indexOf('<') < 0;
}
public static boolean isValid(@Nullable String qualifiedName) {
return qualifiedName != null &&
FqNameUnsafe.isValid(qualifiedName) &&
isValidAfterUnsafeCheck(qualifiedName);
}
@Override
@NotNull
public String getFqName() {
@@ -142,4 +142,36 @@ public final class QualifiedNamesUtil {
return isImported(alreadyImported, newImport.fqnPart());
}
public static boolean isValidJavaFqName(@Nullable String qualifiedName) {
if (qualifiedName == null) return false;
// Check that it is javaName(\.javaName)* or an empty string
class State {}
State BEGINNING = new State();
State MIDDLE = new State();
State AFTER_DOT = new State();
State state = BEGINNING;
int length = qualifiedName.length();
for (int i = 0; i < length; i++) {
char c = qualifiedName.charAt(i);
if (state == BEGINNING || state == AFTER_DOT) {
if (!Character.isJavaIdentifierPart(c)) return false;
state = MIDDLE;
}
else if (state == MIDDLE) {
if (c == '.') {
state = AFTER_DOT;
}
else if (!Character.isJavaIdentifierPart(c)) {
return false;
}
}
}
return state != AFTER_DOT;
}
}
@@ -35,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.java.JavaPsiFacadeKotlinHacks;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.util.QualifiedNamesUtil;
import java.util.Collection;
import java.util.List;
@@ -77,7 +78,7 @@ public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacade
@NotNull
@Override
public PsiClass[] findClasses(@NotNull String qualifiedNameString, @NotNull GlobalSearchScope scope) {
if (!FqName.isValid(qualifiedNameString)) {
if (!QualifiedNamesUtil.isValidJavaFqName(qualifiedNameString)) {
return PsiClass.EMPTY_ARRAY;
}
@@ -162,7 +163,7 @@ public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacade
@Override
public PsiPackage findPackage(@NotNull String qualifiedNameString) {
if (!FqName.isValid(qualifiedNameString)) {
if (!QualifiedNamesUtil.isValidJavaFqName(qualifiedNameString)) {
return null;
}
@@ -20,6 +20,7 @@ import com.google.common.collect.Lists;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.util.QualifiedNamesUtil;
import org.junit.Assert;
import org.junit.Test;
@@ -100,4 +101,25 @@ public class FqNameTest {
FqNameUnsafe fqName = new FqNameUnsafe("ru.yandex");
Assert.assertSame(fqName, fqName.toSafe().toUnsafe());
}
@Test
public void isValidJavaFqName() {
Assert.assertTrue(QualifiedNamesUtil.isValidJavaFqName(""));
Assert.assertTrue(QualifiedNamesUtil.isValidJavaFqName("a"));
Assert.assertTrue(QualifiedNamesUtil.isValidJavaFqName("1"));
Assert.assertTrue(QualifiedNamesUtil.isValidJavaFqName("a.a"));
Assert.assertTrue(QualifiedNamesUtil.isValidJavaFqName("org.jetbrains"));
Assert.assertTrue(QualifiedNamesUtil.isValidJavaFqName("$"));
Assert.assertTrue(QualifiedNamesUtil.isValidJavaFqName("org.A$B"));
Assert.assertFalse(QualifiedNamesUtil.isValidJavaFqName("."));
Assert.assertFalse(QualifiedNamesUtil.isValidJavaFqName(".."));
Assert.assertFalse(QualifiedNamesUtil.isValidJavaFqName("a."));
Assert.assertFalse(QualifiedNamesUtil.isValidJavaFqName(".a"));
Assert.assertFalse(QualifiedNamesUtil.isValidJavaFqName("a..b"));
Assert.assertFalse(QualifiedNamesUtil.isValidJavaFqName("a.b.."));
Assert.assertFalse(QualifiedNamesUtil.isValidJavaFqName("a.b."));
Assert.assertFalse(QualifiedNamesUtil.isValidJavaFqName("a.b...)"));
Assert.assertFalse(QualifiedNamesUtil.isValidJavaFqName("a.b.<special>"));
}
}
@@ -23,10 +23,10 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.plugin.completion.JetLookupObject;
import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper;
import org.jetbrains.jet.util.QualifiedNamesUtil;
// class ExplicitlyImportedWeigher extends ProximityWeigher {
public class JetExplicitlyImportedWeigher extends LookupElementWeigher {
@@ -55,7 +55,7 @@ public class JetExplicitlyImportedWeigher extends LookupElementWeigher {
if (descriptor != null) {
FqNameUnsafe fqName = DescriptorUtils.getFQName(descriptor);
// Invalid name can be met for class object descriptor: Test.MyTest.A.<no name provided>.testOther
if (FqName.isValid(fqName.toString())) {
if (QualifiedNamesUtil.isValidJavaFqName(fqName.toString())) {
ImportPath importPath = new ImportPath(fqName.toString());
if (ImportInsertHelper.doNeedImport(importPath, file)) {
return MyResult.notImported;