[jvm-lang] add ExpectedType, use it in CreateMethodRequest

This commit is contained in:
Daniil Ovchinnikov
2017-09-12 16:21:38 +02:00
parent 92c1e0f683
commit 6eed3ff528
8 changed files with 136 additions and 26 deletions
@@ -25,7 +25,7 @@ interface CreateMethodRequest {
val methodName: String
val returnType: Any? // ExpectedTypeInfo[]
val returnType: ExpectedTypes
val modifiers: Collection<JvmModifier>
@@ -36,4 +36,4 @@ interface CreateMethodRequest {
val targetSubstitutor: JvmSubstitutor
}
typealias ExpectedParameter = Pair<SuggestedNameInfo, Any? /* ExpectedTypeInfo[]*/>
typealias ExpectedParameter = Pair<SuggestedNameInfo, ExpectedTypes>
@@ -0,0 +1,31 @@
/*
* 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.types.JvmType
interface ExpectedType {
val theType: JvmType
val theKind: Kind
enum class Kind {
EXACT,
SUBTYPE,
SUPERTYPE
}
}
@@ -0,0 +1,29 @@
/*
* 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.types.JvmType
typealias ExpectedTypes = List<ExpectedType>
fun expectedType(type: JvmType, kind: ExpectedType.Kind = ExpectedType.Kind.EXACT): ExpectedType {
return SimpleExpectedType(type, kind)
}
private class SimpleExpectedType(
override val theType: JvmType,
override val theKind: ExpectedType.Kind
) : ExpectedType
@@ -26,10 +26,10 @@ import com.intellij.codeInsight.template.Template
import com.intellij.codeInsight.template.TemplateBuilder
import com.intellij.codeInsight.template.TemplateBuilderImpl
import com.intellij.codeInsight.template.TemplateEditingAdapter
import com.intellij.lang.java.actions.Workaround.extractExpectedTypes
import com.intellij.lang.java.request.CreateMethodFromJavaUsageRequest
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.actions.CreateMethodRequest
import com.intellij.lang.jvm.actions.ExpectedTypes
import com.intellij.openapi.command.WriteCommandAction.runWriteCommandAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
@@ -167,9 +167,9 @@ private class JavaMethodRenderer(
return builder
}
private fun setupTypeElement(guesser: GuessTypeParameters, typeElement: PsiTypeElement?, types: Any?) {
private fun setupTypeElement(guesser: GuessTypeParameters, typeElement: PsiTypeElement?, types: ExpectedTypes) {
typeElement ?: return
val expectedTypes = extractExpectedTypes(types) ?: emptyArray()
val expectedTypes = extractExpectedTypes(project, types).toTypedArray()
guesser.setupTypeElement(typeElement, expectedTypes, javaUsage?.context, targetClass)
}
@@ -15,9 +15,17 @@
*/
package com.intellij.lang.java.actions
import com.intellij.codeInsight.ExpectedTypeInfo
import com.intellij.codeInsight.ExpectedTypesProvider
import com.intellij.codeInsight.TailType
import com.intellij.lang.java.JavaLanguage
import com.intellij.lang.java.request.ExpectedJavaType
import com.intellij.lang.jvm.JvmClass
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.actions.ExpectedType
import com.intellij.lang.jvm.actions.ExpectedTypes
import com.intellij.openapi.project.Project
import com.intellij.psi.JvmPsiConversionHelper
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiModifier.ModifierConstant
@@ -61,3 +69,25 @@ internal val visibilityModifiers = setOf(
JvmModifier.PACKAGE_LOCAL,
JvmModifier.PRIVATE
)
internal fun extractExpectedTypes(project: Project, expectedTypes: ExpectedTypes): List<ExpectedTypeInfo> {
return expectedTypes.mapNotNull {
toExpectedTypeInfo(project, it)
}
}
private fun toExpectedTypeInfo(project: Project, expectedType: ExpectedType): ExpectedTypeInfo? {
if (expectedType is ExpectedJavaType) return expectedType.info
val helper = JvmPsiConversionHelper.getInstance(project)
val psiType = helper.convertType(expectedType.theType) ?: return null
return ExpectedTypesProvider.createInfo(psiType, expectedType.theKind.infoKind(), psiType, TailType.NONE)
}
@ExpectedTypeInfo.Type
private fun ExpectedType.Kind.infoKind(): Int {
return when (this) {
ExpectedType.Kind.EXACT -> ExpectedTypeInfo.TYPE_STRICTLY
ExpectedType.Kind.SUPERTYPE -> ExpectedTypeInfo.TYPE_OR_SUPERTYPE
ExpectedType.Kind.SUBTYPE -> ExpectedTypeInfo.TYPE_OR_SUBTYPE
}
}
@@ -15,16 +15,11 @@
*/
package com.intellij.lang.java.request
import com.intellij.codeInsight.ExpectedTypeInfo
import com.intellij.codeInsight.ExpectedTypesProvider
import com.intellij.codeInsight.TailType
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils.guessExpectedTypes
import com.intellij.codeInsight.daemon.impl.quickfix.CreateMethodFromUsageFix.getTargetSubstitutor
import com.intellij.codeInsight.daemon.impl.quickfix.CreateMethodFromUsageFix.hasErrorsInArgumentList
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.ExpectedParameter
import com.intellij.lang.jvm.actions.*
import com.intellij.lang.jvm.types.JvmSubstitutor
import com.intellij.psi.*
import com.intellij.psi.codeStyle.JavaCodeStyleManager
@@ -52,7 +47,7 @@ class CreateMethodFromJavaUsageRequest(
override val methodName: String get() = methodCall.methodExpression.referenceName!!
override val returnType: Any? get() = guessExpectedTypes(methodCall, methodCall.parent is PsiStatement)
override val returnType: ExpectedTypes get() = guessExpectedTypes(methodCall, methodCall.parent is PsiStatement).map(::ExpectedJavaType)
override val targetSubstitutor: JvmSubstitutor get() {
val call = methodCall
@@ -76,11 +71,9 @@ class CreateMethodFromJavaUsageRequest(
else if (argType is PsiWildcardType) {
argType = if (argType.isBounded) argType.bound else PsiType.getJavaLangObject(psiManager, scope)
}
val expectedTypeInfo = argType?.let {
ExpectedTypesProvider.createInfo(it, ExpectedTypeInfo.TYPE_OR_SUPERTYPE, argType, TailType.NONE)
}
val expectedTypes: Any? = expectedTypeInfo?.let { arrayOf(it) } ?: emptyArray<ExpectedTypeInfo>()
Pair(names, expectedTypes)
val expectedTypeInfo = argType?.let { expectedType(it, ExpectedType.Kind.SUPERTYPE) }
val expectedTypes = expectedTypeInfo?.let { listOf(it) } ?: emptyList()
ExpectedParameter(names, expectedTypes)
}
}
@@ -0,0 +1,32 @@
/*
* 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.java.request
import com.intellij.codeInsight.ExpectedTypeInfo
import com.intellij.lang.jvm.actions.ExpectedType
import com.intellij.lang.jvm.types.JvmType
internal class ExpectedJavaType(val info: ExpectedTypeInfo) : ExpectedType {
override val theType: JvmType get() = info.defaultType
override val theKind: ExpectedType.Kind
get() = when (info.kind) {
ExpectedTypeInfo.TYPE_OR_SUBTYPE -> ExpectedType.Kind.SUBTYPE
ExpectedTypeInfo.TYPE_OR_SUPERTYPE -> ExpectedType.Kind.SUPERTYPE
else -> ExpectedType.Kind.EXACT
}
}
@@ -1,8 +1,5 @@
package org.jetbrains.plugins.javaFX.fxml.refs
import com.intellij.codeInsight.ExpectedTypeInfo
import com.intellij.codeInsight.ExpectedTypesProvider.createInfo
import com.intellij.codeInsight.TailType
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider
import com.intellij.lang.jvm.JvmModifier
@@ -52,16 +49,14 @@ class CreateEventHandlerRequest(element: XmlAttributeValue) : CreateMethodReques
override val methodName: String get() = myElement.value!!.substring(1)
override val returnType: Any? get() {
val typeInfo = createInfo(PsiType.VOID, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.VOID, TailType.NONE)
return arrayOf(typeInfo)
}
override val returnType: ExpectedTypes get() = listOf(expectedType(PsiType.VOID, ExpectedType.Kind.EXACT))
override val parameters: List<ExpectedParameter> get() {
val eventType = getEventType(myElement)
val typeInfo = createInfo(eventType, ExpectedTypeInfo.TYPE_STRICTLY, eventType, TailType.NONE)
val expectedType = expectedType(eventType, ExpectedType.Kind.EXACT)
val nameInfo = suggestParamName(myProject, eventType)
return listOf(ExpectedParameter(nameInfo, arrayOf(typeInfo)))
val parameter = ExpectedParameter(nameInfo, listOf(expectedType))
return listOf(parameter)
}
override val modifiers: Collection<JvmModifier> get() = setOf(myVisibility)