Parameter info fetches default parameter values from library sources

This commit is contained in:
Valentin Kipyatkov
2015-10-05 21:50:43 +03:00
parent 778e2f6f0b
commit a923e9e9c8
5 changed files with 47 additions and 28 deletions
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import java.util.*
public object OptionalParametersHelper {
@@ -114,26 +115,30 @@ public object OptionalParametersHelper {
public val parameterUsages: Map<ValueParameterDescriptor, Collection<JetExpression>>
)
//TODO: handle imports
//TODO: handle implicit receivers
public fun defaultParameterValue(parameter: ValueParameterDescriptor, project: Project): DefaultValue? {
public fun defaultParameterValueExpression(parameter: ValueParameterDescriptor, project: Project): JetExpression? {
if (!parameter.hasDefaultValue()) return null
if (!parameter.declaresDefaultValue()) {
val overridden = parameter.getOverriddenDescriptors().firstOrNull { it.hasDefaultValue() } ?: return null
return defaultParameterValue(overridden, project)
return defaultParameterValueExpression(overridden, project)
}
//TODO: parameter in overriding method!
//TODO: it's a temporary code while we don't have default values accessible from descriptors
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, parameter)?.getNavigationElement() as? JetParameter
val expression = declaration?.getDefaultValue() ?: return null
return declaration?.defaultValue
}
//TODO: handle imports
//TODO: handle implicit receivers
public fun defaultParameterValue(parameter: ValueParameterDescriptor, project: Project): DefaultValue? {
val expression = defaultParameterValueExpression(parameter, project) ?: return null
val allParameters = parameter.getContainingDeclaration().getValueParameters().toSet()
val parameterUsages = HashMap<ValueParameterDescriptor, MutableCollection<JetExpression>>()
val bindingContext = expression.analyze()
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
expression.forEachDescendantOfType<JetSimpleNameExpression> {
val target = bindingContext[BindingContext.REFERENCE_TARGET, it]
if (target is ValueParameterDescriptor && target in allParameters) {
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.idea.parameterInfo
import com.intellij.codeInsight.CodeInsightBundle
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.lang.parameterInfo.*
import com.intellij.psi.PsiElement
import com.intellij.openapi.project.Project
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.ui.Gray
import com.intellij.ui.JBColor
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.OptionalParametersHelper
import org.jetbrains.kotlin.idea.core.getResolutionScope
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.resolve.frontendService
@@ -146,6 +147,8 @@ class KotlinFunctionParameterInfoHandler : ParameterInfoHandlerWithTabActionSupp
val callElement = argumentList.parent as? JetCallElement ?: return false
val call = callElement.getCall(bindingContext) ?: return false
val project = callElement.project
val currentParameterIndex = context.currentParameterIndex
if (currentParameterIndex < 0) return false // by some strange reason we are invoked with currentParameterIndex == -1 during initialization
@@ -169,7 +172,7 @@ class KotlinFunctionParameterInfoHandler : ParameterInfoHandlerWithTabActionSupp
boldStartOffset = length()
}
append(renderParameter(parameter, namedMode))
append(renderParameter(parameter, namedMode, project))
if (highlightParameter) {
boldEndOffset = length()
@@ -214,40 +217,40 @@ class KotlinFunctionParameterInfoHandler : ParameterInfoHandlerWithTabActionSupp
companion object {
val GREEN_BACKGROUND: Color = JBColor(Color(231, 254, 234), Gray._100)
private fun renderParameter(parameter: ValueParameterDescriptor, named: Boolean): String {
private fun renderParameter(parameter: ValueParameterDescriptor, named: Boolean, project: Project): String {
return StringBuilder {
if (named) append("[")
if (parameter.varargElementType != null) {
append("vararg ")
}
append(parameter.name)
append(": ")
append(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(parameterTypeToRender(parameter)))
if (parameter.hasDefaultValue()) {
val parameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(parameter)
append(" = ")
append(getDefaultExpressionString(parameterDeclaration))
append(parameter.renderDefaultValue(project))
}
if (named) append("]")
}.toString()
}
private fun getDefaultExpressionString(parameterDeclaration: PsiElement?): String {
if (parameterDeclaration is JetParameter) {
val defaultValue = parameterDeclaration.defaultValue
if (defaultValue != null) {
val defaultExpression = defaultValue.text
if (defaultExpression.length() <= 32) {
return defaultExpression
}
private fun ValueParameterDescriptor.renderDefaultValue(project: Project): String {
val expression = OptionalParametersHelper.defaultParameterValueExpression(this, project)
if (expression != null) {
val text = expression.text
if (text.length() <= 32) {
return text
}
if (defaultValue is JetConstantExpression || defaultValue is JetStringTemplateExpression) {
if (defaultExpression.startsWith("\"")) {
return "\"...\""
}
else if (defaultExpression.startsWith("\'")) {
return "\'...\'"
}
if (expression is JetConstantExpression || expression is JetStringTemplateExpression) {
if (text.startsWith("\"")) {
return "\"...\""
}
else if (text.startsWith("\'")) {
return "\'...\'"
}
}
}
@@ -0,0 +1,5 @@
fun f() {
listOf(1).joinToString(<caret>)
}
//Text: (<highlight>separator: String = ", "</highlight>, prefix: String = "", postfix: String = "", limit: Int = -1, truncated: String = "...", transform: ((Int) -> String)? = null), Disabled: false, Strikeout: false, Green: true
@@ -20,8 +20,8 @@ import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiWhiteSpace
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.test.JetWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.ProjectDescriptorWithStdlibSources
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.JetFile
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.junit.Assert
abstract class AbstractFunctionParameterInfoTest : LightCodeInsightFixtureTestCase() {
override fun getProjectDescriptor() = JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
override fun getProjectDescriptor() = ProjectDescriptorWithStdlibSources.INSTANCE
override fun setUp() {
super.setUp()
@@ -35,6 +35,12 @@ public class FunctionParameterInfoTestGenerated extends AbstractFunctionParamete
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/parameterInfo/functionParameterInfo"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("DefaultValuesFromLib.kt")
public void testDefaultValuesFromLib() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/parameterInfo/functionParameterInfo/DefaultValuesFromLib.kt");
doTest(fileName);
}
@TestMetadata("Deprecated.kt")
public void testDeprecated() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/parameterInfo/functionParameterInfo/Deprecated.kt");