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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user