From 64eeaf8b9d4315e5fc9335a2371ffae390e4bc7b Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Wed, 6 Jan 2016 01:09:52 +0300 Subject: [PATCH] Make Class an Annotation Quick-Fix: Convert to Kotlin & refactor --- .../kotlin/idea/KotlinBundle.properties | 2 - .../quickfix/MakeClassAnAnnotationClassFix.kt | 121 +++++------------- .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 2 +- 3 files changed, 33 insertions(+), 92 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties index 8d015df2d3e..c47ea7e7504 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/KotlinBundle.properties @@ -7,8 +7,6 @@ add.init.keyword.in.whole.project=Add 'init' keyword in whole project add.init.keyword.in.whole.project.modal.title=Adding 'init' keyword in whole project add.init.keyword.in.whole.project.family=Add 'init' keyword in whole project insert.delegation.call=Insert ''{0}()'' call -make.class.annotation.class=Make ''{0}'' an annotation class -make.class.annotation.class.family=Make class an annotation class remove.parts.from.property=Remove {0} from property remove.parts.from.property.family=Remove parts from property remove.psi.element.family=Remove element diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/MakeClassAnAnnotationClassFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/MakeClassAnAnnotationClassFix.kt index 90032e4703b..d8669d70ed7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/MakeClassAnAnnotationClassFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/MakeClassAnAnnotationClassFix.kt @@ -14,99 +14,42 @@ * limitations under the License. */ -package org.jetbrains.kotlin.idea.quickfix; +package org.jetbrains.kotlin.idea.quickfix -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiReference; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.diagnostics.Diagnostic; -import org.jetbrains.kotlin.idea.KotlinBundle; -import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil; -import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtilKt; -import org.jetbrains.kotlin.idea.references.ReferenceUtilKt; -import org.jetbrains.kotlin.lexer.KtTokens; -import org.jetbrains.kotlin.psi.*; +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.refactoring.canRefactor +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtAnnotationEntry +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -public class MakeClassAnAnnotationClassFix extends KotlinQuickFixAction { - private final KtAnnotationEntry annotationEntry; - private KtClass annotationClass; +class MakeClassAnAnnotationClassFix(annotationClass: KtClass) : KotlinQuickFixAction(annotationClass) { + override fun getFamilyName() = "Make class an annotation class" - public MakeClassAnAnnotationClassFix(@NotNull KtAnnotationEntry annotationEntry) { - super(annotationEntry); - this.annotationEntry = annotationEntry; + override fun getText() = "Make '${element.name}' an annotation class" + + public override fun invoke(project: Project, editor: Editor?, file: KtFile) { + element.addModifier(KtTokens.ANNOTATION_KEYWORD) } - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiFile file) { - if (!super.isAvailable(project, editor, file)) { - return false; + companion object : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val typeReference = diagnostic.psiElement.getNonStrictParentOfType()?.typeReference ?: return null + val bindingContext = typeReference.analyze(BodyResolveMode.PARTIAL) + val type = bindingContext[BindingContext.TYPE, typeReference] ?: return null + val classDescriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null + val klass = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor) as? KtClass ?: return null + if (!klass.canRefactor()) return null + return MakeClassAnAnnotationClassFix(klass) } - - KtTypeReference typeReference = annotationEntry.getTypeReference(); - if (typeReference == null) { - return false; - } - - KtSimpleNameExpression referenceExpression = PsiTreeUtil.findChildOfType(typeReference, KtSimpleNameExpression.class); - if (referenceExpression == null) { - return false; - } - - PsiReference reference = ReferenceUtilKt.getMainReference(referenceExpression); - PsiElement target = reference.resolve(); - if (target instanceof KtClass) { - annotationClass = (KtClass) target; - return JetRefactoringUtilKt.canRefactor(annotationClass); - } - - return false; } - - @NotNull - @Override - public String getText() { - return KotlinBundle.message("make.class.annotation.class", annotationClass.getName()); - } - - @NotNull - @Override - public String getFamilyName() { - return KotlinBundle.message("make.class.annotation.class.family"); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull KtFile file) throws IncorrectOperationException { - KtPsiFactory factory = new KtPsiFactory(annotationClass.getProject()); - KtModifierList list = annotationClass.getModifierList(); - PsiElement added; - if (list == null) { - KtModifierList newModifierList = factory.createModifierList(KtTokens.ANNOTATION_KEYWORD); - added = annotationClass.addBefore(newModifierList, annotationClass.getClassOrInterfaceKeyword()); - } - else { - PsiElement entry = factory.createModifier(KtTokens.ANNOTATION_KEYWORD); - added = list.addBefore(entry, list.getFirstChild()); - } - annotationClass.addAfter(factory.createWhiteSpace(), added); - } - - @NotNull - public static KotlinSingleIntentionActionFactory createFactory() { - return new KotlinSingleIntentionActionFactory() { - @Nullable - @Override - public IntentionAction createAction(@NotNull Diagnostic diagnostic) { - KtAnnotationEntry annotation = QuickFixUtil.getParentElementOfType(diagnostic, KtAnnotationEntry.class); - return annotation == null ? null : new MakeClassAnAnnotationClassFix(annotation); - } - }; - } -} - +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 5ee1b880aff..ba6f0d74788 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -213,7 +213,7 @@ class QuickFixRegistrar : QuickFixContributor { PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(false)) PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(false)) - NOT_AN_ANNOTATION_CLASS.registerFactory(MakeClassAnAnnotationClassFix.createFactory()) + NOT_AN_ANNOTATION_CLASS.registerFactory(MakeClassAnAnnotationClassFix) val changeVariableTypeFix = ChangeVariableTypeFix.createFactoryForPropertyOrReturnTypeMismatchOnOverride() RETURN_TYPE_MISMATCH_ON_OVERRIDE.registerFactory(changeVariableTypeFix)