Make Class an Annotation Quick-Fix: Convert to Kotlin & refactor

This commit is contained in:
Alexey Sedunov
2016-01-06 01:09:52 +03:00
parent 04b8f16576
commit 64eeaf8b9d
3 changed files with 33 additions and 92 deletions
@@ -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.modal.title=Adding 'init' keyword in whole project
add.init.keyword.in.whole.project.family=Add 'init' keyword in whole project add.init.keyword.in.whole.project.family=Add 'init' keyword in whole project
insert.delegation.call=Insert ''{0}()'' call 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=Remove {0} from property
remove.parts.from.property.family=Remove parts from property remove.parts.from.property.family=Remove parts from property
remove.psi.element.family=Remove element remove.psi.element.family=Remove element
@@ -14,99 +14,42 @@
* limitations under the License. * 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.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement; import org.jetbrains.kotlin.descriptors.ClassDescriptor
import com.intellij.psi.PsiFile; import org.jetbrains.kotlin.diagnostics.Diagnostic
import com.intellij.psi.PsiReference; import org.jetbrains.kotlin.idea.caches.resolve.analyze
import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.kotlin.idea.refactoring.canRefactor
import com.intellij.util.IncorrectOperationException; import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.diagnostics.Diagnostic; import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.idea.KotlinBundle; import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil; import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtilKt; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.idea.references.ReferenceUtilKt; import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.*;
public class MakeClassAnAnnotationClassFix extends KotlinQuickFixAction<KtAnnotationEntry> { class MakeClassAnAnnotationClassFix(annotationClass: KtClass) : KotlinQuickFixAction<KtClass>(annotationClass) {
private final KtAnnotationEntry annotationEntry; override fun getFamilyName() = "Make class an annotation class"
private KtClass annotationClass;
public MakeClassAnAnnotationClassFix(@NotNull KtAnnotationEntry annotationEntry) { override fun getText() = "Make '${element.name}' an annotation class"
super(annotationEntry);
this.annotationEntry = annotationEntry; public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
element.addModifier(KtTokens.ANNOTATION_KEYWORD)
} }
@Override companion object : KotlinSingleIntentionActionFactory() {
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiFile file) { override fun createAction(diagnostic: Diagnostic): IntentionAction? {
if (!super.isAvailable(project, editor, file)) { val typeReference = diagnostic.psiElement.getNonStrictParentOfType<KtAnnotationEntry>()?.typeReference ?: return null
return false; 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);
}
};
}
}
@@ -213,7 +213,7 @@ class QuickFixRegistrar : QuickFixContributor {
PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(false)) PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(false))
PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE.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() val changeVariableTypeFix = ChangeVariableTypeFix.createFactoryForPropertyOrReturnTypeMismatchOnOverride()
RETURN_TYPE_MISMATCH_ON_OVERRIDE.registerFactory(changeVariableTypeFix) RETURN_TYPE_MISMATCH_ON_OVERRIDE.registerFactory(changeVariableTypeFix)