diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddModifierFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddModifierFix.kt index da0f3ea9f18..ce977da7ca7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddModifierFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddModifierFix.kt @@ -20,16 +20,18 @@ import com.intellij.codeInsight.intention.IntentionAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.psi.PsiNameIdentifierOwner +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.JetBundle +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens.ABSTRACT_KEYWORD -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtModifierListOwner -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.jetbrains.kotlin.psi.KtPropertyAccessor +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode open class AddModifierFix( element: KtModifierListOwner, @@ -85,4 +87,17 @@ open class AddModifierFix( } } } + + object MakeClassOpenFactory : JetSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val typeReference = diagnostic.psiElement as KtTypeReference + val bindingContext = typeReference.analyze(BodyResolveMode.PARTIAL) + val type = bindingContext[BindingContext.TYPE, typeReference] ?: return null + val classDescriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null + val declaration = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor) as? KtClass ?: return null + if (!QuickFixUtil.canModifyElement(declaration)) return null + if (declaration.isEnum()) return null + return AddModifierFix(declaration, KtTokens.OPEN_KEYWORD) + } + } } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddOpenModifierToClassDeclarationFix.java b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddOpenModifierToClassDeclarationFix.java deleted file mode 100644 index 96ebad1cb48..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddOpenModifierToClassDeclarationFix.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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.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.JetBundle; -import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil; -import org.jetbrains.kotlin.idea.references.ReferenceUtilKt; -import org.jetbrains.kotlin.lexer.KtTokens; -import org.jetbrains.kotlin.psi.*; - -public class AddOpenModifierToClassDeclarationFix extends KotlinQuickFixAction { - private KtClass classDeclaration; - - public AddOpenModifierToClassDeclarationFix(@NotNull KtTypeReference typeReference) { - super(typeReference); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - if (!super.isAvailable(project, editor, file)) { - return false; - } - - KtSimpleNameExpression referenceExpression = PsiTreeUtil.findChildOfType(getElement(), KtSimpleNameExpression.class); - if (referenceExpression == null) { - return false; - } - - PsiReference reference = ReferenceUtilKt.getMainReference(referenceExpression); - PsiElement target = reference.resolve(); - if (target instanceof KtSecondaryConstructor) { - target = ((KtSecondaryConstructor) target).getContainingClassOrObject(); - } - if (target instanceof KtClass && QuickFixUtil.canModifyElement(target)) { - classDeclaration = (KtClass) target; - return !(classDeclaration.isEnum() || classDeclaration.isInterface()); - } - - return false; - } - - @NotNull - @Override - public String getText() { - return JetBundle.message("make.element.modifier", classDeclaration != null ? classDeclaration.getName() : "", "open"); - } - - @NotNull - @Override - public String getFamilyName() { - return JetBundle.message("add.modifier.family"); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, KtFile file) throws IncorrectOperationException { - classDeclaration.addModifier(KtTokens.OPEN_KEYWORD); - } - - @NotNull - public static JetSingleIntentionActionFactory createFactory() { - return new JetSingleIntentionActionFactory() { - @Nullable - @Override - public IntentionAction createAction(Diagnostic diagnostic) { - KtTypeReference typeReference = QuickFixUtil.getParentElementOfType(diagnostic, KtTypeReference.class); - return typeReference == null ? null : new AddOpenModifierToClassDeclarationFix(typeReference); - } - }; - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 4c75222cff9..52c5c08fa3f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -195,9 +195,8 @@ public class QuickFixRegistrar : QuickFixContributor { INACCESSIBLE_OUTER_CLASS_EXPRESSION.registerFactory(AddModifierFix.createFactory(INNER_KEYWORD, javaClass())) - val addOpenModifierToClassDeclarationFix = AddOpenModifierToClassDeclarationFix.createFactory() - FINAL_SUPERTYPE.registerFactory(addOpenModifierToClassDeclarationFix) - FINAL_UPPER_BOUND.registerFactory(addOpenModifierToClassDeclarationFix) + FINAL_SUPERTYPE.registerFactory(AddModifierFix.MakeClassOpenFactory) + FINAL_UPPER_BOUND.registerFactory(AddModifierFix.MakeClassOpenFactory) OVERRIDING_FINAL_MEMBER.registerFactory(MakeOverriddenMemberOpenFix) diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/enumSupertype.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/enumSupertype.kt index eda74fa9d2a..cf91ce3b4fc 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/enumSupertype.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/enumSupertype.kt @@ -1,4 +1,4 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddOpenModifierToClassDeclarationFix" "false" +// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" // ERROR: This type is final, so it cannot be inherited from // ERROR: Cannot access '': it is 'private' in 'E' enum class E {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/enumUpperBound.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/enumUpperBound.kt index bba4e2ef3dc..ebc8554dac6 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/enumUpperBound.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/enumUpperBound.kt @@ -1,3 +1,3 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddOpenModifierToClassDeclarationFix" "false" +// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" enum class E {} class A> {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalSupertype.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalSupertype.kt index 2e7c157919f..379fc2e0fe1 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalSupertype.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalSupertype.kt @@ -1,3 +1,3 @@ -// "Make A open" "true" +// "Make 'A' open" "true" final class A {} class B : A() {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalSupertype.kt.after b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalSupertype.kt.after index 1aeebf3f9e8..d801bcb4d7b 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalSupertype.kt.after +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalSupertype.kt.after @@ -1,3 +1,3 @@ -// "Make A open" "true" +// "Make 'A' open" "true" open class A {} class B : A() {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalUpperBound.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalUpperBound.kt index 1c298afb8b6..46948a6d5de 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalUpperBound.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalUpperBound.kt @@ -1,3 +1,3 @@ -// "Make A open" "true" +// "Make 'A' open" "true" final class A {} class B> {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalUpperBound.kt.after b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalUpperBound.kt.after index d962ff70b4b..8d8d70c2d31 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalUpperBound.kt.after +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/explicitlyFinalUpperBound.kt.after @@ -1,3 +1,3 @@ -// "Make A open" "true" +// "Make 'A' open" "true" open class A {} class B> {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaClass/FinalJavaSupertype.before.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaClass/FinalJavaSupertype.before.kt index a18d6d9818c..1bf375231a1 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaClass/FinalJavaSupertype.before.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaClass/FinalJavaSupertype.before.kt @@ -1,4 +1,4 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddOpenModifierToClassDeclarationFix" "false" +// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" // ERROR: This type is final, so it cannot be inherited from // ACTION: Create test import testPackage.* diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaClass/FinalJavaUpperBound.before.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaClass/FinalJavaUpperBound.before.kt index 0b7f0f28b1a..dd1a8c38e66 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaClass/FinalJavaUpperBound.before.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalJavaClass/FinalJavaUpperBound.before.kt @@ -1,4 +1,4 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddOpenModifierToClassDeclarationFix" "false" +// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" import testPackage.* class foo() {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibrarySupertype.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibrarySupertype.kt index 5b294760e60..d2ac8296e01 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibrarySupertype.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibrarySupertype.kt @@ -1,3 +1,3 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddOpenModifierToClassDeclarationFix" "false" +// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" // ERROR: This type is final, so it cannot be inherited from class A : String() {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibraryUpperBound.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibraryUpperBound.kt index 2acea138dc6..4067a679d7f 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibraryUpperBound.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalLibraryUpperBound.kt @@ -1,2 +1,2 @@ -// "class org.jetbrains.kotlin.idea.quickfix.AddOpenModifierToClassDeclarationFix" "false" +// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false" class A> {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalSupertype.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalSupertype.kt index 845d8ec4daf..ae4364f7947 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalSupertype.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalSupertype.kt @@ -1,3 +1,3 @@ -// "Make A open" "true" +// "Make 'A' open" "true" class A {} class B : A() {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalSupertype.kt.after b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalSupertype.kt.after index 1aeebf3f9e8..d801bcb4d7b 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalSupertype.kt.after +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalSupertype.kt.after @@ -1,3 +1,3 @@ -// "Make A open" "true" +// "Make 'A' open" "true" open class A {} class B : A() {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalUpperBound.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalUpperBound.kt index 1c298afb8b6..46948a6d5de 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalUpperBound.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalUpperBound.kt @@ -1,3 +1,3 @@ -// "Make A open" "true" +// "Make 'A' open" "true" final class A {} class B> {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalUpperBound.kt.after b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalUpperBound.kt.after index d962ff70b4b..8d8d70c2d31 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalUpperBound.kt.after +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/finalUpperBound.kt.after @@ -1,3 +1,3 @@ -// "Make A open" "true" +// "Make 'A' open" "true" open class A {} class B> {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/implementTraitFinalSupertype.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/implementTraitFinalSupertype.kt index b1623460e9a..53523c3292a 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/implementTraitFinalSupertype.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/implementTraitFinalSupertype.kt @@ -1,4 +1,4 @@ -// "Make A open" "true" +// "Make 'A' open" "true" interface X {} interface Y {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/implementTraitFinalSupertype.kt.after b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/implementTraitFinalSupertype.kt.after index 805ef93115f..e42400231ba 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/implementTraitFinalSupertype.kt.after +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/implementTraitFinalSupertype.kt.after @@ -1,4 +1,4 @@ -// "Make A open" "true" +// "Make 'A' open" "true" interface X {} interface Y {} diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInHeader.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInHeader.kt index 2919f62d66f..683c94923f9 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInHeader.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInHeader.kt @@ -1,4 +1,4 @@ -// "Make B open" "true" +// "Make 'B' open" "true" class B { constructor() { } diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInHeader.kt.after b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInHeader.kt.after index de092c6b347..bf03e57981d 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInHeader.kt.after +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInHeader.kt.after @@ -1,4 +1,4 @@ -// "Make B open" "true" +// "Make 'B' open" "true" open class B { constructor() { } diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInSecondary.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInSecondary.kt index 728fb349dc2..825f57f6cee 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInSecondary.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInSecondary.kt @@ -1,4 +1,4 @@ -// "Make B open" "true" +// "Make 'B' open" "true" class B { constructor() { } diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInSecondary.kt.after b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInSecondary.kt.after index c4d8c08c93a..3b7f28e88c6 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInSecondary.kt.after +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/secondaryCtrDelegationInSecondary.kt.after @@ -1,4 +1,4 @@ -// "Make B open" "true" +// "Make 'B' open" "true" open class B { constructor() { } diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/withConstructor.kt b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/withConstructor.kt index 553c256cd58..c5bf42500ec 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/withConstructor.kt +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/withConstructor.kt @@ -1,4 +1,4 @@ -// "Make A open" "true" +// "Make 'A' open" "true" class A(val v: Int) -class B : A() +class B : A(1) diff --git a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/withConstructor.kt.after b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/withConstructor.kt.after index 33c3dea7641..78386d8671d 100644 --- a/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/withConstructor.kt.after +++ b/idea/testData/quickfix/modifiers/addOpenToClassDeclaration/withConstructor.kt.after @@ -1,4 +1,4 @@ -// "Make A open" "true" +// "Make 'A' open" "true" open class A(val v: Int) -class B : A() +class B : A(1)