[jvm-lang] add and use ExpectedParameter

- update Java request implementations;
- update render actions in Java and Groovy.
This commit is contained in:
Daniil Ovchinnikov
2018-02-19 22:20:00 +03:00
parent 5c6aeec85a
commit ddbb94b737
22 changed files with 165 additions and 100 deletions

View File

@@ -21,6 +21,12 @@ public interface CreateExecutableRequest extends ActionRequest {
@NotNull
JvmSubstitutor getTargetSubstitutor();
@Deprecated
@NotNull
List<Pair<SuggestedNameInfo, List<ExpectedType>>> getParameters();
default List<Pair<SuggestedNameInfo, List<ExpectedType>>> getParameters() {
return CompatibilityUtil.getParameters(getExpectedParameters());
}
@NotNull
List<ExpectedParameter> getExpectedParameters();
}

View File

@@ -0,0 +1,24 @@
// 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 org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public interface ExpectedParameter {
@NotNull
List<ExpectedType> getExpectedTypes();
/**
* For example for unresolved call in Java {@code a.foo(bars)} this method will return 'bars' string,
* which then will be used to suggest parameter names
* taking code style parameter prefix into consideration as well as its type.
*/
@NotNull
default Collection<String> getSemanticNames() {
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,26 @@
// 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.
@file:JvmName("CompatibilityUtil")
package com.intellij.lang.jvm.actions
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiType
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.psi.codeStyle.VariableKind
internal fun getParameters(expectedParameters: List<ExpectedParameter>): List<Pair<SuggestedNameInfo, List<ExpectedType>>> {
return expectedParameters.map {
val nameInfo = object : SuggestedNameInfo(it.semanticNames.toTypedArray()) {}
Pair(nameInfo, it.expectedTypes)
}
}
fun getParameters(expectedParameters: List<ExpectedParameter>, project: Project): List<Pair<SuggestedNameInfo, List<ExpectedType>>> {
val styleManager = JavaCodeStyleManager.getInstance(project)
return expectedParameters.map {
val expectedTypes = it.expectedTypes
val nameInfo = styleManager.suggestNames(it.semanticNames, VariableKind.PARAMETER, expectedTypes.firstOrNull()?.theType as? PsiType)
Pair(nameInfo, expectedTypes)
}
}

View File

@@ -7,7 +7,7 @@ typealias ExpectedTypes = List<ExpectedType>
fun expectedType(type: JvmType, kind: ExpectedType.Kind = ExpectedType.Kind.EXACT): ExpectedType = SimpleExpectedType(type, kind)
fun expectedTypes(type: JvmType): ExpectedTypes = listOf(expectedType(type))
fun expectedTypes(type: JvmType, kind: ExpectedType.Kind = ExpectedType.Kind.EXACT): ExpectedTypes = listOf(expectedType(type, kind))
private class SimpleExpectedType(private val theType: JvmType, private val theKind: ExpectedType.Kind) : ExpectedType {
override fun getTheType(): JvmType = theType

View File

@@ -5,11 +5,10 @@ import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.types.JvmSubstitutor
import com.intellij.lang.jvm.types.JvmType
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Pair
import com.intellij.psi.PsiJvmSubstitutor
import com.intellij.psi.PsiSubstitutor
import com.intellij.psi.PsiType
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.openapi.util.Pair as JBPair
private class SimpleMethodRequest(
private val methodName: String,
@@ -22,19 +21,19 @@ private class SimpleMethodRequest(
override fun getModifiers() = modifiers
override fun getReturnType() = returnType
override fun getAnnotations() = emptyList<AnnotationRequest>()
override fun getParameters() = emptyList<kotlin.Pair<SuggestedNameInfo, ExpectedTypes>>()
override fun getExpectedParameters() = emptyList<ExpectedParameter>()
override fun getTargetSubstitutor() = targetSubstitutor
}
private class SimpleConstructorRequest(
private val parameters: List<kotlin.Pair<SuggestedNameInfo, ExpectedTypes>>,
private val expectedParameters: List<ExpectedParameter>,
private val targetSubstitutor: JvmSubstitutor
) : CreateConstructorRequest {
override fun isValid(): Boolean = true
override fun getModifiers() = emptyList<JvmModifier>()
override fun getAnnotations() = emptyList<AnnotationRequest>()
override fun getTargetSubstitutor() = targetSubstitutor
override fun getParameters() = parameters
override fun getExpectedParameters() = expectedParameters
}
fun methodRequest(project: Project, methodName: String, modifier: JvmModifier, returnType: JvmType): CreateMethodRequest {
@@ -46,12 +45,9 @@ fun methodRequest(project: Project, methodName: String, modifier: JvmModifier, r
)
}
fun constructorRequest(project: Project, parameters: List<Pair<String, PsiType>>): CreateConstructorRequest {
val expectedParameters = parameters.map {
nameInfo(it.first) to expectedTypes(it.second)
}
fun constructorRequest(project: Project, parameters: List<JBPair<String, PsiType>>): CreateConstructorRequest {
return SimpleConstructorRequest(
parameters = expectedParameters,
expectedParameters = parameters.map { expectedParameter(it.second, it.first) },
targetSubstitutor = PsiJvmSubstitutor(project, PsiSubstitutor.EMPTY)
)
}

View File

@@ -1,19 +1,28 @@
// 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.openapi.project.Project
import com.intellij.psi.PsiType
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.psi.codeStyle.VariableKind
import com.intellij.lang.jvm.types.JvmType
fun nameInfo(vararg names: String): SuggestedNameInfo = object : SuggestedNameInfo(names) {}
fun suggestJavaParamName(project: Project, type: PsiType, propertyName: String? = null): SuggestedNameInfo {
val codeStyleManager = JavaCodeStyleManager.getInstance(project)!!
return codeStyleManager.suggestVariableName(VariableKind.PARAMETER, propertyName, null, type)
fun expectedParameter(type: JvmType, vararg names: String): ExpectedParameter {
return expectedParameter(expectedType(type, ExpectedType.Kind.SUPERTYPE), *names)
}
fun SuggestedNameInfo.orDefault(defaultName: String): SuggestedNameInfo {
return if (names.isEmpty()) nameInfo(defaultName) else this
fun expectedParameter(expectedType: ExpectedType, vararg names: String): ExpectedParameter {
return expectedParameter(listOf(expectedType), *names)
}
fun expectedParameter(types: List<ExpectedType>, vararg names: String): ExpectedParameter {
return expectedParameter(types, names.toList())
}
fun expectedParameter(types: List<ExpectedType>, names: Collection<String>): ExpectedParameter {
return SimpleExpectedParameter(types, names)
}
private class SimpleExpectedParameter(
private val types: List<ExpectedType>,
private val names: Collection<String>
) : ExpectedParameter {
override fun getExpectedTypes() = types
override fun getSemanticNames() = names
}

View File

@@ -55,7 +55,7 @@ private class JavaConstructorRenderer(
constructor = forcePsiPostprocessAndRestoreElement(constructor) ?: return
val builder = TemplateBuilderImpl(constructor)
createTemplateContext(builder).setupParameters(constructor, request.parameters)
createTemplateContext(builder).setupParameters(constructor, request.expectedParameters)
val superConstructor = setupSuperCall(targetClass, constructor, builder)
constructor = forcePsiPostprocessAndRestoreElement(constructor) ?: return

View File

@@ -122,7 +122,7 @@ private class JavaMethodRenderer(
val builder = TemplateBuilderImpl(method)
createTemplateContext(builder).run {
setupTypeElement(method.returnTypeElement, request.returnType)
setupParameters(method, request.parameters)
setupParameters(method, request.expectedParameters)
}
builder.setEndVariableAfter(method.body ?: method)
return builder

View File

@@ -29,7 +29,7 @@ internal class CreatePropertyAction(target: PsiClass, request: CreateMethodReque
val counterPart = when (propertyKind) {
GETTER, BOOLEAN_GETTER -> SETTER
SETTER -> {
val expectedType = request.parameters.single().second.singleOrNull()
val expectedType = request.expectedParameters.single().expectedTypes.singleOrNull()
if (expectedType != null && PsiType.BOOLEAN == JvmPsiConversionHelper.getInstance(project).convertType(expectedType.theType)) {
BOOLEAN_GETTER
}

View File

@@ -36,8 +36,8 @@ internal abstract class CreatePropertyActionBase(
// check parameters count
when (propertyKind) {
PropertyKind.GETTER, PropertyKind.BOOLEAN_GETTER -> if (request.parameters.isNotEmpty()) return false
PropertyKind.SETTER -> if (request.parameters.size != 1) return false
PropertyKind.GETTER, PropertyKind.BOOLEAN_GETTER -> if (request.expectedParameters.isNotEmpty()) return false
PropertyKind.SETTER -> if (request.expectedParameters.size != 1) return false
}
return target.findMethodsByName(request.methodName, false).isEmpty()

View File

@@ -47,7 +47,7 @@ internal abstract class PropertyRenderer(
private val expectedTypes: List<ExpectedTypeInfo> = when (propertyKind) {
PropertyKind.GETTER -> extractExpectedTypes(project, request.returnType).orObject(target)
PropertyKind.BOOLEAN_GETTER -> listOf(PsiType.BOOLEAN.toExpectedType())
PropertyKind.SETTER -> extractExpectedTypes(project, request.parameters.single().second).orObject(target)
PropertyKind.SETTER -> extractExpectedTypes(project, request.expectedParameters.single().expectedTypes).orObject(target)
}
private lateinit var targetDocument: Document

View File

@@ -14,7 +14,6 @@ import com.intellij.lang.jvm.types.JvmSubstitutor
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.PsiModifier.ModifierConstant
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.psi.impl.compiled.ClsClassImpl
@ModifierConstant
@@ -80,11 +79,6 @@ internal fun JvmSubstitutor.toPsiSubstitutor(project: Project): PsiSubstitutor {
return JvmPsiConversionHelper.getInstance(project).convertSubstitutor(this)
}
internal inline fun extractNames(suggestedNames: SuggestedNameInfo?, defaultName: () -> String): Array<out String> {
val names = (suggestedNames ?: SuggestedNameInfo.NULL_INFO).names
return if (names.isEmpty()) arrayOf(defaultName()) else names
}
internal fun PsiType.toExpectedType() = createInfo(this, ExpectedTypeInfo.TYPE_STRICTLY, this, TailType.NONE)
internal fun List<ExpectedTypeInfo>.orObject(context: PsiElement): List<ExpectedTypeInfo> {

View File

@@ -5,11 +5,14 @@ import com.intellij.codeInsight.ExpectedTypeInfo
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils
import com.intellij.codeInsight.daemon.impl.quickfix.GuessTypeParameters
import com.intellij.codeInsight.template.TemplateBuilder
import com.intellij.lang.jvm.actions.ExpectedParameter
import com.intellij.lang.jvm.actions.ExpectedTypes
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Computable
import com.intellij.psi.*
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.codeStyle.VariableKind
import com.intellij.psi.impl.source.PostprocessReformattingAspect
import com.intellij.psi.util.PsiUtil
@@ -22,7 +25,7 @@ internal class TemplateContext(
val guesserContext: PsiElement?
)
internal fun TemplateContext.setupParameters(method: PsiMethod, parameters: List<Pair<SuggestedNameInfo, ExpectedTypes>>) {
internal fun TemplateContext.setupParameters(method: PsiMethod, parameters: List<ExpectedParameter>) {
if (parameters.isEmpty()) return
val postprocessReformattingAspect = PostprocessReformattingAspect.getInstance(project)
val parameterList = method.parameterList
@@ -31,16 +34,15 @@ internal fun TemplateContext.setupParameters(method: PsiMethod, parameters: List
//255 is the maximum number of method parameters
for (i in 0 until minOf(parameters.size, 255)) {
val parameterInfo = parameters[i]
val names = extractNames(parameterInfo.first) { "p" + i }
val dummyParameter = factory.createParameter(names.first(), PsiType.INT)
val dummyParameter = factory.createParameter("p$i", PsiType.VOID)
if (isInterface) {
PsiUtil.setModifierProperty(dummyParameter, PsiModifier.FINAL, false)
}
val parameter = postprocessReformattingAspect.postponeFormattingInside(Computable {
parameterList.add(dummyParameter)
}) as PsiParameter
setupTypeElement(parameter.typeElement, parameterInfo.second)
setupParameterName(parameter, names)
setupTypeElement(parameter.typeElement, parameterInfo.expectedTypes)
setupParameterName(parameter, parameterInfo)
}
}
@@ -53,8 +55,11 @@ internal fun TemplateContext.setupTypeElement(typeElement: PsiTypeElement, types
return guesser.setupTypeElement(typeElement, types.toTypedArray(), guesserContext, targetClass)
}
internal fun TemplateContext.setupParameterName(parameter: PsiParameter, names: Array<out String>) {
internal fun TemplateContext.setupParameterName(parameter: PsiParameter, expectedParameter: ExpectedParameter) {
val nameIdentifier = parameter.nameIdentifier ?: return
val codeStyleManager: JavaCodeStyleManager = project.service()
val argumentType = expectedParameter.expectedTypes.firstOrNull()?.theType as? PsiType
val names = codeStyleManager.suggestNames(expectedParameter.semanticNames, VariableKind.PARAMETER, argumentType).names
val expression = CreateFromUsageUtils.ParameterNameExpression(names)
builder.replaceElement(nameIdentifier, expression)
}

View File

@@ -6,9 +6,9 @@ import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.actions.*
import com.intellij.openapi.components.service
import com.intellij.psi.*
import com.intellij.psi.PsiType.getJavaLangObject
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.psi.codeStyle.VariableKind
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.createSmartPointer
import com.intellij.psi.util.parentOfType
import com.intellij.refactoring.util.RefactoringUtil
@@ -31,27 +31,33 @@ internal abstract class CreateExecutableFromJavaUsageRequest<out T : PsiCall>(
override fun getTargetSubstitutor() = PsiJvmSubstitutor(project, getTargetSubstitutor(call))
override fun getParameters(): List<Pair<SuggestedNameInfo, ExpectedTypes>> {
override fun getExpectedParameters(): List<ExpectedParameter> {
val argumentList = call.argumentList ?: return emptyList()
val scope = call.resolveScope
val codeStyleManager: JavaCodeStyleManager = project.service()
return argumentList.expressions.map { expression ->
var argType: PsiType? = RefactoringUtil.getTypeByExpression(expression)
val names = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, expression, argType)
if (argType == null || PsiType.NULL == argType || LambdaUtil.notInferredType(argType)) {
argType = PsiType.getJavaLangObject(psiManager, scope)
}
else if (argType is PsiDisjunctionType) {
argType = argType.leastUpperBound
}
else if (argType is PsiWildcardType) {
argType = if (argType.isBounded) argType.bound else PsiType.getJavaLangObject(psiManager, scope)
}
val expectedTypeInfo = argType?.let { expectedType(it, ExpectedType.Kind.SUPERTYPE) }
val expectedTypes = expectedTypeInfo?.let { listOf(it) } ?: emptyList()
Pair<SuggestedNameInfo, ExpectedTypes>(names, expectedTypes)
val type = getArgType(expression, scope)
val names = codeStyleManager.suggestSemanticNames(expression)
val expectedTypes = if (type == null) emptyList() else expectedTypes(type, ExpectedType.Kind.SUPERTYPE)
expectedParameter(expectedTypes, names)
}
}
override fun getParameters() = getParameters(expectedParameters, project)
private fun getArgType(expression: PsiExpression, scope: GlobalSearchScope): PsiType? {
val argType: PsiType? = RefactoringUtil.getTypeByExpression(expression)
if (argType == null || PsiType.NULL == argType || LambdaUtil.notInferredType(argType)) {
return getJavaLangObject(psiManager, scope)
}
else if (argType is PsiDisjunctionType) {
return argType.leastUpperBound
}
else if (argType is PsiWildcardType) {
return if (argType.isBounded) argType.bound else getJavaLangObject(psiManager, scope)
}
return argType
}
val context get() = call.parentOfType(PsiMethod::class, PsiClass::class)
}

View File

@@ -3,10 +3,7 @@ package com.intellij.psi.impl.beanProperties
import com.intellij.lang.java.beans.PropertyKind
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.actions.AnnotationRequest
import com.intellij.lang.jvm.actions.CreateMethodRequest
import com.intellij.lang.jvm.actions.expectedTypes
import com.intellij.lang.jvm.actions.suggestJavaParamName
import com.intellij.lang.jvm.actions.*
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiJvmSubstitutor
import com.intellij.psi.PsiSubstitutor
@@ -21,7 +18,6 @@ internal class CreateBeanPropertyRequest(
) : CreateMethodRequest {
private val isSetter: Boolean = propertyKind == PropertyKind.SETTER
private val names = suggestJavaParamName(project, type, propertyName)
private val expectedTypes = expectedTypes(type)
private val myMethodName = getAccessorName(propertyName, propertyKind)
@@ -38,8 +34,11 @@ internal class CreateBeanPropertyRequest(
private val myTargetSubstitutor = PsiJvmSubstitutor(project, PsiSubstitutor.EMPTY)
override fun getTargetSubstitutor() = myTargetSubstitutor
private val myParameters = if (isSetter) listOf(Pair(names, expectedTypes)) else emptyList()
override fun getParameters() = myParameters
private val myParameters = if (isSetter) listOf(expectedParameter(type, propertyName)) else emptyList()
override fun getExpectedParameters() = myParameters
private val oldParameters = getParameters(myParameters, project)
override fun getParameters() = oldParameters
override fun isValid() = type.isValid
}

View File

@@ -44,8 +44,9 @@ private class ConstructorMethodRenderer(
}
private fun setupTemplate(method: GrMethod) {
val typeExpressions = setupParameters(method, request.parameters).toTypedArray()
val nameExpressions = setupNameExpressions(request.parameters).toTypedArray()
val parameters = request.expectedParameters
val typeExpressions = setupParameters(method, parameters).toTypedArray()
val nameExpressions = setupNameExpressions(parameters, project).toTypedArray()
createTemplateForMethod(typeExpressions, nameExpressions, method, targetClass, null, true, null)
}

View File

@@ -67,8 +67,9 @@ private class MethodRenderer(
}
private fun setupTemplate(method: GrMethod) {
val typeExpressions = setupParameters(method, request.parameters).toTypedArray()
val nameExpressions = setupNameExpressions(request.parameters).toTypedArray()
val parameters = request.expectedParameters
val typeExpressions = setupParameters(method, parameters).toTypedArray()
val nameExpressions = setupNameExpressions(parameters, project).toTypedArray()
val returnExpression = setupTypeElement(method, createConstraints(project, request.returnType))
createTemplateForMethod(typeExpressions, nameExpressions, method, targetClass, returnExpression, false, null)
}

View File

@@ -36,9 +36,10 @@ internal class CreatePropertyAction(
if (propertyKind == SETTER && readOnly) return false
val parameters = request.expectedParameters
when (propertyKind) {
GETTER, BOOLEAN_GETTER -> if (request.parameters.isNotEmpty()) return false
SETTER -> if (request.parameters.size != 1) return false
GETTER, BOOLEAN_GETTER -> if (parameters.isNotEmpty()) return false
SETTER -> if (parameters.size != 1) return false
}
val counterAccessorName = counterPart(propertyKind).getAccessorName(propertyName)
@@ -49,7 +50,7 @@ internal class CreatePropertyAction(
return when (propertyKind) {
GETTER, BOOLEAN_GETTER -> SETTER
SETTER -> {
val expectedType = request.parameters.single().second.singleOrNull()
val expectedType = request.expectedParameters.single().expectedTypes.singleOrNull()
if (expectedType != null && PsiType.BOOLEAN == JvmPsiConversionHelper.getInstance(project).convertType(expectedType.theType)) {
BOOLEAN_GETTER
}

View File

@@ -4,15 +4,11 @@ package org.jetbrains.plugins.groovy.annotator.intentions.elements
import com.intellij.lang.java.beans.PropertyKind
import com.intellij.lang.jvm.JvmClass
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.actions.CreateMethodRequest
import com.intellij.lang.jvm.actions.ExpectedType
import com.intellij.lang.jvm.actions.ExpectedTypes
import com.intellij.lang.jvm.actions.expectedType
import com.intellij.lang.jvm.actions.*
import com.intellij.lang.jvm.types.JvmSubstitutor
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.PsiModifier.ModifierConstant
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.psi.impl.compiled.ClsClassImpl
import com.intellij.psi.impl.light.LightElement
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition
@@ -21,7 +17,7 @@ import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass
internal typealias ExpectedParameters = List<Pair<SuggestedNameInfo, List<ExpectedType>>>
internal typealias ExpectedParameters = List<ExpectedParameter>
@ModifierConstant
internal fun JvmModifier.toPsiModifier(): String = when (this) {
@@ -73,19 +69,14 @@ private fun toTypeConstraint(project: Project, expectedType: ExpectedType): Type
return if (expectedType.theKind == ExpectedType.Kind.SUPERTYPE) SupertypeConstraint.create(psiType) else SubtypeConstraint.create(psiType)
}
internal fun extractNames(suggestedNames: SuggestedNameInfo?, defaultName: () -> String): Array<out String> {
val names = (suggestedNames ?: SuggestedNameInfo.NULL_INFO).names
return if (names.isEmpty()) arrayOf(defaultName()) else names
}
internal fun JvmSubstitutor.toPsiSubstitutor(project: Project): PsiSubstitutor {
return JvmPsiConversionHelper.getInstance(project).convertSubstitutor(this)
}
internal fun CreateMethodRequest.createPropertyTypeConstraints(kind: PropertyKind) : ExpectedTypes {
return when(kind) {
internal fun CreateMethodRequest.createPropertyTypeConstraints(kind: PropertyKind): ExpectedTypes {
return when (kind) {
PropertyKind.GETTER -> returnType
PropertyKind.BOOLEAN_GETTER -> listOf(expectedType(PsiType.BOOLEAN))
PropertyKind.SETTER -> parameters.single().second
PropertyKind.SETTER -> expectedParameters.single().expectedTypes
}
}

View File

@@ -1,8 +1,11 @@
// 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 org.jetbrains.plugins.groovy.annotator.intentions.elements
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Computable
import com.intellij.psi.PsiType
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import com.intellij.psi.codeStyle.VariableKind
import com.intellij.psi.impl.source.PostprocessReformattingAspect
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter
@@ -24,13 +27,12 @@ internal fun setupParameters(method: GrMethod, parameters: ExpectedParameters):
var paramTypesExpressions = listOf<ChooseTypeExpression>()
for (i in 0 until minOf(parameters.size, 255)) {
val parameterInfo = parameters[i]
val names = extractNames(parameterInfo.first) { "p" + i }
val dummyParameter = factory.createParameter(names.first(), PsiType.INT)
val dummyParameter = factory.createParameter("p$i", PsiType.INT)
postprocessReformattingAspect.postponeFormattingInside(Computable {
parameterList.add(dummyParameter)
}) as GrParameter
paramTypesExpressions += setupTypeElement(method, createConstraints(project, parameterInfo.second))
paramTypesExpressions += setupTypeElement(method, createConstraints(project, parameterInfo.expectedTypes))
}
return paramTypesExpressions
@@ -40,6 +42,11 @@ internal fun setupTypeElement(method: GrMethod, constraints: List<TypeConstraint
return ChooseTypeExpression(constraints.toTypedArray(), method.manager, method.resolveScope, false)
}
internal fun setupNameExpressions(parameters: ExpectedParameters): List<ParameterNameExpression> {
return parameters.map { SuggestedParameterNameExpression(it.first) }
internal fun setupNameExpressions(parameters: ExpectedParameters, project: Project): List<ParameterNameExpression> {
val codeStyleManager = JavaCodeStyleManager.getInstance(project)
return parameters.map {
val type = it.expectedTypes.firstOrNull()?.theType as? PsiType
val nameInfo = codeStyleManager.suggestNames(it.semanticNames, VariableKind.PARAMETER, type)
SuggestedParameterNameExpression(nameInfo)
}
}

View File

@@ -1,5 +1,5 @@
class A {
void f(Object i) {
void f(Object o) {
}
}

View File

@@ -11,7 +11,6 @@ import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiSubstitutor
import com.intellij.psi.PsiType
import com.intellij.psi.codeStyle.JavaCodeStyleSettings
import com.intellij.psi.codeStyle.SuggestedNameInfo
import com.intellij.psi.util.createSmartPointer
import com.intellij.psi.xml.XmlAttribute
import com.intellij.psi.xml.XmlAttributeValue
@@ -50,14 +49,14 @@ class CreateEventHandlerRequest(element: XmlAttributeValue) : CreateMethodReques
override fun getReturnType() = listOf(expectedType(PsiType.VOID, ExpectedType.Kind.EXACT))
override fun getParameters(): List<Pair<SuggestedNameInfo, ExpectedTypes>> {
val eventType = getEventType(myElement)
val expectedType = expectedType(eventType, ExpectedType.Kind.EXACT)
val nameInfo = suggestJavaParamName(myProject, eventType).orDefault("e")
val parameter = Pair(nameInfo, listOf(expectedType))
override fun getExpectedParameters(): List<ExpectedParameter> {
val eventType = expectedType(getEventType(myElement), ExpectedType.Kind.EXACT)
val parameter = expectedParameter(eventType)
return listOf(parameter)
}
override fun getParameters() = getParameters(expectedParameters, myProject)
override fun getModifiers() = setOf(myVisibility)
override fun getAnnotations() = if (myVisibility != JvmModifier.PUBLIC) {