diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/LazyResolveBasedCache.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/LazyResolveBasedCache.kt index dd8cfa658d7..cb196d569d1 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/LazyResolveBasedCache.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/LazyResolveBasedCache.kt @@ -26,15 +26,9 @@ import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils import org.jetbrains.kotlin.name.FqName import javax.inject.Inject import kotlin.properties.Delegates -import com.intellij.openapi.diagnostic.Logger import org.jetbrains.kotlin.name.tail -import org.jetbrains.kotlin.name.each public class LazyResolveBasedCache() : JavaResolverCache { - class object { - private val LOG = Logger.getInstance(javaClass()) - } - private var resolveSession by Delegates.notNull() private val traceBasedCache = TraceBasedJavaResolverCache() @@ -89,4 +83,11 @@ public class LazyResolveBasedCache() : JavaResolverCache { return result } + + tailRecursive + private fun FqName.each(operation: (FqName) -> Boolean) { + if (operation(this) && !isRoot()) { + parent().each(operation) + } + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSessionUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSessionUtils.java index 3d7d3ce328a..684c6c92f5a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSessionUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSessionUtils.java @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.scopes.JetScope; import java.util.Collection; import java.util.Collections; +import java.util.List; public class ResolveSessionUtils { @@ -105,15 +106,16 @@ public class ResolveSessionUtils { return null; } - Name firstName = NamePackage.getFirstSegment(path); + List pathSegments = path.pathSegments(); + Name firstName = pathSegments.get(0); - // Search in internal class ClassifierDescriptor classifier = jetScope.getClassifier(firstName); if (classifier instanceof ClassDescriptor) { return findByQualifiedName( ((ClassDescriptor) classifier).getUnsubstitutedInnerClassesScope(), - NamePackage.withoutFirstSegment(path), - filter); + new FqName(path.asString().substring(firstName.asString().length() + 1)), + filter + ); } // TODO: search in class object diff --git a/core/descriptors/src/org/jetbrains/kotlin/name/FqNamesUtil.kt b/core/descriptors/src/org/jetbrains/kotlin/name/FqNamesUtil.kt index 988d99d0f36..f0ddfb20632 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/name/FqNamesUtil.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/name/FqNamesUtil.kt @@ -16,8 +16,6 @@ package org.jetbrains.kotlin.name -import org.jetbrains.kotlin.resolve.ImportPath - public fun FqName.isSubpackageOf(packageName: FqName): Boolean { return when { this == packageName -> true @@ -26,56 +24,36 @@ public fun FqName.isSubpackageOf(packageName: FqName): Boolean { } } -public fun FqName.isParent(child: FqName): Boolean = child.isSubpackageOf(this) +private fun isSubpackageOf(subpackageNameStr: String, packageNameStr: String): Boolean { + return subpackageNameStr.startsWith(packageNameStr) && subpackageNameStr[packageNameStr.length()] == '.' +} public fun FqName.isOneSegmentFQN(): Boolean = !isRoot() && parent().isRoot() -public fun FqName.withoutFirstSegment(): FqName { - if (isRoot() || parent().isRoot()) return FqName.ROOT - - val fqNameStr = asString() - return FqName(fqNameStr.substring(fqNameStr.indexOf('.') + 1, fqNameStr.length())) -} - -public fun FqName.numberOfSegments(): Int { - return if (isRoot()) 0 else 1 + parent().numberOfSegments() -} - /** - * Get tail part of the full fqn by subtracting head part. + * Get the tail part of the FQ name by stripping a prefix. If FQ name does not begin with the given prefix, it will be returned as is. * - * @param headFQN - * @return tail fqn. If first part is not a begging of the full fqn, fullFQN will be returned. + * Examples: + * "org.jetbrains.kotlin".tail("org") = "jetbrains.kotlin" + * "org.jetbrains.kotlin".tail("") = "org.jetbrains.kotlin" + * "org.jetbrains.kotlin".tail("org.jetbrains.kotlin") = "" + * "org.jetbrains.kotlin".tail("org.jetbrains.gogland") = "org.jetbrains.kotlin" */ -public fun FqName.tail(headFQN: FqName): FqName { +public fun FqName.tail(prefix: FqName): FqName { return when { - !isSubpackageOf(headFQN) || headFQN.isRoot() -> this - this == headFQN -> FqName.ROOT - else -> FqName(asString().substring(headFQN.asString().length + 1)) + !isSubpackageOf(prefix) || prefix.isRoot() -> this + this == prefix -> FqName.ROOT + else -> FqName(asString().substring(prefix.asString().length() + 1)) } } -public fun FqName.isImported(importPath: ImportPath, skipAliasedImports: Boolean = true): Boolean { - return when { - skipAliasedImports && importPath.hasAlias() -> false - importPath.isAllUnder() && !isRoot() -> importPath.fqnPart() == this.parent() - else -> importPath.fqnPart() == this - } -} - -public fun ImportPath.isImported(alreadyImported: ImportPath): Boolean { - return if (isAllUnder() || hasAlias()) this == alreadyImported else fqnPart().isImported(alreadyImported) -} - -public fun ImportPath.isImported(imports: Iterable): Boolean = imports.any { isImported(it) } - -// Check that it is javaName(\.javaName)* or an empty string private enum class State { BEGINNING MIDDLE AFTER_DOT } +// Check that it is javaName(\.javaName)* or an empty string public fun isValidJavaFqName(qualifiedName: String?): Boolean { if (qualifiedName == null) return false @@ -98,22 +76,3 @@ public fun isValidJavaFqName(qualifiedName: String?): Boolean { return state != State.AFTER_DOT } - -public fun FqName.getFirstSegment(): Name = this.pathSegments().first() - -tailRecursive -public fun FqName.each(operation: (FqName) -> Boolean) { - if (operation(this) && !isRoot()) { - parent().each(operation) - } -} - -private fun isSubpackageOf(subpackageNameStr: String, packageNameStr: String): Boolean { - return subpackageNameStr == packageNameStr || - (subpackageNameStr.startsWith(packageNameStr) && subpackageNameStr[packageNameStr.length()] == '.') -} - -private fun getFirstSegment(fqn: String): String { - val dotIndex = fqn.indexOf('.') - return if ((dotIndex != -1)) fqn.substring(0, dotIndex) else fqn -} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/refactoring/fqName/fqNameUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/refactoring/fqName/fqNameUtil.kt index 0acdc054a70..d20ae683dfb 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/refactoring/fqName/fqNameUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/refactoring/fqName/fqNameUtil.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.JetElement import org.jetbrains.kotlin.psi.JetCallExpression import org.jetbrains.kotlin.psi.JetUserType import org.jetbrains.kotlin.psi +import org.jetbrains.kotlin.resolve.ImportPath /** * Returns FqName for given declaration (either Java or Kotlin) @@ -74,3 +75,17 @@ fun JetSimpleNameExpression.changeQualifiedName(fqName: FqName): JetElement { else -> elementToReplace.replace(psiFactory.createExpression(text)) } as JetElement } + +public fun FqName.isImported(importPath: ImportPath, skipAliasedImports: Boolean = true): Boolean { + return when { + skipAliasedImports && importPath.hasAlias() -> false + importPath.isAllUnder() && !isRoot() -> importPath.fqnPart() == this.parent() + else -> importPath.fqnPart() == this + } +} + +public fun ImportPath.isImported(alreadyImported: ImportPath): Boolean { + return if (isAllUnder() || hasAlias()) this == alreadyImported else fqnPart().isImported(alreadyImported) +} + +public fun ImportPath.isImported(imports: Iterable): Boolean = imports.any { isImported(it) } diff --git a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt index 2afc2c3792a..d87230bebc0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/imports/KotlinImportOptimizer.kt @@ -29,6 +29,7 @@ import java.util.HashSet import java.util.ArrayList import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.idea.refactoring.fqName.isImported public class KotlinImportOptimizer() : ImportOptimizer { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt index 31803e597f8..e852f67dc68 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveUtils.kt @@ -30,7 +30,7 @@ import org.jetbrains.kotlin.psi.JetNamedDeclaration import org.jetbrains.kotlin.idea.codeInsight.DescriptorToDeclarationUtil import org.jetbrains.kotlin.psi.psiUtil.isAncestor import java.util.Collections -import org.jetbrains.kotlin.name.isImported +import org.jetbrains.kotlin.idea.refactoring.fqName.isImported import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PackageViewDescriptor diff --git a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt index e3ed0eea3b3..c60b05bd41b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt +++ b/idea/src/org/jetbrains/kotlin/idea/util/ImportInsertHelperImpl.kt @@ -54,6 +54,7 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.idea.util.ImportInsertHelper.ImportDescriptorResult import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.idea.refactoring.fqName.isImported public class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper() { /**