Intention to import members with '*'
This commit is contained in:
@@ -23,21 +23,21 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.resolve.ImportPath
|
import org.jetbrains.kotlin.resolve.ImportPath
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public abstract class ImportInsertHelper {
|
abstract class ImportInsertHelper {
|
||||||
/*TODO: implementation is not quite correct*/
|
/*TODO: implementation is not quite correct*/
|
||||||
public abstract fun isImportedWithDefault(importPath: ImportPath, contextFile: KtFile): Boolean
|
abstract fun isImportedWithDefault(importPath: ImportPath, contextFile: KtFile): Boolean
|
||||||
|
|
||||||
public abstract fun mayImportOnShortenReferences(descriptor: DeclarationDescriptor): Boolean
|
abstract fun mayImportOnShortenReferences(descriptor: DeclarationDescriptor): Boolean
|
||||||
|
|
||||||
public abstract val importSortComparator: Comparator<ImportPath>
|
abstract val importSortComparator: Comparator<ImportPath>
|
||||||
|
|
||||||
public enum class ImportDescriptorResult {
|
enum class ImportDescriptorResult {
|
||||||
FAIL,
|
FAIL,
|
||||||
IMPORT_ADDED,
|
IMPORT_ADDED,
|
||||||
ALREADY_IMPORTED
|
ALREADY_IMPORTED
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract fun importDescriptor(file: KtFile, descriptor: DeclarationDescriptor): ImportDescriptorResult
|
abstract fun importDescriptor(file: KtFile, descriptor: DeclarationDescriptor, forceAllUnderImport: Boolean = false): ImportDescriptorResult
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|||||||
@@ -207,11 +207,11 @@ public class ShortenReferences(val options: (KtElement) -> Options = { Options.D
|
|||||||
protected fun analyze(element: KtElement)
|
protected fun analyze(element: KtElement)
|
||||||
= resolutionFacade.analyze(element, BodyResolveMode.PARTIAL)
|
= resolutionFacade.analyze(element, BodyResolveMode.PARTIAL)
|
||||||
|
|
||||||
protected fun processQualifiedElement(element: T, target: DeclarationDescriptor, canShortenNow: Boolean) {
|
protected fun processQualifiedElement(element: T, target: DeclarationDescriptor?, canShortenNow: Boolean) {
|
||||||
if (canShortenNow) {
|
if (canShortenNow) {
|
||||||
addElementToShorten(element)
|
addElementToShorten(element)
|
||||||
}
|
}
|
||||||
else if (target !in failedToImportDescriptors && mayImport(target, file)) {
|
else if (target != null && target !in failedToImportDescriptors && mayImport(target, file)) {
|
||||||
descriptorsToImport.add(target)
|
descriptorsToImport.add(target)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -340,13 +340,14 @@ public class ShortenReferences(val options: (KtElement) -> Options = { Options.D
|
|||||||
|
|
||||||
val selector = qualifiedExpression.getSelectorExpression() ?: return false
|
val selector = qualifiedExpression.getSelectorExpression() ?: return false
|
||||||
val callee = selector.getCalleeExpressionIfAny() as? KtReferenceExpression ?: return false
|
val callee = selector.getCalleeExpressionIfAny() as? KtReferenceExpression ?: return false
|
||||||
val target = callee.targets(bindingContext).singleOrNull() ?: return false
|
val targets = callee.targets(bindingContext)
|
||||||
|
if (targets.isEmpty()) return false
|
||||||
|
|
||||||
val scope = qualifiedExpression.getResolutionScope(bindingContext, resolutionFacade)
|
val scope = qualifiedExpression.getResolutionScope(bindingContext, resolutionFacade)
|
||||||
val selectorCopy = selector.copy() as KtReferenceExpression
|
val selectorCopy = selector.copy() as KtReferenceExpression
|
||||||
val newContext = selectorCopy.analyzeInContext(scope, selector)
|
val newContext = selectorCopy.analyzeInContext(scope, selector)
|
||||||
val targetsWhenShort = (selectorCopy.getCalleeExpressionIfAny() as KtReferenceExpression).targets(newContext)
|
val targetsWhenShort = (selectorCopy.getCalleeExpressionIfAny() as KtReferenceExpression).targets(newContext)
|
||||||
val targetsMatch = targetsWhenShort.singleOrNull()?.asString() == target.asString()
|
val targetsMatch = targetsMatch(targets, targetsWhenShort)
|
||||||
|
|
||||||
if (receiver is KtThisExpression) {
|
if (receiver is KtThisExpression) {
|
||||||
if (!targetsMatch) return false
|
if (!targetsMatch) return false
|
||||||
@@ -368,10 +369,20 @@ public class ShortenReferences(val options: (KtElement) -> Options = { Options.D
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
processQualifiedElement(qualifiedExpression, target, targetsMatch)
|
processQualifiedElement(qualifiedExpression, targets.singleOrNull(), targetsMatch)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun targetsMatch(targets1: Collection<DeclarationDescriptor>, targets2: Collection<DeclarationDescriptor>): Boolean {
|
||||||
|
if (targets1.size != targets2.size) return false
|
||||||
|
if (targets1.size == 1) {
|
||||||
|
return targets1.single().asString() == targets2.single().asString()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return targets1.map { it.asString() }.toSet() == targets2.map { it.asString() }.toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun shortenElement(element: KtDotQualifiedExpression): KtElement {
|
override fun shortenElement(element: KtDotQualifiedExpression): KtElement {
|
||||||
return element.replace(element.getSelectorExpression()!!) as KtElement
|
return element.replace(element.getSelectorExpression()!!) as KtElement
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import javax.swing.SwingUtilities
|
||||||
|
<spot>import javax.swing.SwingUtilities.*</spot>
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
SwingUtilities.invokeLater { }
|
||||||
|
SwingUtilities.invokeAndWait()
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<spot>SwingUtilities.</spot>invokeLater { }
|
||||||
|
<spot>SwingUtilities.</spot>invokeAndWait()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
This intention converts selected qualified reference into simple reference and adds import for corresponding class.
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -632,6 +632,11 @@
|
|||||||
<category>Kotlin</category>
|
<category>Kotlin</category>
|
||||||
</intentionAction>
|
</intentionAction>
|
||||||
|
|
||||||
|
<intentionAction>
|
||||||
|
<className>org.jetbrains.kotlin.idea.intentions.ImportAllMembersIntention</className>
|
||||||
|
<category>Kotlin</category>
|
||||||
|
</intentionAction>
|
||||||
|
|
||||||
<intentionAction>
|
<intentionAction>
|
||||||
<className>org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention</className>
|
<className>org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention</className>
|
||||||
<category>Kotlin</category>
|
<category>Kotlin</category>
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.intentions
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.conversion.copy.range
|
||||||
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
|
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
|
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassifierQualifier
|
||||||
|
|
||||||
|
class ImportAllMembersIntention : SelfTargetingIntention<KtDotQualifiedExpression>(
|
||||||
|
KtDotQualifiedExpression::class.java,
|
||||||
|
"Import members with '*'"
|
||||||
|
){
|
||||||
|
override fun isApplicableTo(element: KtDotQualifiedExpression, caretOffset: Int): Boolean {
|
||||||
|
if (!element.receiverExpression.range.containsOffset(caretOffset)) return false
|
||||||
|
|
||||||
|
val target = target(element) ?: return false
|
||||||
|
val targetFqName = target.importableFqName ?: return false
|
||||||
|
|
||||||
|
val file = element.getContainingKtFile()
|
||||||
|
val project = file.project
|
||||||
|
val dummyFileText = (file.packageDirective?.text ?: "") + "\n" + (file.importList?.text ?: "")
|
||||||
|
val dummyFile = KtPsiFactory(project).createAnalyzableFile("Dummy.kt", dummyFileText, file)
|
||||||
|
val helper = ImportInsertHelper.getInstance(project)
|
||||||
|
if (helper.importDescriptor(dummyFile, target, forceAllUnderImport = true) == ImportInsertHelper.ImportDescriptorResult.FAIL) return false
|
||||||
|
|
||||||
|
text = "Import members from '${targetFqName.parent().asString()}'"
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyTo(element: KtDotQualifiedExpression, editor: Editor) {
|
||||||
|
val target = target(element)!!
|
||||||
|
val classFqName = target.importableFqName!!.parent()
|
||||||
|
|
||||||
|
ImportInsertHelper.getInstance(element.project).importDescriptor(element.getContainingKtFile(), target, forceAllUnderImport = true)
|
||||||
|
|
||||||
|
val qualifiedExpressions = element.getContainingKtFile().collectDescendantsOfType<KtDotQualifiedExpression> { qualifiedExpression ->
|
||||||
|
val qualifierName = qualifiedExpression.receiverExpression.getQualifiedElementSelector() as? KtNameReferenceExpression
|
||||||
|
?: return@collectDescendantsOfType false
|
||||||
|
qualifierName.getReferencedNameAsName() == classFqName.shortName() && target(qualifiedExpression)?.importableFqName?.parent() == classFqName
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: not deep
|
||||||
|
ShortenReferences.DEFAULT.process(qualifiedExpressions)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun target(expression: KtDotQualifiedExpression): DeclarationDescriptor? {
|
||||||
|
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
||||||
|
val qualifier = bindingContext[BindingContext.QUALIFIER, expression.receiverExpression] as? ClassifierQualifier ?: return null
|
||||||
|
if (qualifier.descriptor !is ClassDescriptor) return null
|
||||||
|
val selector = expression.getQualifiedElementSelector() as? KtNameReferenceExpression ?: return null
|
||||||
|
return selector.mainReference.resolveToDescriptors(bindingContext).firstOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,6 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.impl.PsiModificationTrackerImpl
|
import com.intellij.psi.impl.PsiModificationTrackerImpl
|
||||||
import com.intellij.psi.util.PsiModificationTracker
|
import com.intellij.psi.util.PsiModificationTracker
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.util.getFileResolutionScope
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
|
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
|
||||||
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||||
@@ -30,6 +29,7 @@ import org.jetbrains.kotlin.idea.imports.importableFqName
|
|||||||
import org.jetbrains.kotlin.idea.project.platform
|
import org.jetbrains.kotlin.idea.project.platform
|
||||||
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
|
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
|
||||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
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.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -38,8 +38,8 @@ import org.jetbrains.kotlin.resolve.ImportPath
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
||||||
@@ -99,8 +99,15 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun importDescriptor(file: KtFile, descriptor: DeclarationDescriptor)
|
override fun importDescriptor(file: KtFile, descriptor: DeclarationDescriptor, forceAllUnderImport: Boolean): ImportDescriptorResult {
|
||||||
= Importer(file).importDescriptor(descriptor)
|
val importer = Importer(file)
|
||||||
|
if (forceAllUnderImport) {
|
||||||
|
return importer.importDescriptorWithStarImport(descriptor)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return importer.importDescriptor(descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private inner class Importer(
|
private inner class Importer(
|
||||||
private val file: KtFile
|
private val file: KtFile
|
||||||
@@ -135,10 +142,7 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
|
|||||||
val targetFqName = target.importableFqName ?: return ImportDescriptorResult.FAIL
|
val targetFqName = target.importableFqName ?: return ImportDescriptorResult.FAIL
|
||||||
if (isAlreadyImported(target, topLevelScope, targetFqName)) return ImportDescriptorResult.ALREADY_IMPORTED
|
if (isAlreadyImported(target, topLevelScope, targetFqName)) return ImportDescriptorResult.ALREADY_IMPORTED
|
||||||
|
|
||||||
val imports = if (file is KtCodeFragment)
|
val imports = getImports(file)
|
||||||
file.importsAsImportList()?.getImports() ?: listOf()
|
|
||||||
else
|
|
||||||
file.getImportDirectives()
|
|
||||||
|
|
||||||
if (imports.any { !it.isAllUnder && it.importPath?.fqnPart() == targetFqName }) {
|
if (imports.any { !it.isAllUnder && it.importPath?.fqnPart() == targetFqName }) {
|
||||||
return ImportDescriptorResult.FAIL
|
return ImportDescriptorResult.FAIL
|
||||||
@@ -159,9 +163,9 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
|
|||||||
}
|
}
|
||||||
|
|
||||||
val fqName = target.importableFqName!!
|
val fqName = target.importableFqName!!
|
||||||
val packageFqName = fqName.parent()
|
val containerFqName = fqName.parent()
|
||||||
|
|
||||||
val tryStarImport = shouldTryStarImport(packageFqName, target, imports)
|
val tryStarImport = shouldTryStarImport(containerFqName, target, imports)
|
||||||
&& when (target) {
|
&& when (target) {
|
||||||
// this check does not give a guarantee that import with * will import the class - for example,
|
// 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 *
|
// there can be classes with conflicting name in more than one import with *
|
||||||
@@ -178,14 +182,31 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
|
|||||||
return addExplicitImport(target)
|
return addExplicitImport(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldTryStarImport(containerFqName: FqName, target: DeclarationDescriptor, imports: Collection<KtImportDirective>): Boolean {
|
fun importDescriptorWithStarImport(descriptor: DeclarationDescriptor): ImportDescriptorResult {
|
||||||
if (containerFqName.isRoot) return false
|
val target = descriptor.getImportableDescriptor()
|
||||||
|
|
||||||
val container = target.containingDeclaration
|
val fqName = target.importableFqName ?: return ImportDescriptorResult.FAIL
|
||||||
if (container is ClassDescriptor && container.kind == ClassKind.OBJECT) return false // cannot import with '*' from object
|
val containerFqName = fqName.parent()
|
||||||
|
val imports = getImports(file)
|
||||||
|
|
||||||
val starImportPath = ImportPath(containerFqName, true)
|
val starImportPath = ImportPath(containerFqName, true)
|
||||||
if (imports.any { it.getImportPath() == starImportPath }) return false
|
if (imports.any { it.importPath == starImportPath }) {
|
||||||
|
return if (isAlreadyImported(target, resolutionFacade.getFileResolutionScope(file), fqName))
|
||||||
|
ImportDescriptorResult.ALREADY_IMPORTED
|
||||||
|
else
|
||||||
|
ImportDescriptorResult.FAIL
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canImportWithStar(containerFqName, target)) return ImportDescriptorResult.FAIL
|
||||||
|
|
||||||
|
return addStarImport(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldTryStarImport(containerFqName: FqName, target: DeclarationDescriptor, imports: Collection<KtImportDirective>): Boolean {
|
||||||
|
if (!canImportWithStar(containerFqName, target)) return false
|
||||||
|
|
||||||
|
val starImportPath = ImportPath(containerFqName, true)
|
||||||
|
if (imports.any { it.importPath == starImportPath }) return false
|
||||||
|
|
||||||
if (containerFqName.asString() in codeStyleSettings.PACKAGES_TO_USE_STAR_IMPORTS) return true
|
if (containerFqName.asString() in codeStyleSettings.PACKAGES_TO_USE_STAR_IMPORTS) return true
|
||||||
|
|
||||||
@@ -193,13 +214,22 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
|
|||||||
val path = it.getImportPath()
|
val path = it.getImportPath()
|
||||||
path != null && !path.isAllUnder() && !path.hasAlias() && path.fqnPart().parent() == containerFqName
|
path != null && !path.isAllUnder() && !path.hasAlias() && path.fqnPart().parent() == containerFqName
|
||||||
}
|
}
|
||||||
val nameCountToUseStar = if (container is ClassDescriptor)
|
val nameCountToUseStar = if (target.containingDeclaration is ClassDescriptor)
|
||||||
codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS
|
codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS
|
||||||
else
|
else
|
||||||
codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT
|
codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT
|
||||||
return importsFromPackage + 1 >= nameCountToUseStar
|
return importsFromPackage + 1 >= nameCountToUseStar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun canImportWithStar(containerFqName: FqName, target: DeclarationDescriptor): Boolean {
|
||||||
|
if (containerFqName.isRoot) return false
|
||||||
|
|
||||||
|
val container = target.containingDeclaration
|
||||||
|
if (container is ClassDescriptor && container.kind == ClassKind.OBJECT) return false // cannot import with '*' from object
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
private fun addStarImport(target: DeclarationDescriptor): ImportDescriptorResult {
|
private fun addStarImport(target: DeclarationDescriptor): ImportDescriptorResult {
|
||||||
val targetFqName = target.importableFqName!!
|
val targetFqName = target.importableFqName!!
|
||||||
val parentFqName = targetFqName.parent()
|
val parentFqName = targetFqName.parent()
|
||||||
@@ -397,4 +427,11 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getImports(file: KtFile): List<KtImportDirective> {
|
||||||
|
return if (file is KtCodeFragment)
|
||||||
|
file.importsAsImportList()?.imports ?: listOf()
|
||||||
|
else
|
||||||
|
file.importDirectives
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
org.jetbrains.kotlin.idea.intentions.ImportAllMembersIntention
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.SwingUtilities.invokeLater
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>SwingUtilities.invokeLater { }
|
||||||
|
|
||||||
|
val bottom = SwingUtilities.BOTTOM
|
||||||
|
|
||||||
|
SwingUtilities.invokeAndWait {
|
||||||
|
SwingUtilities.invokeLater { }
|
||||||
|
}
|
||||||
|
|
||||||
|
val horizontal = javax.swing.SwingUtilities.HORIZONTAL
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.SwingUtilities.*
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>invokeLater { }
|
||||||
|
|
||||||
|
val bottom = BOTTOM
|
||||||
|
|
||||||
|
invokeAndWait {
|
||||||
|
invokeLater { }
|
||||||
|
}
|
||||||
|
|
||||||
|
val horizontal = HORIZONTAL
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.SwingUtilities.*
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>SwingUtilities.invokeLater { }
|
||||||
|
|
||||||
|
val bottom = SwingUtilities.BOTTOM
|
||||||
|
|
||||||
|
SwingUtilities.invokeAndWait {
|
||||||
|
SwingUtilities.invokeLater { }
|
||||||
|
}
|
||||||
|
|
||||||
|
val horizontal = javax.swing.SwingUtilities.HORIZONTAL
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.SwingUtilities.*
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>invokeLater { }
|
||||||
|
|
||||||
|
val bottom = BOTTOM
|
||||||
|
|
||||||
|
invokeAndWait {
|
||||||
|
invokeLater { }
|
||||||
|
}
|
||||||
|
|
||||||
|
val horizontal = HORIZONTAL
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// ERROR: None of the following functions can be called with the arguments supplied: <br>public open fun convertPoint(p0: java.awt.Component!, p1: [ERROR : Unresolved java classifier: Point]!, p2: java.awt.Component!): [ERROR : Unresolved java classifier: Point]! defined in javax.swing.SwingUtilities<br>public open fun convertPoint(p0: java.awt.Component!, p1: kotlin.Int, p2: kotlin.Int, p3: java.awt.Component!): [ERROR : Unresolved java classifier: Point]! defined in javax.swing.SwingUtilities
|
||||||
|
// ERROR: None of the following functions can be called with the arguments supplied: <br>public open fun convertPoint(p0: java.awt.Component!, p1: [ERROR : Unresolved java classifier: Point]!, p2: java.awt.Component!): [ERROR : Unresolved java classifier: Point]! defined in javax.swing.SwingUtilities<br>public open fun convertPoint(p0: java.awt.Component!, p1: kotlin.Int, p2: kotlin.Int, p3: java.awt.Component!): [ERROR : Unresolved java classifier: Point]! defined in javax.swing.SwingUtilities
|
||||||
|
// ERROR: Unresolved reference: unresolved
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>SwingUtilities.convertPoint()
|
||||||
|
|
||||||
|
val bottom = SwingUtilities.BOTTOM
|
||||||
|
|
||||||
|
SwingUtilities.convertPoint()
|
||||||
|
|
||||||
|
SwingUtilities.unresolved
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// ERROR: None of the following functions can be called with the arguments supplied: <br>public open fun convertPoint(p0: java.awt.Component!, p1: [ERROR : Unresolved java classifier: Point]!, p2: java.awt.Component!): [ERROR : Unresolved java classifier: Point]! defined in javax.swing.SwingUtilities<br>public open fun convertPoint(p0: java.awt.Component!, p1: kotlin.Int, p2: kotlin.Int, p3: java.awt.Component!): [ERROR : Unresolved java classifier: Point]! defined in javax.swing.SwingUtilities
|
||||||
|
// ERROR: None of the following functions can be called with the arguments supplied: <br>public open fun convertPoint(p0: java.awt.Component!, p1: [ERROR : Unresolved java classifier: Point]!, p2: java.awt.Component!): [ERROR : Unresolved java classifier: Point]! defined in javax.swing.SwingUtilities<br>public open fun convertPoint(p0: java.awt.Component!, p1: kotlin.Int, p2: kotlin.Int, p3: java.awt.Component!): [ERROR : Unresolved java classifier: Point]! defined in javax.swing.SwingUtilities
|
||||||
|
// ERROR: Unresolved reference: unresolved
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.SwingUtilities.*
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>convertPoint()
|
||||||
|
|
||||||
|
val bottom = BOTTOM
|
||||||
|
|
||||||
|
convertPoint()
|
||||||
|
|
||||||
|
SwingUtilities.unresolved
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'kotlin.LazyThreadSafetyMode'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class A {
|
||||||
|
val v1: Int by lazy(<caret>LazyThreadSafetyMode.NONE) { 1 }
|
||||||
|
val v2: Int by lazy(LazyThreadSafetyMode.PUBLICATION) { 1 }
|
||||||
|
/*
|
||||||
|
val v3 = LazyThreadSafetyMode.values
|
||||||
|
val v4 = LazyThreadSafetyMode.valueOf("")
|
||||||
|
*/
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import kotlin.LazyThreadSafetyMode.*
|
||||||
|
|
||||||
|
// INTENTION_TEXT: "Import members from 'kotlin.LazyThreadSafetyMode'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class A {
|
||||||
|
val v1: Int by lazy(<caret>NONE) { 1 }
|
||||||
|
val v2: Int by lazy(PUBLICATION) { 1 }
|
||||||
|
/*
|
||||||
|
val v3 = LazyThreadSafetyMode.values
|
||||||
|
val v4 = LazyThreadSafetyMode.valueOf("")
|
||||||
|
*/
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val v = <caret>LazyThreadSafetyMode.values
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import kotlin.text.Regex
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>Regex.escape("")
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
class A {
|
||||||
|
val v1: Int by <caret>Delegates.notNull()
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
javax.swing.SwingUtilities<caret>.invokeLater { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import javax.swing.SwingUtilities.*
|
||||||
|
|
||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>invokeLater { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>javax.swing.SwingUtilities.invokeLater { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import javax.swing.SwingUtilities.*
|
||||||
|
|
||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
<caret>invokeLater { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.SwingUtilities.invokeLater
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
invokeLater { }
|
||||||
|
|
||||||
|
val bottom = <caret>SwingUtilities.BOTTOM
|
||||||
|
|
||||||
|
SwingUtilities.invokeAndWait {
|
||||||
|
invokeLater { }
|
||||||
|
}
|
||||||
|
|
||||||
|
val horizontal = javax.swing.SwingUtilities.HORIZONTAL
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.SwingUtilities.*
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
invokeLater { }
|
||||||
|
|
||||||
|
val bottom = <caret>BOTTOM
|
||||||
|
|
||||||
|
invokeAndWait {
|
||||||
|
invokeLater { }
|
||||||
|
}
|
||||||
|
|
||||||
|
val horizontal = HORIZONTAL
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// ERROR: Unresolved reference: unresolved
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
SwingUtilities.invokeLater { }
|
||||||
|
|
||||||
|
val bottom = <caret>SwingUtilities.BOTTOM
|
||||||
|
|
||||||
|
SwingUtilities.invokeAndWait {
|
||||||
|
SwingUtilities.invokeLater { }
|
||||||
|
}
|
||||||
|
|
||||||
|
val horizontal = javax.swing.SwingUtilities.HORIZONTAL
|
||||||
|
|
||||||
|
SwingUtilities.unresolved
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'javax.swing.SwingUtilities'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// ERROR: Unresolved reference: unresolved
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
import javax.swing.SwingUtilities.*
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
invokeLater { }
|
||||||
|
|
||||||
|
val bottom = <caret>BOTTOM
|
||||||
|
|
||||||
|
invokeAndWait {
|
||||||
|
invokeLater { }
|
||||||
|
}
|
||||||
|
|
||||||
|
val horizontal = HORIZONTAL
|
||||||
|
|
||||||
|
SwingUtilities.unresolved
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// ERROR: Unresolved reference: unresolved
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
|
val v = <caret>SwingUtilities.unresolved()
|
||||||
@@ -5098,6 +5098,81 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/intentions/importAllMembers")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ImportAllMembers extends AbstractIntentionTest {
|
||||||
|
public void testAllFilesPresentInImportAllMembers() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/importAllMembers"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AlreadyImported.kt")
|
||||||
|
public void testAlreadyImported() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/AlreadyImported.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AlreadyImportedWithStar.kt")
|
||||||
|
public void testAlreadyImportedWithStar() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/AlreadyImportedWithStar.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AmbiguousCalls.kt")
|
||||||
|
public void testAmbiguousCalls() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/AmbiguousCalls.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EnumMembers.kt")
|
||||||
|
public void testEnumMembers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/EnumMembers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NotFromCompanionObject.kt")
|
||||||
|
public void testNotFromCompanionObject() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/NotFromCompanionObject.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NotFromObject.kt")
|
||||||
|
public void testNotFromObject() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/NotFromObject.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("QualifiedName.kt")
|
||||||
|
public void testQualifiedName() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/QualifiedName.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("QualifiedName2.kt")
|
||||||
|
public void testQualifiedName2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/QualifiedName2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("RemoveSingleImports.kt")
|
||||||
|
public void testRemoveSingleImports() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/RemoveSingleImports.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("StaticJavaMembers.kt")
|
||||||
|
public void testStaticJavaMembers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/StaticJavaMembers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("UnresolvedMember.kt")
|
||||||
|
public void testUnresolvedMember() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/UnresolvedMember.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/intentions/importMember")
|
@TestMetadata("idea/testData/intentions/importMember")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user