diff --git a/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java b/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java index 553f735cc05..db62e45c1d3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java @@ -15,12 +15,12 @@ public final class QualifiedNamesUtil { return subpackageName.equals(packageName) || (subpackageName.startsWith(packageName) && subpackageName.charAt(packageName.length()) == '.'); } - + public static boolean isShortNameForFQN(@NotNull final String name, @NotNull final String fqn) { return fqn.equals(name) || (fqn.endsWith(name) && fqn.charAt(fqn.length() - name.length() - 1) == '.'); } - + public static boolean isOneSegmentFQN(@NotNull final String fqn) { if (fqn.isEmpty()) { return false; @@ -30,14 +30,20 @@ public final class QualifiedNamesUtil { } @NotNull - public static String fqnToShortName(@NotNull String fqName) { - int lastDotIndex = fqName.lastIndexOf('.'); + public static String fqnToShortName(@NotNull String fqn) { + return getLastSegment(fqn); + } - if (lastDotIndex != -1) { - return fqName.substring(lastDotIndex + 1, fqName.length()); - } + @NotNull + public static String getLastSegment(@NotNull String fqn) { + int lastDotIndex = fqn.lastIndexOf('.'); + return (lastDotIndex != -1) ? fqn.substring(lastDotIndex + 1, fqn.length()) : fqn; + } - return fqName; + @NotNull + public static String getFirstSegment(@NotNull String fqn) { + int dotIndex = fqn.indexOf('.'); + return (dotIndex != -1) ? fqn.substring(0, dotIndex) : fqn; } @NotNull @@ -55,17 +61,43 @@ public final class QualifiedNamesUtil { return first + "." + second; } -// private static String subPackageName(String packageName, String packageFQN) { -// if (!isInPackage(packageName, packageFQN)) { -// return null; -// } -// -// int nextDotIndex = packageFQN.indexOf('.', (packageName + ".").length()); -// -// if (nextDotIndex != -1) { -// return packageFQN.substring((packageName + ".").length(), nextDotIndex); -// } -// -// return packageFQN.substring((packageName + ".").length()); -// } -} + /** + * Get tail part of the full fqn by subtracting head part. + * + * @param headFQN + * @param fullFQN + * @return tail fqn. If first part is not a begging of the full fqn, fullFQN will be returned. + */ + @NotNull + public static String tail(@NotNull String headFQN, @NotNull String fullFQN) { + if (!isSubpackageOf(fullFQN, headFQN)) { + return fullFQN; + } + + return fullFQN.equals(headFQN) ? + "" : + fullFQN.substring(headFQN.length() + 1); // (headFQN + '.').length + } + + /** + * Add one segment of nesting to given qualified name according to the full qualified name. + * + * @param fqn + * @param fullFQN + * @return qualified name with one more segment or null if fqn is not head part of fullFQN or there's no additional segment. + */ + @Nullable + public static String plusOneSegment(String fqn, String fullFQN) { + if (!isSubpackageOf(fullFQN, fqn)) { + return null; + } + + final String nextSegment = getFirstSegment(tail(fqn, fullFQN)); + + if (isOneSegmentFQN(nextSegment)) { + return combine(fqn, nextSegment); + } + + return null; + } +} \ No newline at end of file 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 7cc206bb7f9..f747a8d878e 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 @@ -9,7 +9,6 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElementFinder; import com.intellij.psi.PsiManager; import com.intellij.psi.PsiPackage; -import com.intellij.psi.impl.file.PsiPackageImpl; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; @@ -142,7 +141,7 @@ public class JavaElementFinder extends PsiElementFinder { for (JetFile psiFile : psiFiles) { if (JetPsiUtil.getFQName(psiFile).startsWith(qualifiedName)) { - return new PsiPackageImpl(psiFile.getManager(), qualifiedName); + return new JetLightPackage(psiManager, qualifiedName); } } @@ -159,10 +158,9 @@ public class JavaElementFinder extends PsiElementFinder { for (JetFile psiFile : psiFiles) { String jetRootNamespace = JetPsiUtil.getFQName(psiFile); - if (QualifiedNamesUtil.isSubpackageOf(jetRootNamespace, psiPackage.getQualifiedName())) { - - // TODO: wrong package here - answer.add(new JetLightPackage(psiFile.getManager(), jetRootNamespace)); + final String subPackageFQN = QualifiedNamesUtil.plusOneSegment(psiPackage.getQualifiedName(), jetRootNamespace); + if (subPackageFQN != null) { + answer.add(new JetLightPackage(psiManager, subPackageFQN)); } } diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java index 890734b79a1..620e61ee72d 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.lang.resolve.java.JetJavaMirrorMarker; import org.jetbrains.jet.plugin.JetLanguage; +import org.jetbrains.jet.util.QualifiedNamesUtil; import javax.swing.*; import java.util.Collections; @@ -55,8 +56,7 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa @Override public String getName() { - int idx = qualifiedName.lastIndexOf('.'); - return idx > 0 ? qualifiedName.substring(idx + 1) : qualifiedName; + return QualifiedNamesUtil.fqnToShortName(qualifiedName); } @Override @@ -72,6 +72,7 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa @Override public PsiClass getDelegate() { if (delegate == null) { + // TODO: What is the reason for this? delegate = findClass(qualifiedName, getStub()); if (delegate == null) { delegate = findClass(qualifiedName, getStub()); diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightPackage.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightPackage.java index 23a52dae6dd..35fc246573b 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightPackage.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightPackage.java @@ -1,9 +1,12 @@ package org.jetbrains.jet.asJava; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.file.PsiPackageImpl; /** + * TODO: make more accurate wrapper + * * @author Nikolay Krasko */ public class JetLightPackage extends PsiPackageImpl { @@ -11,8 +14,14 @@ public class JetLightPackage extends PsiPackageImpl { super(manager, qualifiedName); } + @Override + public PsiElement copy() { + return new JetLightPackage(getManager(), getQualifiedName()); + } + @Override public boolean isValid() { - return true; + // TODO: invalidate properly + return super.isValid(); } } \ No newline at end of file diff --git a/idea/testData/completion/injava/JetSubpackage.java b/idea/testData/completion/injava/JetSubpackage.java index dc60afb32d7..68eb467baed 100644 --- a/idea/testData/completion/injava/JetSubpackage.java +++ b/idea/testData/completion/injava/JetSubpackage.java @@ -4,4 +4,8 @@ public class Testing { } } -// EXIST: jet \ No newline at end of file +// EXIST: jet1 +// ABSENT: jet2 + +// Only two proposals expected +// NUMBER: 1 \ No newline at end of file diff --git a/idea/testData/completion/injava/JetSubpackage.kt b/idea/testData/completion/injava/JetSubpackage.kt index 8d89bd510a1..430d85149cc 100644 --- a/idea/testData/completion/injava/JetSubpackage.kt +++ b/idea/testData/completion/injava/JetSubpackage.kt @@ -1,4 +1,4 @@ -package testing.jet +package testing.jet1.jet2 fun somefun() { } \ No newline at end of file