mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
JvmCommonIntentionActionsFactory switched from UAST to @JvmCommon-annotated API
This commit is contained in:
+56
-23
@@ -17,13 +17,13 @@ package com.intellij.codeInsight.intention
|
||||
|
||||
import com.intellij.lang.Language
|
||||
import com.intellij.lang.LanguageExtension
|
||||
import com.intellij.psi.PsiModifier
|
||||
import com.intellij.psi.PsiType
|
||||
import com.intellij.psi.PsiTypeParameter
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.uast.UClass
|
||||
import org.jetbrains.uast.UDeclaration
|
||||
import org.jetbrains.uast.UParameter
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.UastContext
|
||||
|
||||
/**
|
||||
* Extension Point provides language-abstracted code modifications for JVM-based languages.
|
||||
@@ -38,18 +38,22 @@ import org.jetbrains.uast.UParameter
|
||||
@ApiStatus.Experimental
|
||||
abstract class JvmCommonIntentionActionsFactory {
|
||||
|
||||
open fun createChangeModifierAction(declaration: UDeclaration,
|
||||
open fun createChangeModifierAction(declaration: @JvmCommon PsiModifierListOwner,
|
||||
@PsiModifier.ModifierConstant modifier: String,
|
||||
shouldPresent: Boolean): IntentionAction? = null
|
||||
shouldPresent: Boolean): IntentionAction? =
|
||||
//Fallback if Uast-version of method is overridden
|
||||
createChangeModifierAction(declaration.asUast<UDeclaration>(), modifier, shouldPresent)
|
||||
|
||||
open fun createAddCallableMemberActions(info: MethodInsertionInfo): List<IntentionAction> = emptyList()
|
||||
|
||||
open fun createAddBeanPropertyActions(uClass: UClass,
|
||||
open fun createAddBeanPropertyActions(psiClass: @JvmCommon PsiClass,
|
||||
propertyName: String,
|
||||
@PsiModifier.ModifierConstant visibilityModifier: String,
|
||||
propertyType: PsiType,
|
||||
setterRequired: Boolean,
|
||||
getterRequired: Boolean): List<IntentionAction> = emptyList()
|
||||
getterRequired: Boolean): List<IntentionAction> =
|
||||
//Fallback if Uast-version of method is overridden
|
||||
createAddBeanPropertyActions(psiClass.asUast<UClass>(), propertyName, visibilityModifier, propertyType, setterRequired, getterRequired)
|
||||
|
||||
companion object : LanguageExtension<JvmCommonIntentionActionsFactory>(
|
||||
"com.intellij.codeInsight.intention.jvmCommonIntentionActionsFactory") {
|
||||
@@ -58,49 +62,78 @@ abstract class JvmCommonIntentionActionsFactory {
|
||||
override fun forLanguage(l: Language): JvmCommonIntentionActionsFactory? = super.forLanguage(l)
|
||||
}
|
||||
|
||||
//A fallback to old api
|
||||
@Deprecated("use or/and override @JvmCommon-version of this method instead")
|
||||
open fun createChangeModifierAction(declaration: UDeclaration,
|
||||
@PsiModifier.ModifierConstant modifier: String,
|
||||
shouldPresent: Boolean): IntentionAction? = null
|
||||
|
||||
@Deprecated("use or/and override @JvmCommon-version of this method instead")
|
||||
open fun createAddBeanPropertyActions(uClass: UClass,
|
||||
propertyName: String,
|
||||
@PsiModifier.ModifierConstant visibilityModifier: String,
|
||||
propertyType: PsiType,
|
||||
setterRequired: Boolean,
|
||||
getterRequired: Boolean): List<IntentionAction> = emptyList()
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
sealed class MethodInsertionInfo(
|
||||
val containingClass: UClass,
|
||||
val targetClass: @JvmCommon PsiClass,
|
||||
@PsiModifier.ModifierConstant
|
||||
val modifiers: List<String> = emptyList(),
|
||||
val typeParams: List<PsiTypeParameter> = emptyList(),
|
||||
val parameters: List<UParameter> = emptyList()
|
||||
val parameters: List<@JvmCommon PsiParameter> = emptyList()
|
||||
) {
|
||||
|
||||
@Deprecated("use `targetClass`", ReplaceWith("targetClass"))
|
||||
val containingClass: UClass
|
||||
get() = targetClass.asUast<UClass>()
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun constructorInfo(containingClass: UClass, parameters: List<UParameter>) =
|
||||
Constructor(containingClass = containingClass, parameters = parameters)
|
||||
fun constructorInfo(targetClass: @JvmCommon PsiClass, parameters: List<@JvmCommon PsiParameter>) =
|
||||
Constructor(targetClass = targetClass, parameters = parameters)
|
||||
|
||||
@JvmStatic
|
||||
fun simpleMethodInfo(containingClass: UClass,
|
||||
fun simpleMethodInfo(containingClass: @JvmCommon PsiClass,
|
||||
methodName: String,
|
||||
@PsiModifier.ModifierConstant modifier: String,
|
||||
returnType: PsiType,
|
||||
parameters: List<UParameter>) =
|
||||
parameters: List<@JvmCommon PsiParameter>) =
|
||||
Method(name = methodName,
|
||||
modifiers = listOf(modifier),
|
||||
containingClass = containingClass,
|
||||
targetClass = containingClass,
|
||||
returnType = returnType,
|
||||
parameters = parameters)
|
||||
|
||||
}
|
||||
|
||||
class Method(
|
||||
containingClass: UClass,
|
||||
targetClass: @JvmCommon PsiClass,
|
||||
val name: String,
|
||||
modifiers: List<String> = emptyList(),
|
||||
typeParams: List<PsiTypeParameter> = emptyList(),
|
||||
typeParams: List<@JvmCommon PsiTypeParameter> = emptyList(),
|
||||
val returnType: PsiType,
|
||||
parameters: List<UParameter> = emptyList(),
|
||||
parameters: List<@JvmCommon PsiParameter> = emptyList(),
|
||||
val isAbstract: Boolean = false
|
||||
) : MethodInsertionInfo(containingClass, modifiers, typeParams, parameters)
|
||||
) : MethodInsertionInfo(targetClass, modifiers, typeParams, parameters)
|
||||
|
||||
class Constructor(
|
||||
containingClass: UClass,
|
||||
targetClass: @JvmCommon PsiClass,
|
||||
modifiers: List<String> = emptyList(),
|
||||
typeParams: List<PsiTypeParameter> = emptyList(),
|
||||
parameters: List<UParameter> = emptyList()
|
||||
) : MethodInsertionInfo(containingClass, modifiers, typeParams, parameters)
|
||||
typeParams: List<@JvmCommon PsiTypeParameter> = emptyList(),
|
||||
parameters: List<@JvmCommon PsiParameter> = emptyList()
|
||||
) : MethodInsertionInfo(targetClass, modifiers, typeParams, parameters)
|
||||
|
||||
}
|
||||
|
||||
@Deprecated("remove after kotlin plugin will be ported")
|
||||
private inline fun <reified T : UElement> PsiElement.asUast(): T = when (this) {
|
||||
is T -> this
|
||||
else -> this.let { ServiceManager.getService(project, UastContext::class.java).convertElement(this, null, T::class.java) as T? }
|
||||
?: throw UnsupportedOperationException("cant convert $this to ${T::class}")
|
||||
}
|
||||
+3
-2
@@ -17,8 +17,8 @@ package com.intellij.codeInspection.inheritance
|
||||
|
||||
import com.intellij.CommonBundle
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle
|
||||
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory
|
||||
import com.intellij.codeInspection.*
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
@@ -185,7 +185,8 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
shouldPresent: Boolean,
|
||||
actionsList: SmartList<IntentionAction>) {
|
||||
if (declaration.modifierList?.hasModifierProperty(name) != shouldPresent) {
|
||||
(actionsFactory.createChangeModifierAction(declaration, name, shouldPresent))?.let {
|
||||
(actionsFactory.createChangeModifierAction(declaration as @com.intellij.psi.JvmCommon PsiModifierListOwner, name,
|
||||
shouldPresent))?.let {
|
||||
actionsList.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
+37
-23
@@ -22,46 +22,47 @@ import com.intellij.codeInsight.intention.AbstractIntentionAction
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory
|
||||
import com.intellij.codeInsight.intention.MethodInsertionInfo
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager
|
||||
import com.intellij.psi.impl.beanProperties.CreateJavaBeanPropertyFix
|
||||
import com.intellij.psi.util.PsiFormatUtil
|
||||
import com.intellij.psi.util.PsiFormatUtilBase
|
||||
import com.intellij.util.VisibilityUtil
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.uast.UClass
|
||||
import org.jetbrains.uast.UDeclaration
|
||||
import org.jetbrains.uast.UParameter
|
||||
|
||||
|
||||
class JavaCommonIntentionActionsFactory : JvmCommonIntentionActionsFactory() {
|
||||
|
||||
override fun createChangeModifierAction(declaration: UDeclaration, modifier: String, shouldPresent: Boolean): IntentionAction {
|
||||
override fun createChangeModifierAction(declaration: @JvmCommon PsiModifierListOwner,
|
||||
modifier: String,
|
||||
shouldPresent: Boolean): IntentionAction {
|
||||
return ModifierFix(declaration.modifierList, modifier, shouldPresent, false)
|
||||
}
|
||||
|
||||
override fun createAddCallableMemberActions(info: MethodInsertionInfo): List<IntentionAction> {
|
||||
return when (info) {
|
||||
is MethodInsertionInfo.Method -> with(info) {
|
||||
createAddMethodAction(containingClass, name, modifiers.joinToString(" "), returnType, parameters)
|
||||
createAddMethodAction(targetClass, name, modifiers.joinToString(" "), returnType, parameters)
|
||||
?.let { listOf(it) } ?: emptyList()
|
||||
}
|
||||
|
||||
is MethodInsertionInfo.Constructor ->
|
||||
listOf(AddConstructorFix(info.containingClass.psi, info.parameters.map { it.psi }))
|
||||
listOf(AddConstructorFix(info.targetClass.javaPsi(), info.parameters.map { it.javaPsi() }))
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAddMethodAction(uClass: UClass,
|
||||
private fun createAddMethodAction(psiClass: @JvmCommon PsiClass,
|
||||
methodName: String,
|
||||
@PsiModifier.ModifierConstant @NotNull visibilityModifier: String,
|
||||
returnType: PsiType,
|
||||
parameters: List<UParameter>): IntentionAction? {
|
||||
val paramsString = parameters.mapIndexed { i, t -> "${t.type.presentableText} ${t.name ?: "arg$i"}" }.joinToString()
|
||||
parameters: List<@JvmCommon PsiParameter>): IntentionAction? {
|
||||
val paramsString = parameters.mapIndexed { i, t -> "${t.type.canonicalText} ${t.name ?: "arg$i"}" }.joinToString()
|
||||
val signatureString =
|
||||
"${VisibilityUtil.getVisibilityString(visibilityModifier)} ${returnType.presentableText} $methodName($paramsString){}"
|
||||
val targetClassPointer = SmartPointerManager.getInstance(uClass.project).createSmartPsiElementPointer(uClass.psi)
|
||||
"${VisibilityUtil.getVisibilityString(visibilityModifier)} ${returnType.canonicalText} $methodName($paramsString){}"
|
||||
val targetClassPointer = SmartPointerManager.getInstance(psiClass.project).createSmartPsiElementPointer(psiClass.javaPsi())
|
||||
return object : AbstractIntentionAction() {
|
||||
|
||||
private val text = targetClassPointer.element?.let { psiClass ->
|
||||
@@ -77,17 +78,30 @@ class JavaCommonIntentionActionsFactory : JvmCommonIntentionActionsFactory() {
|
||||
override fun getText(): String = text
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile) {
|
||||
targetClassPointer.element?.let { targetClass ->
|
||||
targetClass.add(createMethod(targetClass))
|
||||
val targetClass = targetClassPointer.element ?: return
|
||||
runWriteAction {
|
||||
val addedMethod = targetClass.add(createMethod(targetClass))
|
||||
JavaCodeStyleManager.getInstance(project).shortenClassReferences(addedMethod)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMethod(targetClass: PsiClass): PsiMethod = PsiElementFactory.SERVICE.getInstance(targetClass.project)
|
||||
.createMethodFromText(signatureString, targetClass)
|
||||
private fun createMethod(targetClass: PsiClass): PsiMethod {
|
||||
val elementFactory = JVMElementFactories.getFactory(targetClass.language, targetClass.project) // it could be Groovy
|
||||
?: JavaPsiFacade.getElementFactory(targetClass.project)
|
||||
return elementFactory.createMethodFromText(signatureString, targetClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createAddBeanPropertyActions(uClass: UClass,
|
||||
private inline fun <reified T : PsiElement> T.javaPsi(): T {
|
||||
assert(language == JavaLanguage.INSTANCE)
|
||||
return when (this) {
|
||||
is org.jetbrains.uast.UElement -> psi as T
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
override fun createAddBeanPropertyActions(psiClass: @JvmCommon PsiClass,
|
||||
propertyName: String,
|
||||
@PsiModifier.ModifierConstant visibilityModifier: String,
|
||||
propertyType: PsiType,
|
||||
@@ -95,20 +109,20 @@ class JavaCommonIntentionActionsFactory : JvmCommonIntentionActionsFactory() {
|
||||
getterRequired: Boolean): List<IntentionAction> {
|
||||
if (getterRequired && setterRequired)
|
||||
return listOf<IntentionAction>(
|
||||
CreateJavaBeanPropertyFix(uClass.psi, propertyName, propertyType, getterRequired, setterRequired,
|
||||
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired,
|
||||
true),
|
||||
CreateJavaBeanPropertyFix(uClass.psi, propertyName, propertyType, getterRequired, setterRequired,
|
||||
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired,
|
||||
false))
|
||||
if (getterRequired || setterRequired)
|
||||
return listOf<IntentionAction>(
|
||||
CreateJavaBeanPropertyFix(uClass.psi, propertyName, propertyType, getterRequired, setterRequired,
|
||||
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired,
|
||||
true),
|
||||
CreateJavaBeanPropertyFix(uClass.psi, propertyName, propertyType, getterRequired, setterRequired,
|
||||
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired,
|
||||
false),
|
||||
CreateJavaBeanPropertyFix(uClass.psi, propertyName, propertyType, true, true, true))
|
||||
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, true, true, true))
|
||||
|
||||
return listOf<IntentionAction>(
|
||||
CreateJavaBeanPropertyFix(uClass.psi, propertyName, propertyType, getterRequired, setterRequired, true))
|
||||
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired, true))
|
||||
}
|
||||
|
||||
}
|
||||
+5
-8
@@ -25,8 +25,6 @@ import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.uast.UClass;
|
||||
import org.jetbrains.uast.UastContextKt;
|
||||
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
|
||||
import static com.intellij.util.ArrayUtil.toObjectArray;
|
||||
@@ -35,14 +33,14 @@ import static com.intellij.util.ArrayUtil.toObjectArray;
|
||||
public class CreateBeanPropertyFixes {
|
||||
|
||||
public static LocalQuickFix[] createFixes(String propertyName,
|
||||
@NotNull PsiClass psiClass,
|
||||
@NotNull @JvmCommon PsiClass psiClass,
|
||||
@Nullable PsiType type,
|
||||
final boolean createSetter) {
|
||||
return IntentionWrapper.wrapToQuickFixes(createActions(propertyName, psiClass, type, createSetter), psiClass.getContainingFile());
|
||||
}
|
||||
|
||||
public static IntentionAction[] createActions(String propertyName,
|
||||
@NotNull PsiClass psiClass,
|
||||
@NotNull @JvmCommon PsiClass psiClass,
|
||||
@Nullable PsiType type,
|
||||
final boolean createSetter) {
|
||||
if (psiClass instanceof PsiCompiledElement) return IntentionAction.EMPTY_ARRAY;
|
||||
@@ -55,9 +53,8 @@ public class CreateBeanPropertyFixes {
|
||||
}
|
||||
JvmCommonIntentionActionsFactory factory = JvmCommonIntentionActionsFactory.forLanguage(psiClass.getLanguage());
|
||||
if (factory == null) return IntentionAction.EMPTY_ARRAY;
|
||||
UClass uClass = UastContextKt.toUElement(psiClass, UClass.class);
|
||||
if (uClass == null) return IntentionAction.EMPTY_ARRAY;
|
||||
return toObjectArray(factory.createAddBeanPropertyActions(uClass, propertyName, PsiModifier.PUBLIC, type, createSetter, !createSetter),
|
||||
IntentionAction.class);
|
||||
return toObjectArray(
|
||||
factory.createAddBeanPropertyActions(psiClass, propertyName, PsiModifier.PUBLIC, type, createSetter, !createSetter),
|
||||
IntentionAction.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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 com.intellij.psi;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Annotation for marking {@link PsiElement} subclasses usages that they will be used in
|
||||
* language-abstracted way:
|
||||
* <ul>
|
||||
* <li>No modification methods should be directly called on such instances</li>
|
||||
* <li>Usages should be aware of {@link PsiElement#getLanguage()}, and not be hardcoded to dedicated language</li>
|
||||
* <li>Instances could be "virtual" and don't have physical representations</li>
|
||||
* <li>Complex operations should be performed via corresponding {@link com.intellij.lang.LanguageExtensionPoint} or similar API</li>
|
||||
* <li>{@link org.jetbrains.uast.UClass}-like instances should be supported</li>
|
||||
* </ul>
|
||||
* <b>Note:</b> this annotation considered as kind-of "transitional" until generic language-independent API will be implemented
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
@Target({
|
||||
ElementType.TYPE, ElementType.PARAMETER, ElementType.FIELD, ElementType.TYPE_USE, ElementType.TYPE_PARAMETER
|
||||
})
|
||||
public @interface JvmCommon {
|
||||
}
|
||||
Reference in New Issue
Block a user