Render inferred and not inferred type parameters
while rendering a resolved call
This commit is contained in:
@@ -68,6 +68,8 @@ public interface DescriptorRenderer extends Renderer<DeclarationDescriptor> {
|
||||
|
||||
DescriptorRenderer HTML_FOR_UNINFERRED_TYPE_PARAMS = new DescriptorRendererBuilder()
|
||||
.setUninferredTypeParameterAsName(true)
|
||||
.setModifiers()
|
||||
.setShortNames(true)
|
||||
.setTextFormat(TextFormat.HTML).build();
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -28,9 +28,16 @@ import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||
import org.jetbrains.jet.plugin.highlighter.IdeRenderers
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||
|
||||
fun <D : CallableDescriptor> renderResolvedCall(resolvedCall: ResolvedCall<D>): String {
|
||||
val htmlRenderer = DescriptorRenderer.HTML
|
||||
val htmlRenderer = DescriptorRenderer.HTML_FOR_UNINFERRED_TYPE_PARAMS
|
||||
val stringBuilder = StringBuilder("")
|
||||
val indent = " "
|
||||
|
||||
fun append(any: Any): StringBuilder = stringBuilder.append(any)
|
||||
|
||||
fun renderParameter(parameter: ValueParameterDescriptor): String {
|
||||
val varargElementType = parameter.getVarargElementType()
|
||||
val parameterType = varargElementType ?: parameter.getType()
|
||||
@@ -44,21 +51,54 @@ fun <D : CallableDescriptor> renderResolvedCall(resolvedCall: ResolvedCall<D>):
|
||||
return renderedParameter
|
||||
}
|
||||
|
||||
val stringBuilder = StringBuilder("")
|
||||
val funDescriptor = resolvedCall.getResultingDescriptor()
|
||||
fun appendTypeParametersSubstitution() {
|
||||
val parametersToArgumentsMap = resolvedCall.getTypeArguments()
|
||||
fun TypeParameterDescriptor.isInferred(): Boolean {
|
||||
val typeArgument = parametersToArgumentsMap[this]
|
||||
if (typeArgument == null) return false
|
||||
return !ErrorUtils.isUninferredParameter(typeArgument)
|
||||
}
|
||||
|
||||
val receiverParameter = funDescriptor.getReceiverParameter()
|
||||
if (receiverParameter != null) {
|
||||
stringBuilder.append(htmlRenderer.renderType(receiverParameter.getType())).append(".")
|
||||
val typeParameters = resolvedCall.getCandidateDescriptor().getTypeParameters()
|
||||
val (inferredTypeParameters, notInferredTypeParameters) = typeParameters.partition { parameter -> parameter.isInferred() }
|
||||
|
||||
append("<br/>$indent<i>where</i> ")
|
||||
if (!notInferredTypeParameters.isEmpty()) {
|
||||
append(notInferredTypeParameters.map { typeParameter -> IdeRenderers.error(typeParameter.getName()) }.makeString())
|
||||
append("<i> cannot be inferred</i>")
|
||||
if (!inferredTypeParameters.isEmpty()) {
|
||||
append("; ")
|
||||
}
|
||||
}
|
||||
|
||||
val typeParameterToTypeArgumentMap = resolvedCall.getTypeArguments()
|
||||
if (!inferredTypeParameters.isEmpty()) {
|
||||
append(inferredTypeParameters.map { typeParameter ->
|
||||
"${typeParameter.getName()} = ${htmlRenderer.renderType(typeParameterToTypeArgumentMap[typeParameter]!!)}"
|
||||
}.makeString())
|
||||
}
|
||||
}
|
||||
stringBuilder.append(funDescriptor.getName()).append("(")
|
||||
stringBuilder.append(funDescriptor.getValueParameters().map(::renderParameter).makeString(","))
|
||||
stringBuilder.append(if (resolvedCall.hasUnmappedArguments()) IdeRenderers.error(")") else ")")
|
||||
|
||||
stringBuilder.append(" <i>defined in</i> ")
|
||||
val containingDeclaration = funDescriptor.getContainingDeclaration()
|
||||
val fqName = DescriptorUtils.getFqName(containingDeclaration)
|
||||
stringBuilder.append(if (FqName.ROOT.equalsTo(fqName)) "root package" else fqName.asString())
|
||||
val resultingDescriptor = resolvedCall.getResultingDescriptor()
|
||||
val receiverParameter = resultingDescriptor.getReceiverParameter()
|
||||
if (receiverParameter != null) {
|
||||
append(htmlRenderer.renderType(receiverParameter.getType())).append(".")
|
||||
}
|
||||
append(resultingDescriptor.getName()).append("(")
|
||||
append(resultingDescriptor.getValueParameters().map { parameter -> renderParameter(parameter) }.makeString())
|
||||
append(if (resolvedCall.hasUnmappedArguments()) IdeRenderers.error(")") else ")")
|
||||
|
||||
if (!resolvedCall.getCandidateDescriptor().getTypeParameters().isEmpty()) {
|
||||
appendTypeParametersSubstitution()
|
||||
append("<i> for </i><br/>$indent")
|
||||
append(htmlRenderer.render(resolvedCall.getCandidateDescriptor()))
|
||||
}
|
||||
else {
|
||||
append(" <i>defined in</i> ")
|
||||
val containingDeclaration = resultingDescriptor.getContainingDeclaration()
|
||||
val fqName = DescriptorUtils.getFqName(containingDeclaration)
|
||||
append(if (FqName.ROOT.equalsTo(fqName)) "root package" else fqName.asString())
|
||||
}
|
||||
return stringBuilder.toString()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<!-- noneApplicable1 -->
|
||||
<html>
|
||||
None of the following functions can be called with the arguments supplied. <ul>
|
||||
<li>foo(kotlin.Int, kotlin.String, <font color=red><b>kotlin.Boolean</b></font>) <i>defined in</i> root package</li>
|
||||
<li>foo(<font color=red><b>kotlin.Boolean</b></font>, kotlin.String) <i>defined in</i> root package</li>
|
||||
<li>foo(kotlin.Int<font color=red><b>)</b></font> <i>defined in</i> root package</li>
|
||||
None of the following functions can be called with the arguments supplied.
|
||||
<ul>
|
||||
<li>foo(Int, String, <font color=red><b>Boolean</b></font>) <i>defined in</i> root package</li>
|
||||
<li>foo(<font color=red><b>Boolean</b></font>, String) <i>defined in</i> root package</li>
|
||||
<li>foo(Int<font color=red><b>)</b></font> <i>defined in</i> root package</li>
|
||||
</ul>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
// !DIAGNOSTICS_NUMBER: 1
|
||||
// !DIAGNOSTICS: NONE_APPLICABLE
|
||||
// !MESSAGE_TYPE: HTML
|
||||
|
||||
package p
|
||||
|
||||
fun <T> foo(t: T, a: Any, l: List<T>) = 1
|
||||
fun <T, R> foo(t: T, r: R, lt: MutableList<T>, lr: MutableList<R>) = 2
|
||||
fun <T> foo(t: T, a: Any, lt: MutableList<T>, lr: MutableList<T>) = 3
|
||||
|
||||
fun use(vararg a: Any?) = a
|
||||
|
||||
fun test(a: Any, li: MutableList<Int>, ls: MutableList<String>) {
|
||||
use(foo(11, a, li, ls))
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<!-- noneApplicableGeneric1 -->
|
||||
<html>
|
||||
None of the following functions can be called with the arguments supplied.
|
||||
<ul>
|
||||
<li>foo(Int, Any, List<`Int><font color=red><b>)</b></font><br/>
|
||||
<i>where</i> T = Int<i> for </i><br/>
|
||||
<b>fun</b> <`T> foo(t: T, a: Any, l: List<`T>): Int <i>defined in</i> p</li>
|
||||
<li>foo(Int, <font color=red><b>R</b></font>, MutableList<`Int>, MutableList<`<font color=red><b>R</b></font>>)<br/>
|
||||
<i>where</i> <font color=red><b>R</b></font><i> cannot be inferred</i>; T = Int<i> for </i><br/>
|
||||
<b>fun</b> <`T, R> foo(t: T, r: R, lt: MutableList<`T>, lr: MutableList<`R>): Int <i>defined in</i> p</li>
|
||||
<li>foo(<font color=red><b>T</b></font>, Any, MutableList<`<font color=red><b>T</b></font>>, MutableList<`<font color=red><b>T</b></font>>)<br/>
|
||||
<i>where</i> <font color=red><b>T</b></font><i> cannot be inferred</i><i> for </i><br/>
|
||||
<b>fun</b> <`T> foo(t: T, a: Any, lt: MutableList<`T>, lr: MutableList<`T>): Int <i>defined in</i> p</li>
|
||||
</ul>
|
||||
</html>
|
||||
@@ -101,6 +101,11 @@ public class DiagnosticMessageTestGenerated extends AbstractDiagnosticMessageTes
|
||||
doTest("idea/testData/diagnosticMessage/noneApplicable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noneApplicableGeneric.kt")
|
||||
public void testNoneApplicableGeneric() throws Exception {
|
||||
doTest("idea/testData/diagnosticMessage/noneApplicableGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("numberValueTypes.kt")
|
||||
public void testNumberValueTypes() throws Exception {
|
||||
doTest("idea/testData/diagnosticMessage/numberValueTypes.kt");
|
||||
|
||||
Reference in New Issue
Block a user