Prototype of inlay hints for suspending calls (KT-20187)

This commit is contained in:
Dmitry Jemerov
2018-01-04 17:37:24 +01:00
parent d060203896
commit 45282af38b
4 changed files with 78 additions and 15 deletions
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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/LICENSE.txt file.
* 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 org.jetbrains.kotlin.idea.test package org.jetbrains.kotlin.idea.test
@@ -85,6 +74,7 @@ object DirectiveBasedActionUtils {
"Show function return type hints", "Show function return type hints",
"Show property type hints", "Show property type hints",
"Show parameter type hints", "Show parameter type hints",
"Show argument name hints" "Show argument name hints",
"Show hints for suspending calls"
) )
} }
@@ -14,6 +14,7 @@ import com.intellij.lang.java.JavaLanguage
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.getReturnTypeReference import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.getReturnTypeReference
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -83,9 +84,11 @@ enum class HintType(desc: String, enabled: Boolean) {
override fun isApplicable(elem: PsiElement): Boolean = elem is KtValueArgumentList override fun isApplicable(elem: PsiElement): Boolean = elem is KtValueArgumentList
}, },
LAMBDA_RETURN_EXPRESSION("Show lambda return expression hints", true) { LAMBDA_RETURN_EXPRESSION("Show lambda return expression hints", true) {
override fun isApplicable(elem: PsiElement) = override fun isApplicable(elem: PsiElement) =
elem is KtExpression && elem !is KtLambdaExpression && elem !is KtFunctionLiteral elem is KtExpression && elem !is KtLambdaExpression && elem !is KtFunctionLiteral &&
!elem.isNameReferenceInCall()
override fun provideHints(elem: PsiElement): List<InlayInfo> { override fun provideHints(elem: PsiElement): List<InlayInfo> {
if (elem is KtExpression) { if (elem is KtExpression) {
@@ -104,6 +107,14 @@ enum class HintType(desc: String, enabled: Boolean) {
} }
return emptyList() return emptyList()
} }
},
SUSPENDING_CALL("Show hints for suspending calls", false) {
override fun isApplicable(elem: PsiElement) = elem.isNameReferenceInCall() && KotlinInternalMode.enabled
override fun provideHints(elem: PsiElement): List<InlayInfo> {
val callExpression = elem.parent as? KtCallExpression ?: return emptyList()
return provideSuspendingCallHint(callExpression)?.let { listOf(it) } ?: emptyList()
}
}; };
companion object { companion object {
@@ -178,3 +189,5 @@ class KotlinInlayParameterHintsProvider : InlayParameterHintsProvider {
} }
} }
private fun PsiElement.isNameReferenceInCall() =
this is KtNameReferenceExpression && parent is KtCallExpression
@@ -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/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.parameterInfo
import com.intellij.codeInsight.hints.InlayInfo
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
fun provideSuspendingCallHint(callExpression: KtCallExpression): InlayInfo? {
val bindingContext = callExpression.analyze(BodyResolveMode.PARTIAL)
val call = bindingContext[BindingContext.CALL, callExpression.calleeExpression] ?: return null
val resolvedCall = bindingContext[BindingContext.RESOLVED_CALL, call] ?: return null
if (resolvedCall.candidateDescriptor.isSuspend) {
return InlayInfo(TYPE_INFO_PREFIX + "#", callExpression.calleeExpression?.startOffset ?: callExpression.startOffset)
}
return null
}
@@ -0,0 +1,36 @@
/*
* 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/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.parameterInfo
import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
class SuspendingCallHintsTest : KotlinLightCodeInsightFixtureTestCase() {
override fun getProjectDescriptor(): KotlinLightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
fun check(text: String) {
KotlinInternalMode.enabled = true
try {
HintType.SUSPENDING_CALL.option.set(true)
myFixture.configureByText("A.kt", text)
myFixture.testInlays()
} finally {
KotlinInternalMode.enabled = false
}
}
fun testSimple() {
check(
"""import kotlin.coroutines.experimental.buildSequence
val x = buildSequence {<hint text="this: SequenceBuilder<Int>" />
<hint text="#" />yield(<hint text="value:" />1)
} """
)
}
}