JvmCommonIntentionActionsFactory switched to com.intellij.lang.jvm.* api and renamed to JvmElementActionsFactory

old `JvmCommonIntentionActionsFactory` reverted to "UAST"-state and deprecated
This commit is contained in:
Nicolay Mitropolsky
2017-08-03 16:59:04 +03:00
parent d7354396b5
commit 9e4153f60f
13 changed files with 544 additions and 222 deletions
@@ -17,13 +17,13 @@ package com.intellij.codeInsight.intention
import com.intellij.lang.Language
import com.intellij.lang.LanguageExtension
import com.intellij.openapi.components.ServiceManager
import com.intellij.psi.*
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiType
import com.intellij.psi.PsiTypeParameter
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.uast.UClass
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UastContext
import org.jetbrains.uast.UParameter
/**
* Extension Point provides language-abstracted code modifications for JVM-based languages.
@@ -36,24 +36,21 @@ import org.jetbrains.uast.UastContext
* @since 2017.2
*/
@ApiStatus.Experimental
@Deprecated("to be removed in 2017.3", ReplaceWith("com.intellij.lang.jvm.actions.JvmCommonIntentionActionsFactory"))
abstract class JvmCommonIntentionActionsFactory {
open fun createChangeModifierAction(declaration: @JvmCommon PsiModifierListOwner,
open fun createChangeModifierAction(declaration: UDeclaration,
@PsiModifier.ModifierConstant modifier: String,
shouldPresent: Boolean): IntentionAction? =
//Fallback if Uast-version of method is overridden
createChangeModifierAction(declaration.asUast<UDeclaration>(), modifier, shouldPresent)
shouldPresent: Boolean): IntentionAction? = null
open fun createAddCallableMemberActions(info: MethodInsertionInfo): List<IntentionAction> = emptyList()
open fun createAddBeanPropertyActions(psiClass: @JvmCommon PsiClass,
open fun createAddBeanPropertyActions(uClass: UClass,
propertyName: String,
@PsiModifier.ModifierConstant visibilityModifier: String,
propertyType: PsiType,
setterRequired: Boolean,
getterRequired: Boolean): List<IntentionAction> =
//Fallback if Uast-version of method is overridden
createAddBeanPropertyActions(psiClass.asUast<UClass>(), propertyName, visibilityModifier, propertyType, setterRequired, getterRequired)
getterRequired: Boolean): List<IntentionAction> = emptyList()
companion object : LanguageExtension<JvmCommonIntentionActionsFactory>(
"com.intellij.codeInsight.intention.jvmCommonIntentionActionsFactory") {
@@ -62,78 +59,52 @@ 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
@Deprecated("to be removed in 2017.3", ReplaceWith("com.intellij.lang.jvm.actions.JvmCommonIntentionActionsFactory"))
sealed class MethodInsertionInfo(
val targetClass: @JvmCommon PsiClass,
val containingClass: UClass,
@PsiModifier.ModifierConstant
val modifiers: List<String> = emptyList(),
val typeParams: List<PsiTypeParameter> = emptyList(),
val parameters: List<@JvmCommon PsiParameter> = emptyList()
val parameters: List<UParameter> = emptyList()
) {
@Deprecated("use `targetClass`", ReplaceWith("targetClass"))
val containingClass: UClass
get() = targetClass.asUast<UClass>()
companion object {
@JvmStatic
fun constructorInfo(targetClass: @JvmCommon PsiClass, parameters: List<@JvmCommon PsiParameter>) =
Constructor(targetClass = targetClass, parameters = parameters)
fun constructorInfo(containingClass: UClass, parameters: List<UParameter>) =
Constructor(containingClass = containingClass, parameters = parameters)
@JvmStatic
fun simpleMethodInfo(containingClass: @JvmCommon PsiClass,
fun simpleMethodInfo(containingClass: UClass,
methodName: String,
@PsiModifier.ModifierConstant modifier: String,
returnType: PsiType,
parameters: List<@JvmCommon PsiParameter>) =
parameters: List<UParameter>) =
Method(name = methodName,
modifiers = listOf(modifier),
targetClass = containingClass,
containingClass = containingClass,
returnType = returnType,
parameters = parameters)
}
@Deprecated("to be removed in 2017.3", ReplaceWith("com.intellij.lang.jvm.actions.JvmCommonIntentionActionsFactory"))
class Method(
targetClass: @JvmCommon PsiClass,
containingClass: UClass,
val name: String,
modifiers: List<String> = emptyList(),
typeParams: List<@JvmCommon PsiTypeParameter> = emptyList(),
typeParams: List<PsiTypeParameter> = emptyList(),
val returnType: PsiType,
parameters: List<@JvmCommon PsiParameter> = emptyList(),
parameters: List<UParameter> = emptyList(),
val isAbstract: Boolean = false
) : MethodInsertionInfo(targetClass, modifiers, typeParams, parameters)
) : MethodInsertionInfo(containingClass, modifiers, typeParams, parameters)
@Deprecated("to be removed in 2017.3", ReplaceWith("com.intellij.lang.jvm.actions.JvmCommonIntentionActionsFactory"))
class Constructor(
targetClass: @JvmCommon PsiClass,
containingClass: UClass,
modifiers: List<String> = emptyList(),
typeParams: List<@JvmCommon PsiTypeParameter> = emptyList(),
parameters: List<@JvmCommon PsiParameter> = emptyList()
) : MethodInsertionInfo(targetClass, modifiers, typeParams, parameters)
typeParams: List<PsiTypeParameter> = emptyList(),
parameters: List<UParameter> = emptyList()
) : MethodInsertionInfo(containingClass, 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}")
}
@@ -0,0 +1,58 @@
/*
* 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.lang.jvm.actions
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.lang.Language
import com.intellij.lang.LanguageExtension
import com.intellij.lang.jvm.JvmClass
import com.intellij.lang.jvm.JvmModifiersOwner
import com.intellij.openapi.components.ServiceManager
import org.jetbrains.annotations.ApiStatus
/**
* Extension Point provides language-abstracted code modifications for JVM-based languages.
*
* Each method should return list of code modifications which could be empty.
* If method returns empty list this means that operation on given elements is not supported or not yet implemented for a language.
*
* Every new added method should return empty list by default and then be overridden in implementations for each language if it is possible.
*
* @since 2017.3
*/
@ApiStatus.Experimental
abstract class JvmElementActionsFactory {
open fun createChangeModifierActions(target: JvmModifiersOwner, request: MemberRequest.Modifier): List<IntentionAction> = emptyList()
open fun createAddConstructorActions(targetClass: JvmClass, request: MemberRequest.Constructor): List<IntentionAction> = emptyList()
open fun createAddMethodActions(targetClass: JvmClass, request: MemberRequest.Method): List<IntentionAction> = emptyList()
open fun createAddPropertyActions(targetClass: JvmClass, request: MemberRequest.Property): List<IntentionAction> = emptyList()
companion object : LanguageExtension<JvmElementActionsFactory>(
"com.intellij.lang.jvm.actions.jvmElementActionsFactory") {
@JvmStatic
override fun forLanguage(l: Language): JvmElementActionsFactory? =
super.forLanguage(l)
?: ServiceManager.getService(JvmElementActionsFactoryFallback::class.java).forLanguage(l)
}
}
@@ -0,0 +1,25 @@
/*
* 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.lang.jvm.actions
import com.intellij.lang.Language
@Deprecated("to be removed in 2017.3", ReplaceWith("use com.intellij.lang.jvm.actions.JvmElementActionsFactory"))
interface JvmElementActionsFactoryFallback {
fun forLanguage(lang: Language): JvmElementActionsFactory?
}
@@ -0,0 +1,85 @@
/*
* 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.lang.jvm.actions
import com.intellij.lang.jvm.JvmAnnotation
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.JvmParameter
import com.intellij.lang.jvm.JvmTypeParameter
import com.intellij.lang.jvm.types.JvmType
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Experimental
sealed class MemberRequest {
companion object {
@JvmStatic
fun constructorRequest(parameters: List<JvmParameter>) =
Constructor(parameters = parameters)
@JvmStatic
fun simpleMethodRequest(methodName: String,
annotations: List<JvmAnnotation>,
modifier: List<JvmModifier>,
returnType: JvmType,
parameters: List<JvmParameter>) =
Method(name = methodName,
annotations = annotations,
modifiers = modifier,
returnType = returnType,
parameters = parameters)
@JvmStatic
fun simpleMethodRequest(methodName: String,
modifier: JvmModifier,
returnType: JvmType,
parameters: List<JvmParameter>) =
simpleMethodRequest(methodName, emptyList(), listOf(modifier), returnType, parameters)
}
class Method(
val name: String,
val annotations: List<JvmAnnotation> = emptyList(),
val modifiers: List<JvmModifier> = emptyList(),
val typeParameters: List<JvmTypeParameter> = emptyList(),
val returnType: JvmType,
val parameters: List<JvmParameter> = emptyList()
) : MemberRequest()
class Constructor(
val annotations: List<JvmAnnotation> = emptyList(),
val modifiers: List<JvmModifier> = emptyList(),
val typeParameters: List<JvmTypeParameter> = emptyList(),
val parameters: List<JvmParameter> = emptyList()
) : MemberRequest()
class Property(
val propertyName: String,
val visibilityModifier: JvmModifier,
val propertyType: JvmType,
val setterRequired: Boolean,
val getterRequired: Boolean
) : MemberRequest()
class Modifier(
val modifier: JvmModifier,
val shouldPresent: Boolean
) : MemberRequest()
}
@@ -18,8 +18,12 @@ package com.intellij.codeInspection.inheritance
import com.intellij.CommonBundle
import com.intellij.codeInsight.daemon.QuickFixBundle
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory
import com.intellij.codeInspection.*
import com.intellij.lang.jvm.JvmClass
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.JvmModifiersOwner
import com.intellij.lang.jvm.actions.JvmElementActionsFactory
import com.intellij.lang.jvm.actions.MemberRequest
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
@@ -43,8 +47,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
val subclassInfos = subclassProviders.mapNotNull { it.getSubclassingInfo(aClass) }
val methodsToOverride = aClass.methods.mapNotNull {
method ->
val methodsToOverride = aClass.methods.mapNotNull { method ->
subclassInfos
.mapNotNull { it.methodsInfo?.get(method)?.description }
.firstOrNull()?.let { description ->
@@ -58,7 +61,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
val smartPointerManager = SmartPointerManager.getInstance(aClass.project)
val actionsFactory = JvmCommonIntentionActionsFactory.forLanguage(aClass.language)
val actionsFactory = JvmElementActionsFactory.forLanguage(aClass.language)
for ((method, description) in methodsToOverride) {
if (method.isFinal || method.isStatic || method.hasModifierProperty(PsiModifier.PRIVATE)) {
@@ -91,7 +94,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
return problems.toTypedArray()
}
private fun createFixesIfApplicable(actionsFactory: JvmCommonIntentionActionsFactory?,
private fun createFixesIfApplicable(actionsFactory: JvmElementActionsFactory?,
aClass: UDeclaration,
hintTargetName: String,
methodsToAttachToClassFix: List<SmartPsiElementPointer<UDeclaration>> = emptyList()): Array<LocalQuickFix> {
@@ -120,7 +123,7 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
private class MakeExtendableFix(uDeclaration: UDeclaration,
hintTargetName: String,
val actionsFactory: JvmCommonIntentionActionsFactory,
val actionsFactory: JvmElementActionsFactory,
val siblings: List<SmartPsiElementPointer<UDeclaration>> = emptyList())
: LocalQuickFixOnPsiElement(uDeclaration) {
@@ -164,30 +167,30 @@ class ImplicitSubclassInspection : AbstractBaseUastLocalInspectionTool() {
private fun collectMakeExtendable(declaration: UDeclaration,
actionsList: SmartList<IntentionAction>,
checkParent: Boolean = true) {
val isClassMember = !(declaration is UClass)
val isClassMember = !(declaration is JvmClass)
declaration.modifierList?.apply {
addIfApplicable(declaration, PsiModifier.FINAL, false, actionsList)
addIfApplicable(declaration, PsiModifier.PRIVATE, false, actionsList)
addIfApplicable(declaration, JvmModifier.FINAL, false, actionsList)
addIfApplicable(declaration, JvmModifier.PRIVATE, false, actionsList)
if (isClassMember) {
addIfApplicable(declaration, PsiModifier.STATIC, false, actionsList)
addIfApplicable(declaration, JvmModifier.STATIC, false, actionsList)
}
}
if (checkParent && isClassMember) {
(declaration.uastParent as? UClass)?.apply {
addIfApplicable(this, PsiModifier.FINAL, false, actionsList)
addIfApplicable(this, PsiModifier.PRIVATE, false, actionsList)
addIfApplicable(this, JvmModifier.FINAL, false, actionsList)
addIfApplicable(this, JvmModifier.PRIVATE, false, actionsList)
}
}
}
private fun addIfApplicable(declaration: UDeclaration,
name: String,
private fun addIfApplicable(declaration: JvmModifiersOwner,
modifier: JvmModifier,
shouldPresent: Boolean,
actionsList: SmartList<IntentionAction>) {
if (declaration.modifierList?.hasModifierProperty(name) != shouldPresent) {
(actionsFactory.createChangeModifierAction(declaration as @com.intellij.psi.JvmCommon PsiModifierListOwner, name,
shouldPresent))?.let {
actionsList.add(it)
if (declaration.hasModifier(modifier) != shouldPresent) {
actionsFactory.createChangeModifierActions(declaration, MemberRequest.Modifier(modifier,
shouldPresent)).let {
actionsList.addAll(it)
}
}
}
@@ -16,10 +16,11 @@
package com.intellij.codeInsight.daemon.impl.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory
import com.intellij.codeInsight.intention.MethodInsertionInfo
import com.intellij.codeInspection.LocalQuickFixBase
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.actions.JvmElementActionsFactory
import com.intellij.lang.jvm.actions.MemberRequest
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.Project
import com.intellij.psi.*
@@ -56,11 +57,11 @@ class CreateMethodFix(containingClass: @JvmCommon PsiClass, private val createMe
@JvmStatic
fun createVoidMethodIfFixPossible(psiClass: @JvmCommon PsiClass,
methodName: String,
@PsiModifier.ModifierConstant modifier: String): CreateMethodFix? {
modifier: JvmModifier): CreateMethodFix? {
if (!ModuleUtilCore.projectContainsFile(psiClass.project, psiClass.containingFile.virtualFile, false)) return null
val actionsFactory = JvmCommonIntentionActionsFactory.forLanguage(psiClass.language) ?: return null
val action = actionsFactory.createAddCallableMemberActions(
MethodInsertionInfo.simpleMethodInfo(psiClass, methodName, modifier, PsiType.VOID, emptyList())
val actionsFactory = JvmElementActionsFactory.forLanguage(psiClass.language) ?: return null
val action = actionsFactory.createAddMethodActions(psiClass,
MemberRequest.simpleMethodRequest(methodName, modifier, PsiType.VOID, emptyList())
).firstOrNull() ?: return null
return CreateMethodFix(psiClass, action)
}
@@ -0,0 +1,96 @@
/*
* 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.codeInsight.intention.impl
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.lang.Language
import com.intellij.lang.jvm.JvmClass
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.JvmModifiersOwner
import com.intellij.lang.jvm.actions.JvmElementActionsFactory
import com.intellij.lang.jvm.actions.JvmElementActionsFactoryFallback
import com.intellij.lang.jvm.actions.MemberRequest
import com.intellij.openapi.components.ServiceManager
import com.intellij.psi.PsiElement
import org.jetbrains.uast.*
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory as UastJvmCommonIntentionActionsFactory
import com.intellij.codeInsight.intention.MethodInsertionInfo as UastMethodInsertionInfo
@Deprecated("to be removed in 2017.3", ReplaceWith("use com.intellij.lang.jvm.actions.JvmElementActionsFactory"))
class ElementActionsFactoryUastFallback(
val renderer: JavaElementRenderer,
val materializer: JavaElementMaterializer
) : JvmElementActionsFactoryFallback {
override fun forLanguage(lang: Language): JvmElementActionsFactory? {
val factory = UastJvmCommonIntentionActionsFactory.forLanguage(lang) ?: return null
return object : JvmElementActionsFactory() {
override fun createChangeModifierActions(target: JvmModifiersOwner, request: MemberRequest.Modifier): List<IntentionAction> =
with(request) {
listOfNotNull(
factory.createChangeModifierAction(target.asUast<UDeclaration>(), renderer.render(modifier), shouldPresent))
}
override fun createAddConstructorActions(targetClass: JvmClass, request: MemberRequest.Constructor): List<IntentionAction> =
with(request) {
factory.createAddCallableMemberActions(
UastMethodInsertionInfo.Constructor(
targetClass.asUast(),
modifiers.map { renderer.render(it) },
typeParameters.map { materializer.materialize(it) },
parameters.map { it.asUast<UParameter>() }
)
)
}
override fun createAddMethodActions(targetClass: JvmClass, request: MemberRequest.Method): List<IntentionAction> =
with(request) {
factory.createAddCallableMemberActions(
UastMethodInsertionInfo.Method(
targetClass.asUast(),
name,
modifiers.map { renderer.render(it) },
typeParameters.map { materializer.materialize(it) },
materializer.materialize(returnType),
parameters.map { it.asUast<UParameter>() },
modifiers.contains(JvmModifier.ABSTRACT)
)
)
}
override fun createAddPropertyActions(targetClass: JvmClass, request: MemberRequest.Property): List<IntentionAction> =
with(request) {
factory.createAddBeanPropertyActions(targetClass.asUast<UClass>(), propertyName,
renderer.render(visibilityModifier),
materializer.materialize(propertyType), setterRequired, getterRequired)
}
}
}
}
@Deprecated("remove after kotlin plugin will be ported")
private inline fun <reified T : UElement> JvmModifiersOwner.asUast(): T = when (this) {
is T -> this
is PsiElement -> this.let {
ServiceManager.getService(project, UastContext::class.java)
.convertElement(this, null, T::class.java) as T?
}
?: throw UnsupportedOperationException("cant convert $this to ${T::class}")
else -> throw UnsupportedOperationException("cant convert $this to ${T::class}")
}
@@ -1,125 +0,0 @@
/*
* 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.codeInsight.intention.impl
import com.intellij.codeInsight.daemon.QuickFixBundle
import com.intellij.codeInsight.daemon.impl.quickfix.AddConstructorFix
import com.intellij.codeInsight.daemon.impl.quickfix.ModifierFix
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.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
class JavaCommonIntentionActionsFactory : JvmCommonIntentionActionsFactory() {
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(targetClass, name, modifiers.joinToString(" "), returnType, parameters)
?.let { listOf(it) } ?: emptyList()
}
is MethodInsertionInfo.Constructor ->
listOf(AddConstructorFix(info.targetClass.javaPsi(), info.parameters.map { it.javaPsi() }))
}
}
private fun createAddMethodAction(psiClass: @JvmCommon PsiClass,
methodName: String,
@PsiModifier.ModifierConstant @NotNull visibilityModifier: String,
returnType: PsiType,
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.canonicalText} $methodName($paramsString){}"
val targetClassPointer = SmartPointerManager.getInstance(psiClass.project).createSmartPsiElementPointer(psiClass.javaPsi())
return object : AbstractIntentionAction() {
private val text = targetClassPointer.element?.let { psiClass ->
QuickFixBundle.message("create.method.from.usage.text",
PsiFormatUtil.formatMethod(createMethod(psiClass), PsiSubstitutor.EMPTY,
PsiFormatUtilBase.SHOW_NAME or
PsiFormatUtilBase.SHOW_TYPE or
PsiFormatUtilBase.SHOW_PARAMETERS or
PsiFormatUtilBase.SHOW_RAW_TYPE,
PsiFormatUtilBase.SHOW_TYPE or PsiFormatUtilBase.SHOW_RAW_TYPE, 2))
} ?: ""
override fun getText(): String = text
override fun invoke(project: Project, editor: Editor?, file: PsiFile) {
val targetClass = targetClassPointer.element ?: return
runWriteAction {
val addedMethod = targetClass.add(createMethod(targetClass))
JavaCodeStyleManager.getInstance(project).shortenClassReferences(addedMethod)
}
}
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)
}
}
}
private inline fun <reified T : PsiElement> T.javaPsi(): T =
when (this) {
is org.jetbrains.uast.UElement -> this.psi as T
else -> this
}
override fun createAddBeanPropertyActions(psiClass: @JvmCommon PsiClass,
propertyName: String,
@PsiModifier.ModifierConstant visibilityModifier: String,
propertyType: PsiType,
setterRequired: Boolean,
getterRequired: Boolean): List<IntentionAction> {
if (getterRequired && setterRequired)
return listOf<IntentionAction>(
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired,
true),
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired,
false))
if (getterRequired || setterRequired)
return listOf<IntentionAction>(
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired,
true),
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired,
false),
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, true, true, true))
return listOf<IntentionAction>(
CreateJavaBeanPropertyFix(psiClass.javaPsi(), propertyName, propertyType, getterRequired, setterRequired, true))
}
}
@@ -0,0 +1,193 @@
/*
* 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.codeInsight.intention.impl
import com.intellij.codeInsight.daemon.QuickFixBundle
import com.intellij.codeInsight.daemon.impl.quickfix.AddConstructorFix
import com.intellij.codeInsight.daemon.impl.quickfix.ModifierFix
import com.intellij.codeInsight.intention.AbstractIntentionAction
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.lang.jvm.*
import com.intellij.lang.jvm.actions.JvmElementActionsFactory
import com.intellij.lang.jvm.actions.MemberRequest
import com.intellij.lang.jvm.types.JvmType
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.components.ServiceManager
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
class JavaElementActionsFactoryImpl(
private val materializer: JavaElementMaterializer,
private val renderer: JavaElementRenderer
) : JvmElementActionsFactory() {
override fun createChangeModifierActions(target: JvmModifiersOwner, request: MemberRequest.Modifier): List<IntentionAction> = with(
request) {
val declaration = target as PsiModifierListOwner
listOf(ModifierFix(declaration.modifierList, renderer.render(modifier), shouldPresent, false))
}
override fun createAddConstructorActions(targetClass: JvmClass, request: MemberRequest.Constructor): List<IntentionAction> =
with(request) {
val targetClass = materializer.materialize(targetClass)
val factory = JVMElementFactories.getFactory(targetClass.language, targetClass.project)!!
listOf(AddConstructorFix(targetClass, request.parameters.mapIndexed { i, it ->
factory.createParameter(it.name ?: "arg$i", materializer.materialize(it.type), targetClass)
}))
}
override fun createAddMethodActions(targetClass: JvmClass, request: MemberRequest.Method): List<IntentionAction> =
with(request) {
createAddMethodAction(targetClass, request)
?.let { listOf(it) } ?: emptyList()
}
override fun createAddPropertyActions(targetClass: JvmClass, request: MemberRequest.Property): List<IntentionAction> {
with(request) {
val psiClass = materializer.materialize(targetClass)
val propertyType = materializer.materialize(propertyType)
if (getterRequired && setterRequired)
return listOf<IntentionAction>(
CreateJavaBeanPropertyFix(psiClass, propertyName, propertyType, getterRequired, setterRequired,
true),
CreateJavaBeanPropertyFix(psiClass, propertyName, propertyType, getterRequired, setterRequired,
false))
if (getterRequired || setterRequired)
return listOf<IntentionAction>(
CreateJavaBeanPropertyFix(psiClass, propertyName, propertyType, getterRequired, setterRequired,
true),
CreateJavaBeanPropertyFix(psiClass, propertyName, propertyType, getterRequired, setterRequired,
false),
CreateJavaBeanPropertyFix(psiClass, propertyName, propertyType, true, true, true))
return listOf<IntentionAction>(
CreateJavaBeanPropertyFix(psiClass, propertyName, propertyType, getterRequired, setterRequired, true))
}
}
private fun createAddMethodAction(psiClass: JvmClass, request: MemberRequest.Method): IntentionAction? {
with(request) {
val psiClass = materializer.materialize(psiClass)
val signatureString = with(renderer) {
val paramsString = parameters.mapIndexed { i, t -> "${render(t.type)} ${t.name ?: "arg$i"}" }.joinToString()
val modifiersString = (annotations.map { render(it) } + modifiers.map { render(it) }).joinToString(" ")
"${modifiersString} ${render(returnType)} $name($paramsString){}"
}
val targetClassPointer = SmartPointerManager.getInstance(psiClass.project).createSmartPsiElementPointer(psiClass)
return object : AbstractIntentionAction() {
private val text = targetClassPointer.element?.let { psiClass ->
QuickFixBundle.message("create.method.from.usage.text",
PsiFormatUtil.formatMethod(createMethod(psiClass), PsiSubstitutor.EMPTY,
PsiFormatUtilBase.SHOW_NAME or
PsiFormatUtilBase.SHOW_TYPE or
PsiFormatUtilBase.SHOW_PARAMETERS or
PsiFormatUtilBase.SHOW_RAW_TYPE,
PsiFormatUtilBase.SHOW_TYPE or PsiFormatUtilBase.SHOW_RAW_TYPE, 2))
} ?: ""
override fun getText(): String = text
override fun invoke(project: Project, editor: Editor?, file: PsiFile) {
val targetClass = targetClassPointer.element ?: return
runWriteAction {
val addedMethod = targetClass.add(createMethod(targetClass))
JavaCodeStyleManager.getInstance(project).shortenClassReferences(addedMethod)
}
}
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)
}
}
}
}
}
class JavaElementRenderer {
companion object {
@JvmStatic
fun getInstance(): JavaElementRenderer {
return ServiceManager.getService(JavaElementRenderer::class.java)
}
}
fun render(visibilityModifiers: List<JvmModifier>): String =
visibilityModifiers.joinToString(" ") { render(it) }
fun render(jvmType: JvmType): String =
(jvmType as PsiType).canonicalText
fun render(jvmAnnotation: JvmAnnotation): String =
"@" + (jvmAnnotation as PsiAnnotation).qualifiedName!!
@PsiModifier.ModifierConstant
fun render(modifier: JvmModifier): String = when (modifier) {
JvmModifier.PUBLIC -> PsiModifier.PUBLIC
JvmModifier.PROTECTED -> PsiModifier.PROTECTED
JvmModifier.PRIVATE -> PsiModifier.PRIVATE
JvmModifier.PACKAGE_LOCAL -> ""
JvmModifier.STATIC -> PsiModifier.STATIC
JvmModifier.ABSTRACT -> PsiModifier.ABSTRACT
JvmModifier.FINAL -> PsiModifier.FINAL
JvmModifier.DEFAULT -> PsiModifier.DEFAULT
JvmModifier.NATIVE -> PsiModifier.NATIVE
JvmModifier.SYNCHRONIZED -> PsiModifier.NATIVE
JvmModifier.STRICTFP -> PsiModifier.STRICTFP
JvmModifier.TRANSIENT -> PsiModifier.TRANSIENT
JvmModifier.VOLATILE -> PsiModifier.VOLATILE
JvmModifier.TRANSITIVE -> PsiModifier.TRANSITIVE
}
}
class JavaElementMaterializer {
companion object {
@JvmStatic
fun getInstance(): JavaElementMaterializer {
return ServiceManager.getService(JavaElementMaterializer::class.java)
}
}
fun materialize(jvmType: JvmType): PsiType {
return jvmType as PsiType //TODO:probably it could be not so easy sometimes
}
fun materialize(jvmClass: JvmClass): PsiClass {
return jvmClass as PsiClass //TODO:probably it could be not so easy sometimes
}
fun materialize(jvmParameter: JvmParameter): PsiParameter {
return jvmParameter as PsiParameter //TODO:probably it could be not so easy sometimes
}
fun materialize(jvmTypeParameter: JvmTypeParameter): PsiTypeParameter {
return jvmTypeParameter as PsiTypeParameter //TODO:probably it could be not so easy sometimes
}
}
@@ -16,9 +16,11 @@
package com.intellij.psi.impl.beanProperties;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory;
import com.intellij.codeInspection.IntentionWrapper;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.lang.jvm.JvmModifier;
import com.intellij.lang.jvm.actions.JvmElementActionsFactory;
import com.intellij.lang.jvm.actions.MemberRequest;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -51,10 +53,11 @@ public class CreateBeanPropertyFixes {
if (aClass == null) return IntentionAction.EMPTY_ARRAY;
type = facade.getElementFactory().createType(aClass);
}
JvmCommonIntentionActionsFactory factory = JvmCommonIntentionActionsFactory.forLanguage(psiClass.getLanguage());
JvmElementActionsFactory factory = JvmElementActionsFactory.forLanguage(psiClass.getLanguage());
if (factory == null) return IntentionAction.EMPTY_ARRAY;
return toObjectArray(
factory.createAddBeanPropertyActions(psiClass, propertyName, PsiModifier.PUBLIC, type, createSetter, !createSetter),
factory.createAddPropertyActions(psiClass,
new MemberRequest.Property(propertyName, JvmModifier.PUBLIC, type, createSetter, !createSetter)),
IntentionAction.class);
}
}
+2 -2
View File
@@ -337,8 +337,8 @@
<codeInsight.parameterNameHints
language="Groovy" implementationClass="org.jetbrains.plugins.groovy.codeInsight.hint.GroovyInlayParameterHintsProvider"
/>
<codeInsight.intention.jvmCommonIntentionActionsFactory language="Groovy"
implementationClass="com.intellij.codeInsight.intention.impl.JavaCommonIntentionActionsFactory"/>
<lang.jvm.actions.jvmElementActionsFactory language="Groovy"
implementationClass="com.intellij.codeInsight.intention.impl.JavaElementActionsFactoryImpl"/>
<fileTypeFactory implementation="org.jetbrains.plugins.groovy.GroovyFileTypeLoader"/>
<fileTypeFactory implementation="org.jetbrains.plugins.groovy.dgm.DGMFileTypeFactory"/>
@@ -16,9 +16,9 @@
package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
import com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory;
import com.intellij.codeInsight.intention.MethodInsertionInfo;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.lang.jvm.actions.JvmElementActionsFactory;
import com.intellij.lang.jvm.actions.MemberRequest;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
@@ -103,21 +103,21 @@ public class JavaFxEventHandlerReference extends PsiReferenceBase<XmlAttributeVa
@Override
public void registerFixes(@NotNull final JavaFxEventHandlerReference ref, @NotNull final QuickFixActionRegistrar registrar) {
if (ref.myController != null && ref.myEventHandler == null) {
JvmCommonIntentionActionsFactory intentionActionsFactory =
JvmCommonIntentionActionsFactory.forLanguage(ref.myController.getLanguage());
JvmElementActionsFactory intentionActionsFactory =
JvmElementActionsFactory.forLanguage(ref.myController.getLanguage());
if (intentionActionsFactory == null) return;
String javaSignature = getHandlerSignature(ref);
PsiMethod javaMethod = JavaPsiFacade.getElementFactory(ref.myController.getProject())
.createMethodFromText(javaSignature, ref.myController);
MethodInsertionInfo.Method method =
MethodInsertionInfo.simpleMethodInfo(ref.myController,
javaMethod.getName(),
javaMethod.getModifierList().getText(),
javaMethod.getReturnType(),
Arrays.asList(javaMethod.getParameterList().getParameters()));
intentionActionsFactory.createAddCallableMemberActions(method).forEach(registrar::register);
MemberRequest.Method method =
MemberRequest.simpleMethodRequest(javaMethod.getName(),
Arrays.asList(javaMethod.getAnnotations()),
Arrays.asList(javaMethod.getModifiers()),
javaMethod.getReturnType(),
Arrays.asList(javaMethod.getParameterList().getParameters()));
intentionActionsFactory.createAddMethodActions(ref.myController, method).forEach(registrar::register);
}
}
+13 -1
View File
@@ -329,6 +329,10 @@
<extensionPoint qualifiedName="com.intellij.codeInsight.intention.jvmCommonIntentionActionsFactory" beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="com.intellij.codeInsight.intention.JvmCommonIntentionActionsFactory"/>
</extensionPoint>
<extensionPoint qualifiedName="com.intellij.lang.jvm.actions.jvmElementActionsFactory"
beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="com.intellij.lang.jvm.actions.JvmElementActionsFactory"/>
</extensionPoint>
<extensionPoint name="javaModuleSystem" interface="com.intellij.psi.JavaModuleSystem"/>
</extensionPoints>
@@ -508,6 +512,13 @@
<projectService serviceInterface="com.intellij.codeInsight.javadoc.JavaDocCodeStyle"
serviceImplementation="com.intellij.codeInsight.javadoc.JavaDocCodeStyleImpl"/>
<applicationService serviceInterface="com.intellij.lang.jvm.actions.JvmElementActionsFactoryFallback"
serviceImplementation="com.intellij.codeInsight.intention.impl.ElementActionsFactoryUastFallback"/>
<applicationService serviceImplementation="com.intellij.codeInsight.intention.impl.JavaElementRenderer"/>
<applicationService serviceImplementation="com.intellij.codeInsight.intention.impl.JavaElementMaterializer"/>
<applicationService serviceInterface="com.intellij.psi.JavaDirectoryService"
serviceImplementation="com.intellij.psi.impl.file.JavaDirectoryServiceImpl"/>
@@ -2002,7 +2013,8 @@
<projectService serviceInterface="org.jetbrains.uast.UastContext" serviceImplementation="org.jetbrains.uast.UastContext"/>
<metaLanguage implementation="com.intellij.uast.UastMetaLanguage"/>
<smartPointer.anchorProvider implementation="com.intellij.uast.UastElementAnchorProvider"/>
<codeInsight.intention.jvmCommonIntentionActionsFactory language="JAVA" implementationClass="com.intellij.codeInsight.intention.impl.JavaCommonIntentionActionsFactory"/>
<lang.jvm.actions.jvmElementActionsFactory language="JAVA"
implementationClass="com.intellij.codeInsight.intention.impl.JavaElementActionsFactoryImpl"/>
<deadCode implementation="com.intellij.codeInspection.java19modules.Java9ModuleEntryPoint"/>