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_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 {
|
@JvmField val RENDER_POSITION_VARIANCE = Renderer {
|
||||||
variance: Variance ->
|
variance: Variance ->
|
||||||
@@ -442,6 +442,4 @@ object Renderers {
|
|||||||
}.asRenderer()
|
}.asRenderer()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DescriptorRenderer.asRenderer() = Renderer<DeclarationDescriptor> {
|
fun DescriptorRenderer.asRenderer() = SmartDescriptorRenderer(this)
|
||||||
render(it)
|
|
||||||
}
|
|
||||||
+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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -41,7 +41,6 @@ import java.util.*
|
|||||||
internal class DescriptorRendererImpl(
|
internal class DescriptorRendererImpl(
|
||||||
val options: DescriptorRendererOptionsImpl
|
val options: DescriptorRendererOptionsImpl
|
||||||
) : DescriptorRenderer(), DescriptorRendererOptions by options/* this gives access to options without qualifier */ {
|
) : DescriptorRenderer(), DescriptorRendererOptions by options/* this gives access to options without qualifier */ {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
assert(options.isLocked)
|
assert(options.isLocked)
|
||||||
}
|
}
|
||||||
@@ -604,7 +603,7 @@ internal class DescriptorRendererImpl(
|
|||||||
|
|
||||||
val returnType = function.returnType
|
val returnType = function.returnType
|
||||||
if (!withoutReturnType && (unitReturnType || (returnType == null || !KotlinBuiltIns.isUnit(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)
|
renderWhereSuffix(function.typeParameters, builder)
|
||||||
@@ -615,7 +614,7 @@ internal class DescriptorRendererImpl(
|
|||||||
|
|
||||||
val receiver = callableDescriptor.extensionReceiverParameter
|
val receiver = callableDescriptor.extensionReceiverParameter
|
||||||
if (receiver != null) {
|
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
|
val receiver = callableDescriptor.extensionReceiverParameter
|
||||||
if (receiver != null) {
|
if (receiver != null) {
|
||||||
val type = receiver.type
|
val type = receiver.type
|
||||||
var result = escape(renderType(type))
|
var result = renderType(type)
|
||||||
if (shouldRenderAsPrettyFunctionType(type) && !TypeUtils.isNullableType(type)) {
|
if (shouldRenderAsPrettyFunctionType(type) && !TypeUtils.isNullableType(type)) {
|
||||||
result = "($result)"
|
result = "($result)"
|
||||||
}
|
}
|
||||||
@@ -659,7 +658,7 @@ internal class DescriptorRendererImpl(
|
|||||||
for (typeParameter in typeParameters) {
|
for (typeParameter in typeParameters) {
|
||||||
typeParameter.upperBounds
|
typeParameter.upperBounds
|
||||||
.drop(1) // first parameter is rendered by renderTypeParameter
|
.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()) {
|
if (!upperBoundStrings.isEmpty()) {
|
||||||
@@ -743,12 +742,12 @@ internal class DescriptorRendererImpl(
|
|||||||
builder.append(": ")
|
builder.append(": ")
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.append(escape(renderType(typeToRender)))
|
builder.append(renderType(typeToRender))
|
||||||
|
|
||||||
renderInitializer(variable, builder)
|
renderInitializer(variable, builder)
|
||||||
|
|
||||||
if (verbose && varargElementType != null) {
|
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)
|
renderName(property, builder)
|
||||||
builder.append(": ").append(escape(renderType(property.type)))
|
builder.append(": ").append(renderType(property.type))
|
||||||
|
|
||||||
renderReceiverAfterName(property, builder)
|
renderReceiverAfterName(property, builder)
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -21,9 +21,11 @@ import kotlin.Unit;
|
|||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer;
|
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer;
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext;
|
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;
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.DescriptorRow;
|
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.DescriptorRow;
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.FunctionArgumentsRow;
|
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.FunctionArgumentsRow;
|
||||||
@@ -109,7 +111,7 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer {
|
|||||||
}
|
}
|
||||||
if (row instanceof DescriptorRow) {
|
if (row instanceof DescriptorRow) {
|
||||||
tdSpace(result);
|
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) {
|
if (row instanceof FunctionArgumentsRow) {
|
||||||
FunctionArgumentsRow functionArgumentsRow = (FunctionArgumentsRow) row;
|
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>() {
|
new Function1<DescriptorRendererOptions, Unit>() {
|
||||||
@Override
|
@Override
|
||||||
public Unit invoke(DescriptorRendererOptions options) {
|
public Unit invoke(DescriptorRendererOptions options) {
|
||||||
@@ -219,7 +222,7 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer {
|
|||||||
options.setTextFormat(RenderingFormat.HTML);
|
options.setTextFormat(RenderingFormat.HTML);
|
||||||
return Unit.INSTANCE;
|
return Unit.INSTANCE;
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
|
|
||||||
private static void td(StringBuilder builder, String text) {
|
private static void td(StringBuilder builder, String text) {
|
||||||
builder.append("<td style=\"white-space:nowrap;\">").append(text).append("</td>");
|
builder.append("<td style=\"white-space:nowrap;\">").append(text).append("</td>");
|
||||||
|
|||||||
@@ -17,17 +17,13 @@
|
|||||||
package org.jetbrains.kotlin.idea.highlighter
|
package org.jetbrains.kotlin.idea.highlighter
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.ContextDependentRenderer
|
import org.jetbrains.kotlin.diagnostics.rendering.*
|
||||||
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.idea.highlighter.renderersUtil.renderResolvedCall
|
import org.jetbrains.kotlin.idea.highlighter.renderersUtil.renderResolvedCall
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
import org.jetbrains.kotlin.resolve.MemberComparator
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import kotlin.comparisons.compareBy
|
import kotlin.comparisons.compareBy
|
||||||
|
|
||||||
object IdeRenderers {
|
object IdeRenderers {
|
||||||
@@ -40,9 +36,7 @@ object IdeRenderers {
|
|||||||
.joinToString("") { "<li>${DescriptorRenderer.HTML.render(it)}</li>" }
|
.joinToString("") { "<li>${DescriptorRenderer.HTML.render(it)}</li>" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField val HTML_RENDER_TYPE = Renderer<KotlinType> {
|
@JvmField val HTML_RENDER_TYPE = SmartTypeRenderer(DescriptorRenderer.HTML)
|
||||||
DescriptorRenderer.HTML.renderType(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmField val HTML_NONE_APPLICABLE_CALLS= Renderer {
|
@JvmField val HTML_NONE_APPLICABLE_CALLS= Renderer {
|
||||||
calls: Collection<ResolvedCall<*>> ->
|
calls: Collection<ResolvedCall<*>> ->
|
||||||
|
|||||||
Reference in New Issue
Block a user