Adjust diagnostics rendering so that short classifier names are rendered unless the name is ambiguous in corresponding RenderingContext
This commit is contained in:
@@ -109,7 +109,7 @@ object Renderers {
|
||||
|
||||
@JvmField val RENDER_CLASS_OR_OBJECT_NAME = Renderer<ClassDescriptor> { it.renderKindWithName() }
|
||||
|
||||
@JvmField val RENDER_TYPE = Renderer<KotlinType> { DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it) }
|
||||
@JvmField val RENDER_TYPE = SmartTypeRenderer(DescriptorRenderer.FQ_NAMES_IN_TYPES)
|
||||
|
||||
@JvmField val RENDER_POSITION_VARIANCE = Renderer {
|
||||
variance: Variance ->
|
||||
@@ -442,6 +442,4 @@ object Renderers {
|
||||
}.asRenderer()
|
||||
}
|
||||
|
||||
fun DescriptorRenderer.asRenderer() = Renderer<DeclarationDescriptor> {
|
||||
render(it)
|
||||
}
|
||||
fun DescriptorRenderer.asRenderer() = SmartDescriptorRenderer(this)
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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 org.jetbrains.kotlin.diagnostics.rendering
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.renderer.ClassifierNamePolicy
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import java.util.*
|
||||
|
||||
val RenderingContext.adaptiveClassifierPolicy: ClassifierNamePolicy
|
||||
get() = this[ADAPTIVE_CLASSIFIER_POLICY_KEY]
|
||||
|
||||
private class AdaptiveClassifierNamePolicy(private val ambiguousNames: List<Name>) : ClassifierNamePolicy {
|
||||
private val renderedParameters = mutableMapOf<Name, LinkedHashSet<TypeParameterDescriptor>>()
|
||||
|
||||
override fun renderClassifier(classifier: ClassifierDescriptor, renderer: DescriptorRenderer): String {
|
||||
return when {
|
||||
hasUniqueName(classifier) -> ClassifierNamePolicy.SHORT.renderClassifier(classifier, renderer)
|
||||
classifier is ClassDescriptor -> ClassifierNamePolicy.FULLY_QUALIFIED.renderClassifier(classifier, renderer)
|
||||
classifier is TypeParameterDescriptor -> {
|
||||
val name = classifier.name
|
||||
val typeParametersWithSameName = renderedParameters.getOrPut(name) { LinkedHashSet() }
|
||||
val isFirstOccurence = typeParametersWithSameName.add(classifier)
|
||||
val index = typeParametersWithSameName.indexOf(classifier)
|
||||
renderer.renderAmbiguousTypeParameter(classifier, index + 1, isFirstOccurence)
|
||||
}
|
||||
else -> error("Unexpected classifier: ${classifier.javaClass}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasUniqueName(classifier: ClassifierDescriptor): Boolean {
|
||||
return classifier.name !in ambiguousNames
|
||||
}
|
||||
|
||||
private fun DescriptorRenderer.renderAmbiguousTypeParameter(
|
||||
typeParameter: TypeParameterDescriptor, index: Int, firstOccurence: Boolean
|
||||
) = buildString {
|
||||
append(typeParameter.name)
|
||||
append("#$index")
|
||||
if (firstOccurence) {
|
||||
append(renderMessage(" (type parameter of ${renderFqName(typeParameter.containingDeclaration.fqNameUnsafe)})"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val ADAPTIVE_CLASSIFIER_POLICY_KEY = object : RenderingContext.Key<ClassifierNamePolicy>("ADAPTIVE_CLASSIFIER_POLICY") {
|
||||
override fun compute(objectsToRender: Collection<Any?>): ClassifierNamePolicy {
|
||||
val ambiguousNames = collectClassifiers(objectsToRender).groupBy { it.name }.filter { it.value.size > 1 }.map { it.key }
|
||||
return AdaptiveClassifierNamePolicy(ambiguousNames)
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectClassifiers(objectsToRender: Collection<Any?>): Set<ClassifierDescriptor> = LinkedHashSet<ClassifierDescriptor>().apply {
|
||||
collectMentionedClassifiers(objectsToRender, this)
|
||||
}
|
||||
|
||||
private fun collectMentionedClassifiers(contextObjects: Collection<Any?>, result: MutableSet<ClassifierDescriptor>) {
|
||||
contextObjects.filterIsInstance<KotlinType>().forEach { diagnosticType ->
|
||||
diagnosticType.contains {
|
||||
innerType ->
|
||||
innerType.constructor.declarationDescriptor?.let { result.add(it) }
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
contextObjects.filterIsInstance<Collection<*>>().forEach {
|
||||
collectMentionedClassifiers(it, result)
|
||||
}
|
||||
contextObjects.filterIsInstance<ClassifierDescriptor>().forEach {
|
||||
result.add(it)
|
||||
}
|
||||
contextObjects.filterIsInstance<TypeParameterDescriptor>().forEach {
|
||||
collectMentionedClassifiers(it.upperBounds, result)
|
||||
}
|
||||
contextObjects.filterIsInstance<CallableDescriptor>().forEach {
|
||||
collectMentionedClassifiers(listOf(
|
||||
it.typeParameters,
|
||||
it.returnType,
|
||||
it.valueParameters,
|
||||
it.dispatchReceiverParameter?.type,
|
||||
it.extensionReceiverParameter?.type
|
||||
), result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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 org.jetbrains.kotlin.diagnostics.rendering
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class SmartTypeRenderer(private val baseRenderer: DescriptorRenderer) : DiagnosticParameterRenderer<KotlinType> {
|
||||
override fun render(obj: KotlinType, renderingContext: RenderingContext): String {
|
||||
val adaptiveRenderer = baseRenderer.withOptions {
|
||||
classifierNamePolicy = renderingContext.adaptiveClassifierPolicy
|
||||
}
|
||||
return adaptiveRenderer.renderType(obj)
|
||||
}
|
||||
}
|
||||
|
||||
class SmartDescriptorRenderer(private val baseRenderer: DescriptorRenderer) : DiagnosticParameterRenderer<DeclarationDescriptor> {
|
||||
override fun render(obj: DeclarationDescriptor, renderingContext: RenderingContext): String {
|
||||
val adaptiveRenderer = baseRenderer.withOptions {
|
||||
classifierNamePolicy = renderingContext.adaptiveClassifierPolicy
|
||||
}
|
||||
return adaptiveRenderer.render(obj)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2016 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2016 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.
|
||||
@@ -41,7 +41,6 @@ import java.util.*
|
||||
internal class DescriptorRendererImpl(
|
||||
val options: DescriptorRendererOptionsImpl
|
||||
) : DescriptorRenderer(), DescriptorRendererOptions by options/* this gives access to options without qualifier */ {
|
||||
|
||||
init {
|
||||
assert(options.isLocked)
|
||||
}
|
||||
@@ -604,7 +603,7 @@ internal class DescriptorRendererImpl(
|
||||
|
||||
val returnType = function.returnType
|
||||
if (!withoutReturnType && (unitReturnType || (returnType == null || !KotlinBuiltIns.isUnit(returnType)))) {
|
||||
builder.append(": ").append(if (returnType == null) "[NULL]" else escape(renderType(returnType)))
|
||||
builder.append(": ").append(if (returnType == null) "[NULL]" else renderType(returnType))
|
||||
}
|
||||
|
||||
renderWhereSuffix(function.typeParameters, builder)
|
||||
@@ -615,7 +614,7 @@ internal class DescriptorRendererImpl(
|
||||
|
||||
val receiver = callableDescriptor.extensionReceiverParameter
|
||||
if (receiver != null) {
|
||||
builder.append(" on ").append(escape(renderType(receiver.type)))
|
||||
builder.append(" on ").append(renderType(receiver.type))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,7 +622,7 @@ internal class DescriptorRendererImpl(
|
||||
val receiver = callableDescriptor.extensionReceiverParameter
|
||||
if (receiver != null) {
|
||||
val type = receiver.type
|
||||
var result = escape(renderType(type))
|
||||
var result = renderType(type)
|
||||
if (shouldRenderAsPrettyFunctionType(type) && !TypeUtils.isNullableType(type)) {
|
||||
result = "($result)"
|
||||
}
|
||||
@@ -659,7 +658,7 @@ internal class DescriptorRendererImpl(
|
||||
for (typeParameter in typeParameters) {
|
||||
typeParameter.upperBounds
|
||||
.drop(1) // first parameter is rendered by renderTypeParameter
|
||||
.mapTo(upperBoundStrings) { renderName(typeParameter.name) + " : " + escape(renderType(it)) }
|
||||
.mapTo(upperBoundStrings) { renderName(typeParameter.name) + " : " + renderType(it) }
|
||||
}
|
||||
|
||||
if (!upperBoundStrings.isEmpty()) {
|
||||
@@ -743,12 +742,12 @@ internal class DescriptorRendererImpl(
|
||||
builder.append(": ")
|
||||
}
|
||||
|
||||
builder.append(escape(renderType(typeToRender)))
|
||||
builder.append(renderType(typeToRender))
|
||||
|
||||
renderInitializer(variable, builder)
|
||||
|
||||
if (verbose && varargElementType != null) {
|
||||
builder.append(" /*").append(escape(renderType(realType))).append("*/")
|
||||
builder.append(" /*").append(renderType(realType)).append("*/")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,7 +770,7 @@ internal class DescriptorRendererImpl(
|
||||
}
|
||||
|
||||
renderName(property, builder)
|
||||
builder.append(": ").append(escape(renderType(property.type)))
|
||||
builder.append(": ").append(renderType(property.type))
|
||||
|
||||
renderReceiverAfterName(property, builder)
|
||||
|
||||
|
||||
+6
-3
@@ -21,9 +21,11 @@ import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.SmartDescriptorRenderer;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.DescriptorRow;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.FunctionArgumentsRow;
|
||||
@@ -109,7 +111,7 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer {
|
||||
}
|
||||
if (row instanceof DescriptorRow) {
|
||||
tdSpace(result);
|
||||
tdRightBoldColspan(result, 2, DESCRIPTOR_IN_TABLE.render(((DescriptorRow) row).descriptor));
|
||||
tdRightBoldColspan(result, 2, DESCRIPTOR_IN_TABLE.render(((DescriptorRow) row).descriptor, context));
|
||||
}
|
||||
if (row instanceof FunctionArgumentsRow) {
|
||||
FunctionArgumentsRow functionArgumentsRow = (FunctionArgumentsRow) row;
|
||||
@@ -209,7 +211,8 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer {
|
||||
}
|
||||
};
|
||||
|
||||
public static final DescriptorRenderer DESCRIPTOR_IN_TABLE = DescriptorRenderer.Companion.withOptions(
|
||||
private static final DiagnosticParameterRenderer<DeclarationDescriptor>
|
||||
DESCRIPTOR_IN_TABLE = new SmartDescriptorRenderer(DescriptorRenderer.Companion.withOptions(
|
||||
new Function1<DescriptorRendererOptions, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(DescriptorRendererOptions options) {
|
||||
@@ -219,7 +222,7 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer {
|
||||
options.setTextFormat(RenderingFormat.HTML);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
private static void td(StringBuilder builder, String text) {
|
||||
builder.append("<td style=\"white-space:nowrap;\">").append(text).append("</td>");
|
||||
|
||||
@@ -17,17 +17,13 @@
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.ContextDependentRenderer
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.asRenderer
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.*
|
||||
import org.jetbrains.kotlin.idea.highlighter.renderersUtil.renderResolvedCall
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import kotlin.comparisons.compareBy
|
||||
|
||||
object IdeRenderers {
|
||||
@@ -40,9 +36,7 @@ object IdeRenderers {
|
||||
.joinToString("") { "<li>${DescriptorRenderer.HTML.render(it)}</li>" }
|
||||
}
|
||||
|
||||
@JvmField val HTML_RENDER_TYPE = Renderer<KotlinType> {
|
||||
DescriptorRenderer.HTML.renderType(it)
|
||||
}
|
||||
@JvmField val HTML_RENDER_TYPE = SmartTypeRenderer(DescriptorRenderer.HTML)
|
||||
|
||||
@JvmField val HTML_NONE_APPLICABLE_CALLS= Renderer {
|
||||
calls: Collection<ResolvedCall<*>> ->
|
||||
|
||||
Reference in New Issue
Block a user