mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[jvm-lang] createChangeParametersActions made able to keep existing parameters as is (IDEA-199838)
This commit is contained in:
@@ -1,9 +1,41 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.lang.jvm.actions;
|
||||
|
||||
import com.intellij.lang.jvm.JvmParameter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public interface ChangeParametersRequest extends ActionRequest {
|
||||
|
||||
List<ExpectedParameter> getExpectedParameters();
|
||||
|
||||
class ExistingParameterWrapper implements ExpectedParameter {
|
||||
|
||||
private final JvmParameter myExistingParameter;
|
||||
|
||||
public ExistingParameterWrapper(@NotNull JvmParameter existingParameter) {
|
||||
myExistingParameter = existingParameter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ExpectedType> getExpectedTypes() {
|
||||
return Collections.singletonList(new SimpleExpectedType(myExistingParameter.getType(), ExpectedType.Kind.EXACT));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<String> getSemanticNames() {
|
||||
return Collections.singletonList(myExistingParameter.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JvmParameter getExistingParameter() {
|
||||
return myExistingParameter;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,4 +21,10 @@ public interface ExpectedParameter {
|
||||
default Collection<String> getSemanticNames() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
default Collection<AnnotationRequest> getExpectedAnnotations() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,10 +19,16 @@ fun expectedParameter(types: List<ExpectedType>, names: Collection<String>): Exp
|
||||
return SimpleExpectedParameter(types, names)
|
||||
}
|
||||
|
||||
fun expectedParameter(type: JvmType, name: String, annotations: Collection<AnnotationRequest>): ExpectedParameter {
|
||||
return SimpleExpectedParameter(listOf(expectedType(type, ExpectedType.Kind.SUPERTYPE)), listOf(name), annotations)
|
||||
}
|
||||
|
||||
private class SimpleExpectedParameter(
|
||||
private val types: List<ExpectedType>,
|
||||
private val names: Collection<String>
|
||||
private val names: Collection<String>,
|
||||
private val annotations: Collection<AnnotationRequest> = emptyList()
|
||||
) : ExpectedParameter {
|
||||
override fun getExpectedTypes() = types
|
||||
override fun getSemanticNames() = names
|
||||
override fun getExpectedAnnotations() = annotations
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.intellij.lang.java.actions
|
||||
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle
|
||||
import com.intellij.lang.jvm.actions.ChangeParametersRequest
|
||||
import com.intellij.lang.jvm.actions.ExpectedParameter
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
@@ -26,17 +27,46 @@ internal class ChangeMethodParameters(target: PsiMethod, override val request: C
|
||||
override fun getFamilyName(): String = QuickFixBundle.message("change.method.parameters.family")
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
|
||||
target.parameterList.parameters.forEach(PsiParameter::delete)
|
||||
|
||||
val factory = PsiElementFactory.SERVICE.getInstance(project)
|
||||
val helper = JvmPsiConversionHelper.getInstance(target.project)
|
||||
|
||||
for (expectedParameter in request.expectedParameters) {
|
||||
val name = expectedParameter.semanticNames.first()
|
||||
val psiType = helper.convertType(expectedParameter.expectedTypes.first().theType)
|
||||
target.parameterList.add(factory.createParameter(name, psiType))
|
||||
tailrec fun updateParameters(currentParameters: List<PsiParameter>, expectedParameters: List<ExpectedParameter>) {
|
||||
|
||||
val currentHead = currentParameters.firstOrNull()
|
||||
val expectedHead = expectedParameters.firstOrNull()
|
||||
|
||||
if (expectedHead == null) {
|
||||
currentParameters.forEach(PsiParameter::delete)
|
||||
return
|
||||
}
|
||||
|
||||
if (expectedHead is ChangeParametersRequest.ExistingParameterWrapper) {
|
||||
if (expectedHead.existingParameter == currentHead)
|
||||
return updateParameters(currentParameters.subList(1, currentParameters.size),
|
||||
expectedParameters.subList(1, expectedParameters.size))
|
||||
else
|
||||
throw UnsupportedOperationException("processing of existing params in different order is not implemented yet")
|
||||
}
|
||||
|
||||
val name = expectedHead.semanticNames.first()
|
||||
val psiType = helper.convertType(expectedHead.expectedTypes.first().theType)
|
||||
val newParameter = factory.createParameter(name, psiType)
|
||||
|
||||
for (annotationRequest in expectedHead.expectedAnnotations) {
|
||||
addAnnotationToModifierList(newParameter.modifierList!!, annotationRequest)
|
||||
}
|
||||
|
||||
if (currentHead == null)
|
||||
target.parameterList.add(newParameter)
|
||||
else
|
||||
target.parameterList.addBefore(newParameter, currentHead)
|
||||
|
||||
updateParameters(currentParameters, expectedParameters.subList(1, expectedParameters.size))
|
||||
|
||||
}
|
||||
|
||||
updateParameters(target.parameterList.parameters.toList(), request.expectedParameters)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.util.text.StringUtilRt
|
||||
import com.intellij.psi.PsiElementFactory
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiModifierList
|
||||
import com.intellij.psi.PsiModifierListOwner
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager
|
||||
@@ -28,28 +29,30 @@ internal class CreateAnnotationAction(target: PsiModifierListOwner, override val
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
|
||||
val modifierList = target.modifierList ?: return
|
||||
val annotation = modifierList.addAnnotation(request.qualifiedName)
|
||||
|
||||
val psiElementFactory = PsiElementFactory.SERVICE.getInstance(project)
|
||||
|
||||
attributes@ for ((name, value) in request.attributes) {
|
||||
val memberValue = when (value) {
|
||||
is AnnotationAttributeValueRequest.PrimitiveValue -> psiElementFactory
|
||||
.createExpressionFromText(value.value.toString(), null)
|
||||
is AnnotationAttributeValueRequest.StringValue -> psiElementFactory
|
||||
.createExpressionFromText("\"" + StringUtil.escapeStringCharacters(value.value) + "\"", null)
|
||||
else -> {
|
||||
LOG.error("adding annotation members of ${value.javaClass} type is not implemented"); continue@attributes
|
||||
}
|
||||
}
|
||||
annotation.setDeclaredAttributeValue(name.takeIf { name != "value" }, memberValue)
|
||||
}
|
||||
|
||||
val formatter = CodeStyleManager.getInstance(project)
|
||||
val codeStyleManager = JavaCodeStyleManager.getInstance(project)
|
||||
codeStyleManager.shortenClassReferences(formatter.reformat(annotation))
|
||||
|
||||
addAnnotationToModifierList(modifierList, request)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal fun addAnnotationToModifierList(modifierList: PsiModifierList, annotationRequest: AnnotationRequest) {
|
||||
val project = modifierList.project
|
||||
val annotation = modifierList.addAnnotation(annotationRequest.qualifiedName)
|
||||
val psiElementFactory = PsiElementFactory.SERVICE.getInstance(project)
|
||||
|
||||
attributes@ for ((name, value) in annotationRequest.attributes) {
|
||||
val memberValue = when (value) {
|
||||
is AnnotationAttributeValueRequest.PrimitiveValue -> psiElementFactory
|
||||
.createExpressionFromText(value.value.toString(), null)
|
||||
is AnnotationAttributeValueRequest.StringValue -> psiElementFactory
|
||||
.createExpressionFromText("\"" + StringUtil.escapeStringCharacters(value.value) + "\"", null)
|
||||
else -> {
|
||||
LOG.error("adding annotation members of ${value.javaClass} type is not implemented"); continue@attributes
|
||||
}
|
||||
}
|
||||
annotation.setDeclaredAttributeValue(name.takeIf { name != "value" }, memberValue)
|
||||
}
|
||||
|
||||
val formatter = CodeStyleManager.getInstance(project)
|
||||
val codeStyleManager = JavaCodeStyleManager.getInstance(project)
|
||||
codeStyleManager.shortenClassReferences(formatter.reformat(annotation))
|
||||
}
|
||||
Reference in New Issue
Block a user