Refactoring

This commit is contained in:
Dmitry Gridin
2019-02-21 10:36:27 +03:00
parent d58ee133a2
commit 6bf119b262
4 changed files with 37 additions and 38 deletions
@@ -49,7 +49,7 @@ object ImportPathComparator : Comparator<ImportPath> {
private fun isJavaOrKotlinStdlibImport(path: ImportPath): Boolean {
val s = path.pathStr
return s.startsWith("java.") || s.startsWith("javax.")|| s.startsWith("kotlin.")
return s.startsWith("java.") || s.startsWith("javax.") || s.startsWith("kotlin.")
}
}
@@ -62,7 +62,8 @@ val DeclarationDescriptor.importableFqName: FqName?
fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean {
if (this is PackageViewDescriptor ||
DescriptorUtils.isTopLevelDeclaration(this) ||
this is CallableDescriptor && DescriptorUtils.isStaticDeclaration(this)) {
this is CallableDescriptor && DescriptorUtils.isStaticDeclaration(this)
) {
return !name.isSpecial
}
@@ -85,7 +86,7 @@ fun KotlinType.canBeReferencedViaImport(): Boolean {
// for cases when class qualifier refers companion object treats it like reference to class itself
fun KtReferenceExpression.getImportableTargets(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
val targets = bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, this]?.let { listOf(it) }
?: getReferenceTargets(bindingContext)
?: getReferenceTargets(bindingContext)
return targets.map { it.getImportableDescriptor() }.toSet()
}
+1 -1
View File
@@ -226,7 +226,7 @@
serviceImplementation="org.jetbrains.kotlin.idea.KotlinPluginUpdater"/>
<projectService serviceInterface="org.jetbrains.kotlin.idea.util.ImportInsertHelper"
serviceImplementation="org.jetbrains.kotlin.util.ImportInsertHelperImpl"/>
serviceImplementation="org.jetbrains.kotlin.idea.util.ImportInsertHelperImpl"/>
<applicationService serviceInterface="org.jetbrains.kotlin.psi.KotlinDeclarationNavigationPolicy"
serviceImplementation="org.jetbrains.kotlin.idea.decompiler.navigation.KotlinDeclarationNavigationPolicyImpl"/>
@@ -32,12 +32,11 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class ImportMemberIntention : SelfTargetingOffsetIndependentIntention<KtNameReferenceExpression>(
KtNameReferenceExpression::class.java,
"Add import for member"
){
KtNameReferenceExpression::class.java,
"Add import for member"
) {
private fun getFullQualifier(element: KtNameReferenceExpression): KtQualifiedExpression?
= element.getTopmostParentOfType<KtQualifiedExpression>()
private fun getFullQualifier(element: KtNameReferenceExpression): KtQualifiedExpression? = element.getTopmostParentOfType()
override fun isApplicableTo(element: KtNameReferenceExpression): Boolean {
if (element.getQualifiedElement() == element) return false //Ignore simple name expressions
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.util
package org.jetbrains.kotlin.idea.util
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
@@ -29,11 +29,9 @@ import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.util.ImportDescriptorResult
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
import org.jetbrains.kotlin.idea.util.getFileResolutionScope
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.ImportPath
@@ -84,7 +82,7 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
is ClassDescriptor -> {
importable.containingDeclaration is PackageFragmentDescriptor
|| codeStyleSettings.IMPORT_NESTED_CLASSES
|| codeStyleSettings.IMPORT_NESTED_CLASSES
}
else -> importable.containingDeclaration is PackageFragmentDescriptor // do not import members (e.g. java static members)
@@ -95,14 +93,13 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
val importer = Importer(file)
return if (forceAllUnderImport) {
importer.importDescriptorWithStarImport(descriptor)
}
else {
} else {
importer.importDescriptor(descriptor)
}
}
private inner class Importer(
private val file: KtFile
private val file: KtFile
) {
private val resolutionFacade = file.getResolutionFacade()
@@ -156,13 +153,13 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
val containerFqName = fqName.parent()
val tryStarImport = shouldTryStarImport(containerFqName, target, imports)
&& when (target) {
// this check does not give a guarantee that import with * will import the class - for example,
// there can be classes with conflicting name in more than one import with *
is ClassifierDescriptorWithTypeParameters -> topLevelScope.findClassifier(name, NoLookupLocation.FROM_IDE) == null
is FunctionDescriptor, is PropertyDescriptor -> true
else -> error("Unknown kind of descriptor to import:$target")
}
&& when (target) {
// this check does not give a guarantee that import with * will import the class - for example,
// there can be classes with conflicting name in more than one import with *
is ClassifierDescriptorWithTypeParameters -> topLevelScope.findClassifier(name, NoLookupLocation.FROM_IDE) == null
is FunctionDescriptor, is PropertyDescriptor -> true
else -> error("Unknown kind of descriptor to import:$target")
}
if (tryStarImport) {
val result = addStarImport(target)
@@ -192,7 +189,11 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
return addStarImport(target)
}
private fun shouldTryStarImport(containerFqName: FqName, target: DeclarationDescriptor, imports: Collection<KtImportDirective>): Boolean {
private fun shouldTryStarImport(
containerFqName: FqName,
target: DeclarationDescriptor,
imports: Collection<KtImportDirective>
): Boolean {
if (!canImportWithStar(containerFqName, target)) return false
val starImportPath = ImportPath(containerFqName, true)
@@ -240,7 +241,7 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
fun targetFqNameAndType(ref: KtReferenceExpression): Pair<FqName, Class<out Any>>? {
val descriptors = ref.resolveTargets()
val fqName: FqName? = descriptors.filter(::isVisible). map { it.importableFqName }.toSet().singleOrNull()
val fqName: FqName? = descriptors.filter(::isVisible).map { it.importableFqName }.toSet().singleOrNull()
return if (fqName != null) {
Pair(fqName, descriptors.elementAt(0).javaClass)
} else null
@@ -379,11 +380,11 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
return result
}
private fun targetFqName(ref: KtReferenceExpression): FqName?
= ref.resolveTargets().map { it.importableFqName }.toSet().singleOrNull()
private fun targetFqName(ref: KtReferenceExpression): FqName? =
ref.resolveTargets().map { it.importableFqName }.toSet().singleOrNull()
private fun KtReferenceExpression.resolveTargets(): Collection<DeclarationDescriptor>
= this.getImportableTargets(resolutionFacade.analyze(this, BodyResolveMode.PARTIAL))
private fun KtReferenceExpression.resolveTargets(): Collection<DeclarationDescriptor> =
this.getImportableTargets(resolutionFacade.analyze(this, BodyResolveMode.PARTIAL))
private fun addImport(fqName: FqName, allUnder: Boolean): KtImportDirective {
val importPath = ImportPath(fqName, allUnder)
@@ -402,17 +403,15 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
return if (imports.isEmpty()) { //TODO: strange hack
importList.add(psiFactory.createNewLine())
importList.add(newDirective) as KtImportDirective
}
else {
} else {
val insertAfter = imports
.lastOrNull {
val directivePath = it.importPath
directivePath != null && ImportPathComparator.compare(directivePath, importPath) <= 0
}
.lastOrNull {
val directivePath = it.importPath
directivePath != null && ImportPathComparator.compare(directivePath, importPath) <= 0
}
importList.addAfter(newDirective, insertAfter) as KtImportDirective
}
}
else {
} else {
error("Trying to insert import $fqName into a file ${file.name} of type ${file::class.java} with no import list.")
}
}