diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/name/FqName.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/name/FqName.java index d86ea9056cc..60cd3a837d9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/name/FqName.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/name/FqName.java @@ -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() { diff --git a/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java b/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java index 6af6b6446e1..be00e670556 100644 --- a/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java @@ -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; + } } diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java index 41239f5b720..ec8a6eb06dd 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JavaElementFinder.java @@ -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; } diff --git a/compiler/tests/org/jetbrains/jet/FqNameTest.java b/compiler/tests/org/jetbrains/jet/FqNameTest.java index 76475af4f00..9397ca49cee 100644 --- a/compiler/tests/org/jetbrains/jet/FqNameTest.java +++ b/compiler/tests/org/jetbrains/jet/FqNameTest.java @@ -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.")); + } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/weigher/JetExplicitlyImportedWeigher.java b/idea/src/org/jetbrains/jet/plugin/completion/weigher/JetExplicitlyImportedWeigher.java index 507e3007497..58c6e6a445c 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/weigher/JetExplicitlyImportedWeigher.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/weigher/JetExplicitlyImportedWeigher.java @@ -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..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;