Render inferred and not inferred type parameters

while rendering a resolved call
This commit is contained in:
Svetlana Isakova
2014-04-24 20:03:38 +04:00
parent aa40fd6b56
commit a57b4f6459
6 changed files with 95 additions and 17 deletions
@@ -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 = "&nbsp;&nbsp;"
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");