Create From Usage: Create package by reference expression/type reference

This commit is contained in:
Alexey Sedunov
2014-11-13 14:34:13 +03:00
parent fd4fa9a042
commit 2e7cbab453
4 changed files with 51 additions and 12 deletions
@@ -0,0 +1,5 @@
package org.jetbrains.jet.plugin.quickfix
import com.intellij.codeInsight.intention.IntentionAction
public open class DelegatingIntentionAction(val delegate: IntentionAction): IntentionAction by delegate
@@ -23,6 +23,11 @@ import org.jetbrains.jet.lang.psi.JetReferenceExpression
import java.util.Arrays
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression
import org.jetbrains.jet.lang.psi.psiUtil.isDotReceiver
import com.intellij.codeInsight.daemon.quickFix.CreateClassOrPackageFix
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor
import org.jetbrains.jet.lang.resolve.name.FqName
import java.util.ArrayList
import org.jetbrains.jet.utils.addToStdlib.singletonOrEmptyList
public object CreateClassFromReferenceExpressionActionFactory : JetIntentionActionsFactory() {
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
@@ -32,7 +37,6 @@ public object CreateClassFromReferenceExpressionActionFactory : JetIntentionActi
val file = refExpr.getContainingFile() as? JetFile ?: return Collections.emptyList()
val name = refExpr.getReferencedName()
if (!name.checkClassName()) return Collections.emptyList()
val exhaust = refExpr.getAnalysisResults()
val context = exhaust.getBindingContext()
@@ -56,7 +60,10 @@ public object CreateClassFromReferenceExpressionActionFactory : JetIntentionActi
getTargetParentByQualifier(refExpr.getContainingJetFile(), receiverSelector != null, qualifierDescriptor)
?: return Collections.emptyList()
return ClassKind.values()
val createPackageAction = refExpr.getCreatePackageFixIfApplicable(targetParent)
if (createPackageAction != null) return Collections.singletonList(createPackageAction)
return (if (name.checkClassName()) ClassKind.values() else array())
.filter {
when (it) {
ClassKind.ANNOTATION_CLASS -> inImport
@@ -8,22 +8,20 @@ import java.util.Collections
import org.jetbrains.jet.lang.psi.JetUserType
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.caches.resolve.getAnalysisResults
import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.jet.lang.types.Variance
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import com.intellij.psi.PsiElement
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperClass
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall
import org.jetbrains.jet.lang.psi.JetConstructorCalleeExpression
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.utils.addToStdlib.singletonOrEmptyList
public object CreateClassFromTypeReferenceActionFactory: JetIntentionActionsFactory() {
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
val userType = QuickFixUtil.getParentElementOfType(diagnostic, javaClass<JetUserType>()) ?: return Collections.emptyList()
val typeArguments = userType.getTypeArgumentsAsTypes()
val name = userType.getReferencedName() ?: return Collections.emptyList()
val refExpr = userType.getReferenceExpression() ?: return Collections.emptyList()
val name = refExpr.getReferencedName()
val typeRefParent = userType.getParent()?.getParent()
if (typeRefParent is JetConstructorCalleeExpression) return Collections.emptyList()
@@ -54,7 +52,8 @@ public object CreateClassFromTypeReferenceActionFactory: JetIntentionActionsFact
}
}
return possibleKinds.map {
val createPackageAction = refExpr.getCreatePackageFixIfApplicable(targetParent)
val createClassActions = possibleKinds.map {
val classInfo = ClassInfo(
kind = it,
name = name,
@@ -64,5 +63,6 @@ public object CreateClassFromTypeReferenceActionFactory: JetIntentionActionsFact
)
CreateClassFromUsageFix(userType, classInfo)
}
return createPackageAction.singletonOrEmptyList() + createClassActions
}
}
@@ -6,9 +6,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.psi.JavaPsiFacade
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.psi.JetExpression
import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.guessTypes
import org.jetbrains.jet.lang.resolve.BindingContext
@@ -21,16 +19,23 @@ import org.jetbrains.jet.lang.types.Variance
import org.jetbrains.jet.lang.psi.Call
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.jet.lang.resolve.scopes.receivers.Qualifier
import org.jetbrains.jet.plugin.util.ProjectRootsUtil
import org.jetbrains.jet.plugin.quickfix.createFromUsage.callableBuilder.noSubstitutions
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
import com.intellij.codeInsight.intention.IntentionAction
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import com.intellij.codeInsight.daemon.quickFix.CreateClassOrPackageFix
import org.jetbrains.jet.plugin.quickfix.DelegatingIntentionAction
import org.jetbrains.jet.plugin.JetBundle
import com.intellij.psi.PsiPackage
import org.jetbrains.jet.plugin.quickfix.createFromUsage.createClass.canRefactor
import com.intellij.psi.PsiDirectory
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.plugin.util.ProjectRootsUtil
private fun String.checkClassName(): Boolean = isNotEmpty() && Character.isUpperCase(first())
private fun String.checkPackageName(): Boolean = isNotEmpty() && Character.isLowerCase(first())
private fun getTargetParentByQualifier(
file: JetFile,
isQualified: Boolean,
@@ -99,4 +104,26 @@ private fun PsiElement.canRefactor(): Boolean {
else ->
false
}
}
private fun JetSimpleNameExpression.getCreatePackageFixIfApplicable(targetParent: PsiElement): IntentionAction? {
val name = getReferencedName()
if (!name.checkPackageName()) return null
val basePackage: PsiPackage = when (targetParent) {
is JetFile -> JavaPsiFacade.getInstance(targetParent.getProject()).findPackage(targetParent.getPackageFqName().asString())
is PsiPackage -> targetParent : PsiPackage
else -> null
} ?: return null
val baseName = basePackage.getQualifiedName()
val fullName = if (baseName.isNotEmpty()) "$baseName.$name" else name
val javaFix = CreateClassOrPackageFix.createFix(fullName, getResolveScope(), this, basePackage, null, null, null) ?: return null
return object: DelegatingIntentionAction(javaFix) {
override fun getFamilyName(): String = JetBundle.message("create.from.usage.family")
override fun getText(): String = JetBundle.message("create.0.from.usage", "package '${fullName}'")
}
}