From c3d53503151b6dac71150305666a89feb725f4ed Mon Sep 17 00:00:00 2001 From: Wojciech Lopata Date: Thu, 14 Feb 2013 17:20:42 +0100 Subject: [PATCH] QuickFix for NOT_AN_ANNOTATION_CLASS error. --- .../jetbrains/jet/plugin/JetBundle.properties | 2 + .../MakeClassAnAnnotationClassFix.java | 103 ++++++++++++++++++ .../jet/plugin/quickfix/QuickFixes.java | 2 + .../modifiers/afterNotAnAnnotationClass.kt | 4 + .../beforeCannotMakeClassAnnotation.kt | 3 + .../modifiers/beforeNotAnAnnotationClass.kt | 4 + .../quickfix/QuickFixTestGenerated.java | 10 ++ 7 files changed, 128 insertions(+) create mode 100644 idea/src/org/jetbrains/jet/plugin/quickfix/MakeClassAnAnnotationClassFix.java create mode 100644 idea/testData/quickfix/modifiers/afterNotAnAnnotationClass.kt create mode 100644 idea/testData/quickfix/modifiers/beforeCannotMakeClassAnnotation.kt create mode 100644 idea/testData/quickfix/modifiers/beforeNotAnAnnotationClass.kt diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index d8337e7e757..a7b31a008af 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -13,6 +13,8 @@ make.element.modifier=Make {0} {1} add.modifier=Add ''{0}'' modifier add.supertype.modifier=Add ''{0}'' modifier to supertype add.supertype.modifier.family=Add modifier to supertype +make.class.annotation.class=Make ''{0}'' an annotation class +make.class.annotation.class.family=Make class an annotation class add.star.projections=Add ''{0}'' make.element.not.modifier=Make {0} not {1} remove.modifier=Remove ''{0}'' modifier diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/MakeClassAnAnnotationClassFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/MakeClassAnAnnotationClassFix.java new file mode 100644 index 00000000000..3abd59b6752 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/MakeClassAnAnnotationClassFix.java @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2013 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.jet.plugin.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.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.JetAnnotationEntry; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.plugin.JetBundle; +import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager; + +import static org.jetbrains.jet.lexer.JetTokens.ANNOTATION_KEYWORD; + +public class MakeClassAnAnnotationClassFix extends JetIntentionAction { + private final JetAnnotationEntry annotationEntry; + private JetType annotationType; + private JetClass annotationClass; + + public MakeClassAnAnnotationClassFix(@NotNull JetAnnotationEntry annotationEntry) { + super(annotationEntry); + this.annotationEntry = annotationEntry; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + if (!super.isAvailable(project, editor, file)) { + return false; + } + + BindingContext context = KotlinCacheManager.getInstance(project).getDeclarationsFromProject(project).getBindingContext(); + AnnotationDescriptor annotationDescriptor = context.get(BindingContext.ANNOTATION, annotationEntry); + if (annotationDescriptor == null) { + return false; + } + annotationType = annotationDescriptor.getType(); + DeclarationDescriptor declarationDescriptor = annotationType.getConstructor().getDeclarationDescriptor(); + if (declarationDescriptor == null) { + return false; + } + PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, declarationDescriptor); + if (declaration instanceof JetClass) { + annotationClass = (JetClass) declaration; + return annotationClass.isWritable(); + } + return false; + } + + @NotNull + @Override + public String getText() { + return JetBundle.message("make.class.annotation.class", annotationType); + } + + @NotNull + @Override + public String getFamilyName() { + return JetBundle.message("make.class.annotation.class.family"); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + annotationClass.replace(AddModifierFix.addModifier(annotationClass, ANNOTATION_KEYWORD, null, project, false)); + } + + @NotNull + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { + @Nullable + @Override + public IntentionAction createAction(Diagnostic diagnostic) { + JetAnnotationEntry annotation = QuickFixUtil.getParentElementOfType(diagnostic, JetAnnotationEntry.class); + return annotation == null ? null : new MakeClassAnAnnotationClassFix(annotation); + } + }; + } +} + diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index 02569997685..ccd2d287562 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -176,5 +176,7 @@ public class QuickFixes { factories.put(OPEN_MODIFIER_IN_ENUM, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OPEN_KEYWORD)); factories.put(ILLEGAL_ENUM_ANNOTATION, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ENUM_KEYWORD)); + + factories.put(NOT_AN_ANNOTATION_CLASS, MakeClassAnAnnotationClassFix.createFactory()); } } diff --git a/idea/testData/quickfix/modifiers/afterNotAnAnnotationClass.kt b/idea/testData/quickfix/modifiers/afterNotAnAnnotationClass.kt new file mode 100644 index 00000000000..1af416e4fe5 --- /dev/null +++ b/idea/testData/quickfix/modifiers/afterNotAnAnnotationClass.kt @@ -0,0 +1,4 @@ +// "Make 'fancy' an annotation class" "true" +annotation class fancy + +[fancy] class foo {} diff --git a/idea/testData/quickfix/modifiers/beforeCannotMakeClassAnnotation.kt b/idea/testData/quickfix/modifiers/beforeCannotMakeClassAnnotation.kt new file mode 100644 index 00000000000..0b07ad8d99e --- /dev/null +++ b/idea/testData/quickfix/modifiers/beforeCannotMakeClassAnnotation.kt @@ -0,0 +1,3 @@ +// "Make 'String' an annotation class" "false" +// ERROR: 'String' is not an annotation class +[String] class foo {} diff --git a/idea/testData/quickfix/modifiers/beforeNotAnAnnotationClass.kt b/idea/testData/quickfix/modifiers/beforeNotAnAnnotationClass.kt new file mode 100644 index 00000000000..1792bd97baa --- /dev/null +++ b/idea/testData/quickfix/modifiers/beforeNotAnAnnotationClass.kt @@ -0,0 +1,4 @@ +// "Make 'fancy' an annotation class" "true" +class fancy + +[fancy] class foo {} diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java index fb00222b6a3..c8ba83a57f1 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java @@ -403,6 +403,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/modifiers"), Pattern.compile("^before(\\w+)\\.kt$"), true); } + @TestMetadata("beforeCannotMakeClassAnnotation.kt") + public void testCannotMakeClassAnnotation() throws Exception { + doTest("idea/testData/quickfix/modifiers/beforeCannotMakeClassAnnotation.kt"); + } + @TestMetadata("beforeFinalTrait.kt") public void testFinalTrait() throws Exception { doTest("idea/testData/quickfix/modifiers/beforeFinalTrait.kt"); @@ -418,6 +423,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest("idea/testData/quickfix/modifiers/beforeIllegalEnumAnnotation2.kt"); } + @TestMetadata("beforeNotAnAnnotationClass.kt") + public void testNotAnAnnotationClass() throws Exception { + doTest("idea/testData/quickfix/modifiers/beforeNotAnAnnotationClass.kt"); + } + @TestMetadata("beforeOpenMemberInFinalClass1.kt") public void testOpenMemberInFinalClass1() throws Exception { doTest("idea/testData/quickfix/modifiers/beforeOpenMemberInFinalClass1.kt");