diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.java b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.java deleted file mode 100644 index 7c119e05ffe..00000000000 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2010-2015 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.renderer; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.descriptors.FunctionDescriptor; -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.kotlin.name.FqNameBase; -import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.types.JetType; -import org.jetbrains.kotlin.types.TypeProjection; - -import java.util.List; - -public interface DescriptorRenderer extends Renderer { - DescriptorRenderer COMPACT_WITH_MODIFIERS = new DescriptorRendererBuilder().setWithDefinedIn(false).build(); - - DescriptorRenderer COMPACT = new DescriptorRendererBuilder() - .setWithDefinedIn(false) - .setModifiers().build(); - - DescriptorRenderer COMPACT_WITH_SHORT_TYPES = new DescriptorRendererBuilder() - .setModifiers() - .setNameShortness(NameShortness.SHORT) - .setParameterNameRenderingPolicy(ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED).build(); - - DescriptorRenderer STARTS_FROM_NAME = new DescriptorRendererBuilder() - .setWithDefinedIn(false) - .setModifiers() - .setStartFromName(true).build(); - - DescriptorRenderer ONLY_NAMES_WITH_SHORT_TYPES = new DescriptorRendererBuilder() - .setWithDefinedIn(false) - .setModifiers() - .setNameShortness(NameShortness.SHORT) - .setWithoutTypeParameters(true) - .setParameterNameRenderingPolicy(ParameterNameRenderingPolicy.NONE) - .setReceiverAfterName(true) - .setRenderCompanionObjectName(true) - .setWithoutSuperTypes(true) - .setStartFromName(true).build(); - - DescriptorRenderer FQ_NAMES_IN_TYPES = new DescriptorRendererBuilder().build(); - - DescriptorRenderer SHORT_NAMES_IN_TYPES = new DescriptorRendererBuilder() - .setNameShortness(NameShortness.SHORT) - .setParameterNameRenderingPolicy(ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED) - .build(); - - DescriptorRenderer DEBUG_TEXT = new DescriptorRendererBuilder() - .setDebugMode(true) - .setNameShortness(NameShortness.FULLY_QUALIFIED) - .build(); - - DescriptorRenderer FLEXIBLE_TYPES_FOR_CODE = new DescriptorRendererBuilder() - .setFlexibleTypesForCode(true) - .build(); - - DescriptorRenderer HTML_COMPACT_WITH_MODIFIERS = new DescriptorRendererBuilder() - .setWithDefinedIn(false) - .setTextFormat(TextFormat.HTML).build(); - - DescriptorRenderer HTML_NAMES_WITH_SHORT_TYPES = new DescriptorRendererBuilder() - .setWithDefinedIn(false) - .setNameShortness(NameShortness.SHORT) - .setRenderCompanionObjectName(true) - .setTextFormat(TextFormat.HTML).build(); - - DescriptorRenderer HTML = new DescriptorRendererBuilder().setTextFormat(TextFormat.HTML).build(); - - DescriptorRenderer HTML_FOR_UNINFERRED_TYPE_PARAMS = new DescriptorRendererBuilder() - .setUninferredTypeParameterAsName(true) - .setModifiers() - .setNameShortness(NameShortness.SHORT) - .setTextFormat(TextFormat.HTML).build(); - - DescriptorRenderer DEPRECATION = new DescriptorRendererBuilder() - .setWithDefinedIn(false) - .setModifiers() - .setNameShortness(NameShortness.SHORT) - .setWithoutTypeParameters(false) - .setParameterNameRenderingPolicy(ParameterNameRenderingPolicy.NONE) - .setReceiverAfterName(false) - .setRenderCompanionObjectName(true) - .setRenderAccessors(true) - .setWithoutSuperTypes(true) - .setRenderDefaultValues(false) - .setStartFromName(true).build(); - - @NotNull - String renderType(@NotNull JetType type); - - @NotNull - String renderTypeArguments(@NotNull List typeArguments); - - @NotNull - String renderClassifierName(@NotNull ClassifierDescriptor klass); - - @NotNull - String renderAnnotation(@NotNull AnnotationDescriptor annotation); - - @NotNull - @Override - String render(@NotNull DeclarationDescriptor declarationDescriptor); - - @NotNull - String renderFunctionParameters(@NotNull FunctionDescriptor functionDescriptor); - - @NotNull - String renderName(@NotNull Name name); - - @NotNull - String renderFqName(@NotNull FqNameBase fqName); - - enum TextFormat { - PLAIN, HTML - } - - enum OverrideRenderingPolicy { - RENDER_OVERRIDE, RENDER_OPEN, RENDER_OPEN_OVERRIDE - } - - enum ParameterNameRenderingPolicy { - ALL, ONLY_NON_SYNTHESIZED, NONE - } - - enum Modifier { - VISIBILITY, MODALITY, OVERRIDE, ANNOTATIONS, INNER, MEMBER_KIND - } - - /** @see DefaultValueParameterHandler */ - interface ValueParametersHandler { - void appendBeforeValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder stringBuilder); - void appendAfterValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder stringBuilder); - - void appendBeforeValueParameter(@NotNull ValueParameterDescriptor parameter, @NotNull StringBuilder stringBuilder); - void appendAfterValueParameter(@NotNull ValueParameterDescriptor parameter, @NotNull StringBuilder stringBuilder); - } - - class DefaultValueParameterHandler implements ValueParametersHandler { - @Override - public void appendBeforeValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder stringBuilder) { - stringBuilder.append("("); - } - - @Override - public void appendAfterValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder stringBuilder) { - stringBuilder.append(")"); - } - - @Override - public void appendBeforeValueParameter(@NotNull ValueParameterDescriptor parameter, @NotNull StringBuilder stringBuilder) { - } - - @Override - public void appendAfterValueParameter(@NotNull ValueParameterDescriptor parameter, @NotNull StringBuilder stringBuilder) { - FunctionDescriptor function = (FunctionDescriptor) parameter.getContainingDeclaration(); - if (parameter.getIndex() != function.getValueParameters().size() - 1) { - stringBuilder.append(", "); - } - } - } -} diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt new file mode 100644 index 00000000000..84a8f6533ea --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRenderer.kt @@ -0,0 +1,190 @@ +/* + * Copyright 2010-2015 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.renderer + +import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.name.FqNameBase +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.JetType +import org.jetbrains.kotlin.types.TypeProjection + +public interface DescriptorRenderer : Renderer { + + public fun renderType(type: JetType): String + + public fun renderTypeArguments(typeArguments: List): String + + public fun renderClassifierName(klass: ClassifierDescriptor): String + + public fun renderAnnotation(annotation: AnnotationDescriptor): String + + override fun render(declarationDescriptor: DeclarationDescriptor): String + + public fun renderFunctionParameters(functionDescriptor: FunctionDescriptor): String + + public fun renderName(name: Name): String + + public fun renderFqName(fqName: FqNameBase): String + + public enum class TextFormat { + PLAIN, + HTML + } + + public enum class OverrideRenderingPolicy { + RENDER_OVERRIDE, + RENDER_OPEN, + RENDER_OPEN_OVERRIDE + } + + public enum class ParameterNameRenderingPolicy { + ALL, + ONLY_NON_SYNTHESIZED, + NONE + } + + public enum class Modifier { + VISIBILITY, + MODALITY, + OVERRIDE, + ANNOTATIONS, + INNER, + MEMBER_KIND + } + + /** @see DefaultValueParameterHandler + */ + public interface ValueParametersHandler { + public fun appendBeforeValueParameters(function: FunctionDescriptor, stringBuilder: StringBuilder) + public fun appendAfterValueParameters(function: FunctionDescriptor, stringBuilder: StringBuilder) + + public fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, stringBuilder: StringBuilder) + public fun appendAfterValueParameter(parameter: ValueParameterDescriptor, stringBuilder: StringBuilder) + } + + public class DefaultValueParameterHandler : ValueParametersHandler { + override fun appendBeforeValueParameters(function: FunctionDescriptor, stringBuilder: StringBuilder) { + stringBuilder.append("(") + } + + override fun appendAfterValueParameters(function: FunctionDescriptor, stringBuilder: StringBuilder) { + stringBuilder.append(")") + } + + override fun appendBeforeValueParameter(parameter: ValueParameterDescriptor, stringBuilder: StringBuilder) { + } + + override fun appendAfterValueParameter(parameter: ValueParameterDescriptor, stringBuilder: StringBuilder) { + val function = parameter.getContainingDeclaration() as FunctionDescriptor + if (parameter.getIndex() != function.getValueParameters().size() - 1) { + stringBuilder.append(", ") + } + } + } + + companion object { + public val COMPACT_WITH_MODIFIERS: DescriptorRenderer = DescriptorRendererBuilder() + .setWithDefinedIn(false) + .build() + + public val COMPACT: DescriptorRenderer = DescriptorRendererBuilder() + .setWithDefinedIn(false) + .setModifiers() + .build() + + public val COMPACT_WITH_SHORT_TYPES: DescriptorRenderer = DescriptorRendererBuilder() + .setModifiers() + .setNameShortness(NameShortness.SHORT) + .setParameterNameRenderingPolicy(ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED) + .build() + + public val STARTS_FROM_NAME: DescriptorRenderer = DescriptorRendererBuilder() + .setWithDefinedIn(false) + .setModifiers() + .setStartFromName(true) + .build() + + public val ONLY_NAMES_WITH_SHORT_TYPES: DescriptorRenderer = DescriptorRendererBuilder() + .setWithDefinedIn(false) + .setModifiers() + .setNameShortness(NameShortness.SHORT) + .setWithoutTypeParameters(true) + .setParameterNameRenderingPolicy(ParameterNameRenderingPolicy.NONE) + .setReceiverAfterName(true) + .setRenderCompanionObjectName(true) + .setWithoutSuperTypes(true) + .setStartFromName(true) + .build() + + public val FQ_NAMES_IN_TYPES: DescriptorRenderer = DescriptorRendererBuilder().build() + + public val SHORT_NAMES_IN_TYPES: DescriptorRenderer = DescriptorRendererBuilder() + .setNameShortness(NameShortness.SHORT) + .setParameterNameRenderingPolicy(ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED) + .build() + + public val DEBUG_TEXT: DescriptorRenderer = DescriptorRendererBuilder() + .setDebugMode(true) + .setNameShortness(NameShortness.FULLY_QUALIFIED) + .build() + + public val FLEXIBLE_TYPES_FOR_CODE: DescriptorRenderer = DescriptorRendererBuilder() + .setFlexibleTypesForCode(true) + .build() + + public val HTML_COMPACT_WITH_MODIFIERS: DescriptorRenderer = DescriptorRendererBuilder() + .setWithDefinedIn(false) + .setTextFormat(TextFormat.HTML) + .build() + + public val HTML_NAMES_WITH_SHORT_TYPES: DescriptorRenderer = DescriptorRendererBuilder() + .setWithDefinedIn(false) + .setNameShortness(NameShortness.SHORT) + .setRenderCompanionObjectName(true) + .setTextFormat(TextFormat.HTML) + .build() + + public val HTML: DescriptorRenderer = DescriptorRendererBuilder() + .setTextFormat(TextFormat.HTML) + .build() + + public val HTML_FOR_UNINFERRED_TYPE_PARAMS: DescriptorRenderer = DescriptorRendererBuilder() + .setUninferredTypeParameterAsName(true) + .setModifiers() + .setNameShortness(NameShortness.SHORT) + .setTextFormat(TextFormat.HTML) + .build() + + public val DEPRECATION: DescriptorRenderer = DescriptorRendererBuilder() + .setWithDefinedIn(false) + .setModifiers() + .setNameShortness(NameShortness.SHORT) + .setWithoutTypeParameters(false) + .setParameterNameRenderingPolicy(ParameterNameRenderingPolicy.NONE) + .setReceiverAfterName(false) + .setRenderCompanionObjectName(true) + .setRenderAccessors(true) + .setWithoutSuperTypes(true) + .setRenderDefaultValues(false) + .setStartFromName(true) + .build() + } +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererBuilder.java b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererBuilder.java deleted file mode 100644 index 70534f919ad..00000000000 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererBuilder.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2010-2015 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.renderer; - -import kotlin.KotlinPackage; -import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.types.JetType; - -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.Set; - -public class DescriptorRendererBuilder { - private NameShortness nameShortness = NameShortness.SOURCE_CODE_QUALIFIED; - private boolean withDefinedIn = true; - private Set modifiers = EnumSet.allOf(DescriptorRenderer.Modifier.class); - private boolean startFromName = false; - private boolean debugMode = false; - private boolean classWithPrimaryConstructor = false; - private boolean verbose = false; - private boolean unitReturnType = true; - private boolean normalizedVisibilities = false; - private boolean showInternalKeyword = true; - private boolean prettyFunctionTypes = true; - private boolean uninferredTypeParameterAsName = false; - private boolean includePropertyConstant = false; - private boolean withoutTypeParameters = false; - private boolean withoutSuperTypes = false; - private Function1 typeNormalizer = new Function1() { - @Override - public JetType invoke(JetType type) { - return type; - } - }; - private boolean renderDefaultValues = true; - private boolean flexibleTypesForCode = false; - private boolean secondaryConstructorsAsPrimary = true; - private DescriptorRenderer.OverrideRenderingPolicy overrideRenderingPolicy = DescriptorRenderer.OverrideRenderingPolicy.RENDER_OPEN; - private DescriptorRenderer.ValueParametersHandler valueParametersHandler = new DescriptorRenderer.DefaultValueParameterHandler(); - private DescriptorRenderer.TextFormat textFormat = DescriptorRenderer.TextFormat.PLAIN; - private DescriptorRenderer.ParameterNameRenderingPolicy parameterNameRenderingPolicy = DescriptorRenderer.ParameterNameRenderingPolicy.ALL; - private Collection excludedAnnotationClasses = Collections.emptyList(); - private boolean receiverAfterName = false; - private boolean renderCompanionObjectName = false; - private boolean renderAccessors = false; - - // See JvmAnnotationNames#ANNOTATIONS_COPIED_TO_TYPES - private Collection excludedTypeAnnotationClasses = KotlinPackage.setOf( - new FqName("org.jetbrains.annotations.ReadOnly"), - new FqName("org.jetbrains.annotations.Mutable"), - new FqName("org.jetbrains.annotations.NotNull"), - new FqName("org.jetbrains.annotations.Nullable") - ); - - public DescriptorRendererBuilder() { - } - - @NotNull - public DescriptorRendererBuilder setNameShortness(NameShortness shortness) { - this.nameShortness = shortness; - return this; - } - - @NotNull - public DescriptorRendererBuilder setWithDefinedIn(boolean withDefinedIn) { - this.withDefinedIn = withDefinedIn; - return this; - } - - @NotNull - public DescriptorRendererBuilder setModifiers(Set modifiers) { - this.modifiers = modifiers; - return this; - } - - @NotNull - public DescriptorRendererBuilder setModifiers(DescriptorRenderer.Modifier... modifiers) { - return setModifiers(KotlinPackage.setOf(modifiers)); - } - - @NotNull - public DescriptorRendererBuilder setStartFromName(boolean startFromName) { - this.startFromName = startFromName; - return this; - } - - @NotNull - public DescriptorRendererBuilder setDebugMode(boolean debugMode) { - this.debugMode = debugMode; - return this; - } - - @NotNull - public DescriptorRendererBuilder setClassWithPrimaryConstructor(boolean classWithPrimaryConstructor) { - this.classWithPrimaryConstructor = classWithPrimaryConstructor; - return this; - } - - @NotNull - public DescriptorRendererBuilder setVerbose(boolean verbose) { - this.verbose = verbose; - return this; - } - - @NotNull - public DescriptorRendererBuilder setUnitReturnType(boolean unitReturnType) { - this.unitReturnType = unitReturnType; - return this; - } - - @NotNull - public DescriptorRendererBuilder setNormalizedVisibilities(boolean normalizedVisibilities) { - this.normalizedVisibilities = normalizedVisibilities; - return this; - } - - @NotNull - public DescriptorRendererBuilder setShowInternalKeyword(boolean showInternalKeyword) { - this.showInternalKeyword = showInternalKeyword; - return this; - } - - @NotNull - public DescriptorRendererBuilder setOverrideRenderingPolicy(@NotNull DescriptorRenderer.OverrideRenderingPolicy overrideRenderingPolicy) { - this.overrideRenderingPolicy = overrideRenderingPolicy; - return this; - } - - @NotNull - public DescriptorRendererBuilder setValueParametersHandler(@NotNull DescriptorRenderer.ValueParametersHandler valueParametersHandler) { - this.valueParametersHandler = valueParametersHandler; - return this; - } - - @NotNull - public DescriptorRendererBuilder setTextFormat(@NotNull DescriptorRenderer.TextFormat textFormat) { - this.textFormat = textFormat; - return this; - } - - @NotNull - public DescriptorRendererBuilder setExcludedAnnotationClasses(@NotNull Collection excludedAnnotationClasses) { - this.excludedAnnotationClasses = excludedAnnotationClasses; - return this; - } - - @NotNull - public DescriptorRendererBuilder setExcludedTypeAnnotationClasses(@NotNull Collection excludedTypeAnnotationClasses) { - this.excludedTypeAnnotationClasses = excludedTypeAnnotationClasses; - return this; - } - - @NotNull - public DescriptorRendererBuilder setPrettyFunctionTypes(boolean prettyFunctionTypes) { - this.prettyFunctionTypes = prettyFunctionTypes; - return this; - } - - @NotNull - public DescriptorRendererBuilder setUninferredTypeParameterAsName(boolean uninferredTypeParameterAsName) { - this.uninferredTypeParameterAsName = uninferredTypeParameterAsName; - return this; - } - - @NotNull - public DescriptorRendererBuilder setIncludePropertyConstant(boolean includePropertyConstant) { - this.includePropertyConstant = includePropertyConstant; - return this; - } - - @NotNull - public DescriptorRendererBuilder setParameterNameRenderingPolicy(@NotNull DescriptorRenderer.ParameterNameRenderingPolicy parameterNameRenderingPolicy) { - this.parameterNameRenderingPolicy = parameterNameRenderingPolicy; - return this; - } - - @NotNull - public DescriptorRendererBuilder setWithoutTypeParameters(boolean withoutTypeParameters) { - this.withoutTypeParameters = withoutTypeParameters; - return this; - } - - @NotNull - public DescriptorRendererBuilder setReceiverAfterName(boolean receiverAfterName) { - this.receiverAfterName = receiverAfterName; - return this; - } - - @NotNull - public DescriptorRendererBuilder setRenderCompanionObjectName(boolean renderCompanionObjectName) { - this.renderCompanionObjectName = renderCompanionObjectName; - return this; - } - - @NotNull - public DescriptorRendererBuilder setWithoutSuperTypes(boolean withoutSuperTypes) { - this.withoutSuperTypes = withoutSuperTypes; - return this; - } - - @NotNull - public DescriptorRendererBuilder setRenderDefaultValues(boolean renderDefaultValues) { - this.renderDefaultValues = renderDefaultValues; - return this; - } - - @NotNull - public DescriptorRendererBuilder setTypeNormalizer(@NotNull Function1 typeNormalizer) { - this.typeNormalizer = typeNormalizer; - return this; - } - - @NotNull - public DescriptorRendererBuilder setFlexibleTypesForCode(boolean flexibleTypesForCode) { - this.flexibleTypesForCode = flexibleTypesForCode; - return this; - } - - @NotNull - public DescriptorRendererBuilder setSecondaryConstructorsAsPrimary(boolean secondaryConstructorsAsPrimary) { - this.secondaryConstructorsAsPrimary = secondaryConstructorsAsPrimary; - return this; - } - - @NotNull - public DescriptorRendererBuilder setRenderAccessors(boolean renderAccessors) { - this.renderAccessors = renderAccessors; - return this; - } - - @NotNull - public DescriptorRenderer build() { - return new DescriptorRendererImpl( - nameShortness, withDefinedIn, modifiers, startFromName, debugMode, classWithPrimaryConstructor, verbose, unitReturnType, - normalizedVisibilities, showInternalKeyword, prettyFunctionTypes, uninferredTypeParameterAsName, - overrideRenderingPolicy, valueParametersHandler, textFormat, excludedAnnotationClasses, excludedTypeAnnotationClasses, - includePropertyConstant, parameterNameRenderingPolicy, withoutTypeParameters, receiverAfterName, renderCompanionObjectName, - withoutSuperTypes, typeNormalizer, renderDefaultValues, flexibleTypesForCode, secondaryConstructorsAsPrimary, - renderAccessors - ); - } - -} diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererBuilder.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererBuilder.kt new file mode 100644 index 00000000000..df46cac6158 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererBuilder.kt @@ -0,0 +1,212 @@ +/* + * Copyright 2010-2015 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.renderer + +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.types.JetType +import java.util.Collections +import java.util.EnumSet + +public class DescriptorRendererBuilder { + private var nameShortness = NameShortness.SOURCE_CODE_QUALIFIED + private var withDefinedIn = true + private var modifiers: Set = EnumSet.allOf(javaClass()) + private var startFromName = false + private var debugMode = false + private var classWithPrimaryConstructor = false + private var verbose = false + private var unitReturnType = true + private var normalizedVisibilities = false + private var showInternalKeyword = true + private var prettyFunctionTypes = true + private var uninferredTypeParameterAsName = false + private var includePropertyConstant = false + private var withoutTypeParameters = false + private var withoutSuperTypes = false + private var typeNormalizer: Function1 = object : Function1 { + override fun invoke(type: JetType): JetType { + return type + } + } + private var renderDefaultValues = true + private var flexibleTypesForCode = false + private var secondaryConstructorsAsPrimary = true + private var overrideRenderingPolicy: DescriptorRenderer.OverrideRenderingPolicy = DescriptorRenderer.OverrideRenderingPolicy.RENDER_OPEN + private var valueParametersHandler: DescriptorRenderer.ValueParametersHandler = DescriptorRenderer.DefaultValueParameterHandler() + private var textFormat: DescriptorRenderer.TextFormat = DescriptorRenderer.TextFormat.PLAIN + private var parameterNameRenderingPolicy: DescriptorRenderer.ParameterNameRenderingPolicy = DescriptorRenderer.ParameterNameRenderingPolicy.ALL + private var excludedAnnotationClasses: Collection = emptyList() + private var receiverAfterName = false + private var renderCompanionObjectName = false + private var renderAccessors = false + + // See JvmAnnotationNames#ANNOTATIONS_COPIED_TO_TYPES + private var excludedTypeAnnotationClasses: Collection = setOf( + FqName("org.jetbrains.annotations.ReadOnly"), + FqName("org.jetbrains.annotations.Mutable"), + FqName("org.jetbrains.annotations.NotNull"), + FqName("org.jetbrains.annotations.Nullable")) + + public fun setNameShortness(shortness: NameShortness): DescriptorRendererBuilder { + this.nameShortness = shortness + return this + } + + public fun setWithDefinedIn(withDefinedIn: Boolean): DescriptorRendererBuilder { + this.withDefinedIn = withDefinedIn + return this + } + + public fun setModifiers(modifiers: Set): DescriptorRendererBuilder { + this.modifiers = modifiers + return this + } + + public fun setModifiers(vararg modifiers: DescriptorRenderer.Modifier): DescriptorRendererBuilder { + return setModifiers(setOf(*modifiers)) + } + + public fun setStartFromName(startFromName: Boolean): DescriptorRendererBuilder { + this.startFromName = startFromName + return this + } + + public fun setDebugMode(debugMode: Boolean): DescriptorRendererBuilder { + this.debugMode = debugMode + return this + } + + public fun setClassWithPrimaryConstructor(classWithPrimaryConstructor: Boolean): DescriptorRendererBuilder { + this.classWithPrimaryConstructor = classWithPrimaryConstructor + return this + } + + public fun setVerbose(verbose: Boolean): DescriptorRendererBuilder { + this.verbose = verbose + return this + } + + public fun setUnitReturnType(unitReturnType: Boolean): DescriptorRendererBuilder { + this.unitReturnType = unitReturnType + return this + } + + public fun setNormalizedVisibilities(normalizedVisibilities: Boolean): DescriptorRendererBuilder { + this.normalizedVisibilities = normalizedVisibilities + return this + } + + public fun setShowInternalKeyword(showInternalKeyword: Boolean): DescriptorRendererBuilder { + this.showInternalKeyword = showInternalKeyword + return this + } + + public fun setOverrideRenderingPolicy(overrideRenderingPolicy: DescriptorRenderer.OverrideRenderingPolicy): DescriptorRendererBuilder { + this.overrideRenderingPolicy = overrideRenderingPolicy + return this + } + + public fun setValueParametersHandler(valueParametersHandler: DescriptorRenderer.ValueParametersHandler): DescriptorRendererBuilder { + this.valueParametersHandler = valueParametersHandler + return this + } + + public fun setTextFormat(textFormat: DescriptorRenderer.TextFormat): DescriptorRendererBuilder { + this.textFormat = textFormat + return this + } + + public fun setExcludedAnnotationClasses(excludedAnnotationClasses: Collection): DescriptorRendererBuilder { + this.excludedAnnotationClasses = excludedAnnotationClasses + return this + } + + public fun setExcludedTypeAnnotationClasses(excludedTypeAnnotationClasses: Collection): DescriptorRendererBuilder { + this.excludedTypeAnnotationClasses = excludedTypeAnnotationClasses + return this + } + + public fun setPrettyFunctionTypes(prettyFunctionTypes: Boolean): DescriptorRendererBuilder { + this.prettyFunctionTypes = prettyFunctionTypes + return this + } + + public fun setUninferredTypeParameterAsName(uninferredTypeParameterAsName: Boolean): DescriptorRendererBuilder { + this.uninferredTypeParameterAsName = uninferredTypeParameterAsName + return this + } + + public fun setIncludePropertyConstant(includePropertyConstant: Boolean): DescriptorRendererBuilder { + this.includePropertyConstant = includePropertyConstant + return this + } + + public fun setParameterNameRenderingPolicy(parameterNameRenderingPolicy: DescriptorRenderer.ParameterNameRenderingPolicy): DescriptorRendererBuilder { + this.parameterNameRenderingPolicy = parameterNameRenderingPolicy + return this + } + + public fun setWithoutTypeParameters(withoutTypeParameters: Boolean): DescriptorRendererBuilder { + this.withoutTypeParameters = withoutTypeParameters + return this + } + + public fun setReceiverAfterName(receiverAfterName: Boolean): DescriptorRendererBuilder { + this.receiverAfterName = receiverAfterName + return this + } + + public fun setRenderCompanionObjectName(renderCompanionObjectName: Boolean): DescriptorRendererBuilder { + this.renderCompanionObjectName = renderCompanionObjectName + return this + } + + public fun setWithoutSuperTypes(withoutSuperTypes: Boolean): DescriptorRendererBuilder { + this.withoutSuperTypes = withoutSuperTypes + return this + } + + public fun setRenderDefaultValues(renderDefaultValues: Boolean): DescriptorRendererBuilder { + this.renderDefaultValues = renderDefaultValues + return this + } + + public fun setTypeNormalizer(typeNormalizer: Function1): DescriptorRendererBuilder { + this.typeNormalizer = typeNormalizer + return this + } + + public fun setFlexibleTypesForCode(flexibleTypesForCode: Boolean): DescriptorRendererBuilder { + this.flexibleTypesForCode = flexibleTypesForCode + return this + } + + public fun setSecondaryConstructorsAsPrimary(secondaryConstructorsAsPrimary: Boolean): DescriptorRendererBuilder { + this.secondaryConstructorsAsPrimary = secondaryConstructorsAsPrimary + return this + } + + public fun setRenderAccessors(renderAccessors: Boolean): DescriptorRendererBuilder { + this.renderAccessors = renderAccessors + return this + } + + public fun build(): DescriptorRenderer { + return DescriptorRendererImpl(nameShortness, withDefinedIn, modifiers, startFromName, debugMode, classWithPrimaryConstructor, verbose, unitReturnType, normalizedVisibilities, showInternalKeyword, prettyFunctionTypes, uninferredTypeParameterAsName, overrideRenderingPolicy, valueParametersHandler, textFormat, excludedAnnotationClasses, excludedTypeAnnotationClasses, includePropertyConstant, parameterNameRenderingPolicy, withoutTypeParameters, receiverAfterName, renderCompanionObjectName, withoutSuperTypes, typeNormalizer, renderDefaultValues, flexibleTypesForCode, secondaryConstructorsAsPrimary, renderAccessors) + } + +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.java b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.java deleted file mode 100644 index 27fdf8f7e47..00000000000 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.java +++ /dev/null @@ -1,1200 +0,0 @@ -/* - * Copyright 2010-2015 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.renderer; - -import kotlin.KotlinPackage; -import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.builtins.KotlinBuiltIns; -import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.descriptors.annotations.Annotated; -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.kotlin.descriptors.annotations.DefaultAnnotationArgumentVisitor; -import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.name.FqNameBase; -import org.jetbrains.kotlin.name.FqNameUnsafe; -import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.resolve.DescriptorUtils; -import org.jetbrains.kotlin.resolve.constants.*; -import org.jetbrains.kotlin.types.*; -import org.jetbrains.kotlin.types.ErrorUtils.UninferredParameterTypeConstructor; -import org.jetbrains.kotlin.types.error.MissingDependencyErrorClass; -import org.jetbrains.kotlin.utils.UtilsPackage; - -import java.util.*; - -import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject; -import static org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE; - -public class DescriptorRendererImpl implements DescriptorRenderer { - private final Function1 typeNormalizer; - private final NameShortness nameShortness; - private final boolean withDefinedIn; - private final Set modifiers; - private final boolean startFromName; - private final boolean debugMode; - private final boolean classWithPrimaryConstructor; - private final boolean verbose; - private final boolean unitReturnType; - private final boolean normalizedVisibilities; - private final boolean showInternalKeyword; - private final boolean prettyFunctionTypes; - private final boolean uninferredTypeParameterAsName; - private final ParameterNameRenderingPolicy parameterNameRenderingPolicy; - private final boolean withoutTypeParameters; - private final boolean renderCompanionObjectName; - private final boolean withoutSuperTypes; - private final boolean receiverAfterName; - private final boolean renderDefaultValues; - private final boolean flexibleTypesForCode; - private final OverrideRenderingPolicy overrideRenderingPolicy; - private final ValueParametersHandler handler; - private final TextFormat textFormat; - private final boolean includePropertyConstant; - private final boolean secondaryConstructorsAsPrimary; - private final Set excludedAnnotationClasses; - private final Set excludedTypeAnnotationClasses; - private final boolean renderAccessors; - - /* package */ DescriptorRendererImpl( - NameShortness nameShortness, - boolean withDefinedIn, - Set modifiers, - boolean startFromName, - boolean debugMode, - boolean classWithPrimaryConstructor, - boolean verbose, - boolean unitReturnType, - boolean normalizedVisibilities, - boolean showInternalKeyword, - boolean prettyFunctionTypes, - boolean uninferredTypeParameterAsName, - @NotNull OverrideRenderingPolicy overrideRenderingPolicy, - @NotNull ValueParametersHandler handler, - @NotNull TextFormat textFormat, - @NotNull Collection excludedAnnotationClasses, - @NotNull Collection excludedTypeAnnotationClasses, - boolean includePropertyConstant, - @NotNull ParameterNameRenderingPolicy parameterNameRenderingPolicy, - boolean withoutTypeParameters, - boolean receiverAfterName, - boolean renderCompanionObjectName, - boolean withoutSuperTypes, - @NotNull Function1 typeNormalizer, - boolean renderDefaultValues, - boolean flexibleTypesForCode, - boolean secondaryConstructorsAsPrimary, - boolean renderAccessors - ) { - this.nameShortness = nameShortness; - this.withDefinedIn = withDefinedIn; - this.modifiers = modifiers; - this.startFromName = startFromName; - this.handler = handler; - this.classWithPrimaryConstructor = classWithPrimaryConstructor; - this.verbose = verbose; - this.unitReturnType = unitReturnType; - this.normalizedVisibilities = normalizedVisibilities; - this.showInternalKeyword = showInternalKeyword; - this.overrideRenderingPolicy = overrideRenderingPolicy; - this.debugMode = debugMode; - this.textFormat = textFormat; - this.includePropertyConstant = includePropertyConstant; - this.secondaryConstructorsAsPrimary = secondaryConstructorsAsPrimary; - this.renderAccessors = renderAccessors; - this.excludedAnnotationClasses = new HashSet(excludedAnnotationClasses); - this.excludedTypeAnnotationClasses = new HashSet(excludedTypeAnnotationClasses); - this.prettyFunctionTypes = prettyFunctionTypes; - this.uninferredTypeParameterAsName = uninferredTypeParameterAsName; - this.parameterNameRenderingPolicy = parameterNameRenderingPolicy; - this.withoutTypeParameters = withoutTypeParameters; - this.receiverAfterName = receiverAfterName; - this.renderCompanionObjectName = renderCompanionObjectName; - this.withoutSuperTypes = withoutSuperTypes; - this.typeNormalizer = typeNormalizer; - this.renderDefaultValues = renderDefaultValues; - this.flexibleTypesForCode = flexibleTypesForCode; - } - - /* FORMATTING */ - @NotNull - private String renderKeyword(@NotNull String keyword) { - switch (textFormat) { - case PLAIN: - return keyword; - case HTML: - return "" + keyword + ""; - } - throw new IllegalStateException("Unexpected textFormat: " + textFormat); - } - - @NotNull - private String renderError(@NotNull String keyword) { - switch (textFormat) { - case PLAIN: - return keyword; - case HTML: - return "" + keyword + ""; - } - throw new IllegalStateException("Unexpected textFormat: " + textFormat); - } - - @NotNull - private String escape(@NotNull String string) { - switch (textFormat) { - case PLAIN: - return string; - case HTML: - return string.replaceAll("<", "<").replaceAll(">", ">"); - } - throw new IllegalStateException("Unexpected textFormat: " + textFormat); - } - - @NotNull - private String lt() { - return escape("<"); - } - - @NotNull - private String gt() { - return escape(">"); - } - - @NotNull - private String arrow() { - switch (textFormat) { - case PLAIN: - return escape("->"); - case HTML: - return "→"; - } - throw new IllegalStateException("Unexpected textFormat: " + textFormat); - } - - @NotNull - private String renderMessage(@NotNull String message) { - switch (textFormat) { - case PLAIN: - return message; - case HTML: - return "" + message + ""; - } - throw new IllegalStateException("Unexpected textFormat: " + textFormat); - } - - private static void renderSpaceIfNeeded(@NotNull StringBuilder builder) { - int length = builder.length(); - if (length == 0 || builder.charAt(length - 1) != ' ') { - builder.append(' '); - } - } - - /* NAMES RENDERING */ - @Override - @NotNull - public String renderName(@NotNull Name identifier) { - String asString = identifier.asString(); - return escape(nameShouldBeEscaped(identifier) ? '`' + asString + '`' : asString); - } - - private static boolean nameShouldBeEscaped(@NotNull Name identifier) { - if (identifier.isSpecial()) return false; - - String name = identifier.asString(); - - if (KeywordStringsGenerated.KEYWORDS.contains(name)) return true; - - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - if (!Character.isLetterOrDigit(c) && c != '_') return true; - } - - return false; - } - - private void renderName(@NotNull DeclarationDescriptor descriptor, @NotNull StringBuilder builder) { - builder.append(renderName(descriptor.getName())); - } - - private void renderCompanionObjectName(@NotNull DeclarationDescriptor descriptor, @NotNull StringBuilder builder) { - if (renderCompanionObjectName) { - if (startFromName) { - builder.append("companion object"); - } - renderSpaceIfNeeded(builder); - DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); - if (containingDeclaration != null) { - builder.append("of "); - builder.append(renderName(containingDeclaration.getName())); - } - } - if (verbose) { - if (!startFromName) renderSpaceIfNeeded(builder); - builder.append(renderName(descriptor.getName())); - } - } - - @Override - @NotNull - public String renderFqName(@NotNull FqNameBase fqName) { - return renderFqName(fqName.pathSegments()); - } - - - @NotNull - private String renderFqName(@NotNull List pathSegments) { - StringBuilder buf = new StringBuilder(); - for (Name element : pathSegments) { - if (buf.length() != 0) { - buf.append("."); - } - buf.append(renderName(element)); - } - return buf.toString(); - } - - @Override - @NotNull - public String renderClassifierName(@NotNull ClassifierDescriptor klass) { - if (klass instanceof MissingDependencyErrorClass) { - return ((MissingDependencyErrorClass) klass).getFullFqName().asString(); - } - if (ErrorUtils.isError(klass)) { - return klass.getTypeConstructor().toString(); - } - switch (nameShortness) { - case SHORT: { - List qualifiedNameElements = new ArrayList(); - - // for nested classes qualified name should be used - DeclarationDescriptor current = klass; - do { - qualifiedNameElements.add(current.getName()); - current = current.getContainingDeclaration(); - } - while (current instanceof ClassDescriptor); - - Collections.reverse(qualifiedNameElements); - return renderFqName(qualifiedNameElements); - } - - case FULLY_QUALIFIED: - return renderFqName(DescriptorUtils.getFqName(klass)); - - case SOURCE_CODE_QUALIFIED: - return RendererPackage.qualifiedNameForSourceCode(klass); - - default: - throw new IllegalArgumentException(); - } - } - - /* TYPES RENDERING */ - @NotNull - @Override - public String renderType(@NotNull JetType type) { - return renderNormalizedType(typeNormalizer.invoke(type)); - } - - @NotNull - private String renderNormalizedType(@NotNull JetType type) { - if (type instanceof LazyType && debugMode) { - return type.toString(); - } - if (TypesPackage.isDynamic(type)) { - return "dynamic"; - } - if (TypesPackage.isFlexible(type)) { - if (debugMode) { - return renderFlexibleTypeWithBothBounds(TypesPackage.flexibility(type).getLowerBound(), - TypesPackage.flexibility(type).getUpperBound()); - } - else if (flexibleTypesForCode) { - String prefix = nameShortness == NameShortness.SHORT ? "" : Flexibility.FLEXIBLE_TYPE_CLASSIFIER.getPackageFqName().asString() + "."; - return prefix + Flexibility.FLEXIBLE_TYPE_CLASSIFIER.getRelativeClassName() - + lt() - + renderNormalizedType(TypesPackage.flexibility(type).getLowerBound()) + ", " - + renderNormalizedType(TypesPackage.flexibility(type).getUpperBound()) - + gt(); - } - else { - return renderFlexibleType(type); - } - } - return renderInflexibleType(type); - } - - private String renderFlexibleTypeWithBothBounds(@NotNull JetType lower, @NotNull JetType upper) { - return "(" + renderNormalizedType(lower) + ".." + renderNormalizedType(upper) + ")"; - } - - private String renderInflexibleType(@NotNull JetType type) { - assert !TypesPackage.isFlexible(type) : "Flexible types not allowed here: " + renderNormalizedType(type); - - if (type == CANT_INFER_FUNCTION_PARAM_TYPE || TypeUtils.isDontCarePlaceholder(type)) { - return "???"; - } - if (ErrorUtils.isUninferredParameter(type)) { - if (uninferredTypeParameterAsName) { - return renderError(((UninferredParameterTypeConstructor) type.getConstructor()).getTypeParameterDescriptor().getName().toString()); - } - return "???"; - } - if (type.isError()) { - return renderDefaultType(type); - } - if (shouldRenderAsPrettyFunctionType(type)) { - return renderFunctionType(type); - } - return renderDefaultType(type); - } - - private boolean shouldRenderAsPrettyFunctionType(@NotNull JetType type) { - return KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(type) && prettyFunctionTypes; - } - - @NotNull - private String renderFlexibleType(@NotNull JetType type) { - JetType lower = TypesPackage.flexibility(type).getLowerBound(); - JetType upper = TypesPackage.flexibility(type).getUpperBound(); - - String lowerRendered = renderInflexibleType(lower); - String upperRendered = renderInflexibleType(upper); - - if (differsOnlyInNullability(lowerRendered, upperRendered)) { - if (upperRendered.startsWith("(")) { - // the case of complex type, e.g. (() -> Unit)? - return "(" + lowerRendered + ")!"; - } - return lowerRendered + "!"; - } - - String kotlinPrefix = nameShortness != NameShortness.SHORT ? "kotlin." : ""; - String mutablePrefix = "Mutable"; - // java.util.List -> (Mutable)List! - String simpleCollection = replacePrefixes( - lowerRendered, kotlinPrefix + mutablePrefix, upperRendered, kotlinPrefix, kotlinPrefix + "(" + mutablePrefix + ")" - ); - if (simpleCollection != null) return simpleCollection; - // java.util.Map.Entry -> (Mutable)Map.(Mutable)Entry! - String mutableEntry = replacePrefixes( - lowerRendered, kotlinPrefix + "MutableMap.MutableEntry", upperRendered, kotlinPrefix + "Map.Entry", - kotlinPrefix + "(Mutable)Map.(Mutable)Entry" - ); - if (mutableEntry != null) return mutableEntry; - - // Foo[] -> Array<(out) Foo!>! - String array = replacePrefixes( - lowerRendered, kotlinPrefix + escape("Array<"), upperRendered, kotlinPrefix + escape("Array typeArguments) { - if (typeArguments.isEmpty()) return ""; - StringBuilder sb = new StringBuilder(); - sb.append(lt()); - appendTypeProjections(typeArguments, sb); - sb.append(gt()); - return sb.toString(); - } - - @NotNull - private String renderDefaultType(@NotNull JetType type) { - StringBuilder sb = new StringBuilder(); - - renderAnnotations(type, sb, /* needBrackets = */ true); - - if (type.isError()) { - sb.append(type.getConstructor().toString()); // Debug name of an error type is more informative - } - else { - sb.append(renderTypeName(type.getConstructor())); - } - sb.append(renderTypeArguments(type.getArguments())); - if (type.isMarkedNullable()) { - sb.append("?"); - } - return sb.toString(); - } - - @NotNull - private String renderTypeName(@NotNull TypeConstructor typeConstructor) { - ClassifierDescriptor cd = typeConstructor.getDeclarationDescriptor(); - if (cd instanceof TypeParameterDescriptor) { - return renderName(cd.getName()); - } - else if (cd instanceof ClassDescriptor) { - return renderClassifierName(cd); - } - else { - assert cd == null: "Unexpected classifier: " + cd.getClass(); - return typeConstructor.toString(); - } - } - - private void appendTypeProjections(@NotNull List typeProjections, @NotNull StringBuilder builder) { - for (Iterator iterator = typeProjections.iterator(); iterator.hasNext(); ) { - TypeProjection typeProjection = iterator.next(); - if (typeProjection.isStarProjection()) { - builder.append("*"); - } - else { - if (typeProjection.getProjectionKind() != Variance.INVARIANT) { - builder.append(typeProjection.getProjectionKind()).append(" "); - } - builder.append(renderType(typeProjection.getType())); - } - if (iterator.hasNext()) { - builder.append(", "); - } - } - } - - @NotNull - private String renderFunctionType(@NotNull JetType type) { - StringBuilder sb = new StringBuilder(); - - JetType receiverType = KotlinBuiltIns.getReceiverType(type); - if (receiverType != null) { - sb.append(renderNormalizedType(receiverType)); - sb.append("."); - } - - sb.append("("); - appendTypeProjections(KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(type), sb); - sb.append(") ").append(arrow()).append(" "); - sb.append(renderNormalizedType(KotlinBuiltIns.getReturnTypeFromFunctionType(type))); - - if (type.isMarkedNullable()) { - return "(" + sb + ")?"; - } - return sb.toString(); - } - - - /* METHODS FOR ALL KINDS OF DESCRIPTORS */ - private void appendDefinedIn(@NotNull DeclarationDescriptor descriptor, @NotNull StringBuilder builder) { - if (descriptor instanceof PackageFragmentDescriptor || descriptor instanceof PackageViewDescriptor) { - return; - } - if (descriptor instanceof ModuleDescriptor) { - builder.append(" is a module"); - return; - } - builder.append(" ").append(renderMessage("defined in")).append(" "); - - DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); - if (containingDeclaration != null) { - FqNameUnsafe fqName = DescriptorUtils.getFqName(containingDeclaration); - builder.append(FqName.ROOT.equalsTo(fqName) ? "root package" : renderFqName(fqName)); - } - } - - private void renderAnnotations(@NotNull Annotated annotated, @NotNull StringBuilder builder) { - renderAnnotations(annotated, builder, false); - } - - private void renderAnnotations(@NotNull Annotated annotated, @NotNull StringBuilder builder, boolean needBrackets) { - if (!modifiers.contains(Modifier.ANNOTATIONS)) return; - - Set excluded = annotated instanceof JetType ? excludedTypeAnnotationClasses : excludedAnnotationClasses; - - StringBuilder annotationsBuilder = new StringBuilder(); - for (AnnotationDescriptor annotation : annotated.getAnnotations()) { - ClassDescriptor annotationClass = (ClassDescriptor) annotation.getType().getConstructor().getDeclarationDescriptor(); - assert annotationClass != null; - - if (!excluded.contains(DescriptorUtils.getFqNameSafe(annotationClass))) { - annotationsBuilder.append(renderAnnotation(annotation)).append(" "); - } - } - - if (!needBrackets) { - builder.append(annotationsBuilder); - } - else if (annotationsBuilder.length() > 0) { - // remove last whitespace - annotationsBuilder.setLength(annotationsBuilder.length() - 1); - - builder.append("@["); - builder.append(annotationsBuilder); - builder.append("] "); - } - } - - @Override - @NotNull - public String renderAnnotation(@NotNull AnnotationDescriptor annotation) { - StringBuilder sb = new StringBuilder(); - sb.append(renderType(annotation.getType())); - if (verbose) { - sb.append("(").append(UtilsPackage.join(renderAndSortAnnotationArguments(annotation), ", ")).append(")"); - } - return sb.toString(); - } - - @NotNull - private List renderAndSortAnnotationArguments(@NotNull AnnotationDescriptor descriptor) { - Set>> valueArguments = descriptor.getAllValueArguments().entrySet(); - List resultList = new ArrayList(valueArguments.size()); - for (Map.Entry> entry : valueArguments) { - CompileTimeConstant value = entry.getValue(); - String typeSuffix = ": " + renderType(value.getType(KotlinBuiltIns.getInstance())); - resultList.add(entry.getKey().getName().asString() + " = " + renderConstant(value) + typeSuffix); - } - Collections.sort(resultList); - return resultList; - } - - @NotNull - private String renderConstant(@NotNull CompileTimeConstant value) { - return value.accept( - new DefaultAnnotationArgumentVisitor() { - @Override - public String visitValue(@NotNull CompileTimeConstant value, Void data) { - return value.toString(); - } - - @Override - public String visitArrayValue(ArrayValue value, Void data) { - List renderedElements = - KotlinPackage.map(value.getValue(), - new Function1, String>() { - @Override - public String invoke(CompileTimeConstant constant) { - return renderConstant(constant); - } - }); - return "{" + UtilsPackage.join(renderedElements, ", ") + "}"; - } - - @Override - public String visitAnnotationValue(AnnotationValue value, Void data) { - return renderAnnotation(value.getValue()); - } - - @Override - public String visitJavaClassValue(JavaClassValue value, Void data) { - return "javaClass<" + renderType(value.getValue()) + ">()"; - } - - @Override - public String visitKClassValue(KClassValue value, Void data) { - return renderType(value.getValue()) + "::class"; - } - }, - null - ); - } - - private void renderVisibility(@NotNull Visibility visibility, @NotNull StringBuilder builder) { - if (!modifiers.contains(Modifier.VISIBILITY)) return; - if (normalizedVisibilities) { - visibility = visibility.normalize(); - } - if (!showInternalKeyword && visibility == Visibilities.INTERNAL) return; - builder.append(renderKeyword(visibility.toString())).append(" "); - } - - private void renderModality(@NotNull Modality modality, @NotNull StringBuilder builder) { - if (!modifiers.contains(Modifier.MODALITY)) return; - String keyword = modality.name().toLowerCase(); - builder.append(renderKeyword(keyword)).append(" "); - } - - private void renderInner(boolean isInner, @NotNull StringBuilder builder) { - if (!modifiers.contains(Modifier.INNER)) return; - if (isInner) { - builder.append(renderKeyword("inner")).append(" "); - } - } - - private void renderModalityForCallable(@NotNull CallableMemberDescriptor callable, @NotNull StringBuilder builder) { - if (!DescriptorUtils.isTopLevelDeclaration(callable) || callable.getModality() != Modality.FINAL) { - if (overridesSomething(callable) - && overrideRenderingPolicy == OverrideRenderingPolicy.RENDER_OVERRIDE - && callable.getModality() == Modality.OPEN) { - return; - } - renderModality(callable.getModality(), builder); - } - } - - private static boolean overridesSomething(CallableMemberDescriptor callable) { - return !callable.getOverriddenDescriptors().isEmpty(); - } - - private void renderOverride(@NotNull CallableMemberDescriptor callableMember, @NotNull StringBuilder builder) { - if (!modifiers.contains(Modifier.OVERRIDE)) return; - if (overridesSomething(callableMember)) { - if (overrideRenderingPolicy != OverrideRenderingPolicy.RENDER_OPEN) { - builder.append("override "); - if (verbose) { - builder.append("/*").append(callableMember.getOverriddenDescriptors().size()).append("*/ "); - } - } - } - } - - private void renderMemberKind(CallableMemberDescriptor callableMember, StringBuilder builder) { - if (!modifiers.contains(Modifier.MEMBER_KIND)) return; - if (verbose && callableMember.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { - builder.append("/*").append(callableMember.getKind().name().toLowerCase()).append("*/ "); - } - } - - @NotNull - @Override - public String render(@NotNull DeclarationDescriptor declarationDescriptor) { - StringBuilder stringBuilder = new StringBuilder(); - declarationDescriptor.accept(new RenderDeclarationDescriptorVisitor(), stringBuilder); - - if (withDefinedIn) { - appendDefinedIn(declarationDescriptor, stringBuilder); - } - return stringBuilder.toString(); - } - - - /* TYPE PARAMETERS */ - private void renderTypeParameter(@NotNull TypeParameterDescriptor typeParameter, @NotNull StringBuilder builder, boolean topLevel) { - if (topLevel) { - builder.append(lt()); - } - - if (verbose) { - builder.append("/*").append(typeParameter.getIndex()).append("*/ "); - } - - if (typeParameter.isReified()) { - builder.append(renderKeyword("reified")).append(" "); - } - String variance = typeParameter.getVariance().getLabel(); - if (!variance.isEmpty()) { - builder.append(renderKeyword(variance)).append(" "); - } - renderName(typeParameter, builder); - int upperBoundsCount = typeParameter.getUpperBounds().size(); - if ((upperBoundsCount > 1 && !topLevel) || upperBoundsCount == 1) { - JetType upperBound = typeParameter.getUpperBounds().iterator().next(); - if (!KotlinBuiltIns.getInstance().getDefaultBound().equals(upperBound)) { - builder.append(" : ").append(renderType(upperBound)); - } - } - else if (topLevel) { - boolean first = true; - for (JetType upperBound : typeParameter.getUpperBounds()) { - if (upperBound.equals(KotlinBuiltIns.getInstance().getDefaultBound())) { - continue; - } - if (first) { - builder.append(" : "); - } - else { - builder.append(" & "); - } - builder.append(renderType(upperBound)); - first = false; - } - } - else { - // rendered with "where" - } - - if (topLevel) { - builder.append(gt()); - } - } - - private void renderTypeParameters( - @NotNull List typeParameters, - @NotNull StringBuilder builder, - boolean withSpace - ) { - if (withoutTypeParameters) return; - - if (!typeParameters.isEmpty()) { - builder.append(lt()); - for (Iterator iterator = typeParameters.iterator(); iterator.hasNext(); ) { - TypeParameterDescriptor typeParameterDescriptor = iterator.next(); - renderTypeParameter(typeParameterDescriptor, builder, false); - if (iterator.hasNext()) { - builder.append(", "); - } - } - builder.append(gt()); - if (withSpace) { - builder.append(" "); - } - } - } - - /* FUNCTIONS */ - private void renderFunction(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) { - if (!startFromName) { - renderAnnotations(function, builder); - renderVisibility(function.getVisibility(), builder); - renderModalityForCallable(function, builder); - renderOverride(function, builder); - renderMemberKind(function, builder); - - builder.append(renderKeyword("fun")).append(" "); - renderTypeParameters(function.getTypeParameters(), builder, true); - renderReceiver(function, builder); - } - - renderName(function, builder); - - renderValueParameters(function, builder); - - renderReceiverAfterName(function, builder); - - JetType returnType = function.getReturnType(); - if (unitReturnType || (returnType == null || !KotlinBuiltIns.isUnit(returnType))) { - builder.append(": ").append(returnType == null ? "[NULL]" : escape(renderType(returnType))); - } - - renderWhereSuffix(function.getTypeParameters(), builder); - } - - private void renderReceiverAfterName(CallableDescriptor callableDescriptor, StringBuilder builder) { - if (!receiverAfterName) return; - - ReceiverParameterDescriptor receiver = callableDescriptor.getExtensionReceiverParameter(); - if (receiver != null) { - builder.append(" on ").append(escape(renderType(receiver.getType()))); - } - } - - private void renderReceiver(CallableDescriptor callableDescriptor, StringBuilder builder) { - ReceiverParameterDescriptor receiver = callableDescriptor.getExtensionReceiverParameter(); - if (receiver != null) { - JetType type = receiver.getType(); - String result = escape(renderType(type)); - if (shouldRenderAsPrettyFunctionType(type) && !TypeUtils.isNullableType(type)) { - result = "(" + result + ")"; - } - builder.append(result).append("."); - } - } - - private void renderConstructor(@NotNull ConstructorDescriptor constructor, @NotNull StringBuilder builder) { - renderAnnotations(constructor, builder); - renderVisibility(constructor.getVisibility(), builder); - renderMemberKind(constructor, builder); - - builder.append(renderKeyword("constructor")); - if (secondaryConstructorsAsPrimary) { - ClassDescriptor classDescriptor = constructor.getContainingDeclaration(); - builder.append(" "); - renderName(classDescriptor, builder); - renderTypeParameters(classDescriptor.getTypeConstructor().getParameters(), builder, false); - } - - renderValueParameters(constructor, builder); - - if (secondaryConstructorsAsPrimary) { - renderWhereSuffix(constructor.getTypeParameters(), builder); - } - } - - private void renderWhereSuffix(@NotNull List typeParameters, @NotNull StringBuilder builder) { - if (withoutTypeParameters) return; - - List upperBoundStrings = new ArrayList(0); - - for (TypeParameterDescriptor typeParameter : typeParameters) { - if (typeParameter.getUpperBounds().size() > 1) { - boolean first = true; - for (JetType upperBound : typeParameter.getUpperBounds()) { - // first parameter is rendered by renderTypeParameter: - if (!first) { - upperBoundStrings.add(renderName(typeParameter.getName()) + " : " + escape(renderType(upperBound))); - } - first = false; - } - } - } - if (!upperBoundStrings.isEmpty()) { - builder.append(" ").append(renderKeyword("where")).append(" "); - builder.append(UtilsPackage.join(upperBoundStrings, ", ")); - } - } - - @NotNull - @Override - public String renderFunctionParameters(@NotNull FunctionDescriptor functionDescriptor) { - StringBuilder stringBuilder = new StringBuilder(); - renderValueParameters(functionDescriptor, stringBuilder); - return stringBuilder.toString(); - } - - private void renderValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) { - boolean includeNames = shouldRenderParameterNames(function); - handler.appendBeforeValueParameters(function, builder); - for (ValueParameterDescriptor parameter : function.getValueParameters()) { - handler.appendBeforeValueParameter(parameter, builder); - renderValueParameter(parameter, includeNames, builder, false); - handler.appendAfterValueParameter(parameter, builder); - } - handler.appendAfterValueParameters(function, builder); - } - - private boolean shouldRenderParameterNames(@NotNull FunctionDescriptor function) { - switch (parameterNameRenderingPolicy) { - case ALL: - return true; - case ONLY_NON_SYNTHESIZED: - return !function.hasSynthesizedParameterNames(); - case NONE: - return false; - default: - throw new UnsupportedOperationException(parameterNameRenderingPolicy.toString()); - } - } - - /* VARIABLES */ - private void renderValueParameter( - @NotNull ValueParameterDescriptor valueParameter, - boolean includeName, - @NotNull StringBuilder builder, - boolean topLevel - ) { - if (topLevel) { - builder.append(renderKeyword("value-parameter")).append(" "); - } - - if (verbose) { - builder.append("/*").append(valueParameter.getIndex()).append("*/ "); - } - - renderAnnotations(valueParameter, builder); - renderVariable(valueParameter, includeName, builder, topLevel); - boolean withDefaultValue = renderDefaultValues && (debugMode ? valueParameter.declaresDefaultValue() : valueParameter.hasDefaultValue()); - if (withDefaultValue) { - builder.append(" = ..."); - } - } - - private void renderValVarPrefix(@NotNull VariableDescriptor variable, @NotNull StringBuilder builder) { - builder.append(renderKeyword(variable.isVar() ? "var" : "val")).append(" "); - } - - private void renderVariable(@NotNull VariableDescriptor variable, boolean includeName, @NotNull StringBuilder builder, boolean topLevel) { - JetType realType = variable.getType(); - - JetType varargElementType = variable instanceof ValueParameterDescriptor - ? ((ValueParameterDescriptor) variable).getVarargElementType() - : null; - JetType typeToRender = varargElementType != null ? varargElementType : realType; - - if (varargElementType != null) { - builder.append(renderKeyword("vararg")).append(" "); - } - if (topLevel && !startFromName) { - renderValVarPrefix(variable, builder); - } - - if (includeName) { - renderName(variable, builder); - builder.append(": "); - } - - builder.append(escape(renderType(typeToRender))); - - renderInitializer(variable, builder); - - if (verbose && varargElementType != null) { - builder.append(" /*").append(escape(renderType(realType))).append("*/"); - } - } - - private void renderProperty(@NotNull PropertyDescriptor property, @NotNull StringBuilder builder) { - if (!startFromName) { - renderAnnotations(property, builder); - renderVisibility(property.getVisibility(), builder); - renderModalityForCallable(property, builder); - renderOverride(property, builder); - renderMemberKind(property, builder); - renderValVarPrefix(property, builder); - renderTypeParameters(property.getTypeParameters(), builder, true); - renderReceiver(property, builder); - } - - renderName(property, builder); - builder.append(": ").append(escape(renderType(property.getType()))); - - renderReceiverAfterName(property, builder); - - renderInitializer(property, builder); - - renderWhereSuffix(property.getTypeParameters(), builder); - } - - private void renderInitializer(@NotNull VariableDescriptor variable, @NotNull StringBuilder builder) { - if (includePropertyConstant) { - CompileTimeConstant initializer = variable.getCompileTimeInitializer(); - if (initializer != null) { - builder.append(" = ").append(escape(renderConstant(initializer))); - } - } - } - - /* CLASSES */ - private void renderClass(@NotNull ClassDescriptor klass, @NotNull StringBuilder builder) { - if (!startFromName) { - renderAnnotations(klass, builder); - renderVisibility(klass.getVisibility(), builder); - if (!(klass.getKind() == ClassKind.INTERFACE && klass.getModality() == Modality.ABSTRACT - || klass.getKind().isSingleton() && klass.getModality() == Modality.FINAL)) { - renderModality(klass.getModality(), builder); - } - renderInner(klass.isInner(), builder); - renderClassKindPrefix(klass, builder); - } - - if (!isCompanionObject(klass)) { - if (!startFromName) renderSpaceIfNeeded(builder); - renderName(klass, builder); - } - else { - renderCompanionObjectName(klass, builder); - } - - List typeParameters = klass.getTypeConstructor().getParameters(); - renderTypeParameters(typeParameters, builder, false); - - if (!klass.getKind().isSingleton() && classWithPrimaryConstructor) { - ConstructorDescriptor primaryConstructor = klass.getUnsubstitutedPrimaryConstructor(); - if (primaryConstructor != null) { - builder.append(" "); - renderAnnotations(primaryConstructor, builder, true); - renderVisibility(primaryConstructor.getVisibility(), builder); - builder.append("constructor"); - renderValueParameters(primaryConstructor, builder); - } - } - - renderSuperTypes(klass, builder); - renderWhereSuffix(typeParameters, builder); - } - - private void renderSuperTypes(@NotNull ClassDescriptor klass, @NotNull StringBuilder builder) { - if (withoutSuperTypes) return; - - if (!klass.equals(KotlinBuiltIns.getInstance().getNothing())) { - Collection supertypes = klass.getTypeConstructor().getSupertypes(); - - if (supertypes.isEmpty() || - supertypes.size() == 1 && KotlinBuiltIns.isAnyOrNullableAny(supertypes.iterator().next())) { - } - else { - renderSpaceIfNeeded(builder); - builder.append(": "); - for (Iterator iterator = supertypes.iterator(); iterator.hasNext(); ) { - JetType supertype = iterator.next(); - builder.append(renderType(supertype)); - if (iterator.hasNext()) { - builder.append(", "); - } - } - } - } - } - - private void renderClassKindPrefix(ClassDescriptor klass, StringBuilder builder) { - builder.append(renderKeyword(getClassKindPrefix(klass))); - } - - @NotNull - public static String getClassKindPrefix(@NotNull ClassDescriptor klass) { - if (klass.isCompanionObject()) { - return "companion object"; - } - switch (klass.getKind()) { - case CLASS: - return "class"; - case INTERFACE: - return "interface"; - case ENUM_CLASS: - return "enum class"; - case OBJECT: - return "object"; - case ANNOTATION_CLASS: - return "annotation class"; - case ENUM_ENTRY: - return "enum entry"; - default: - throw new IllegalStateException("unknown class kind: " + klass.getKind()); - } - } - - - /* OTHER */ - private void renderModuleOrScript(@NotNull DeclarationDescriptor moduleOrScript, @NotNull StringBuilder builder) { - renderName(moduleOrScript, builder); - } - - private void renderPackageView(@NotNull PackageViewDescriptor packageView, @NotNull StringBuilder builder) { - builder.append(renderKeyword("package")).append(" "); - builder.append(renderFqName(packageView.getFqName())); - if (debugMode) { - builder.append(" in context of "); - renderName(packageView.getModule(), builder); - } - } - - private void renderPackageFragment(@NotNull PackageFragmentDescriptor fragment, @NotNull StringBuilder builder) { - builder.append(renderKeyword("package-fragment")).append(" "); - builder.append(renderFqName(fragment.getFqName())); - if (debugMode) { - builder.append(" in "); - renderName(fragment.getContainingDeclaration(), builder); - } - } - - - /* STUPID DISPATCH-ONLY VISITOR */ - private class RenderDeclarationDescriptorVisitor extends DeclarationDescriptorVisitorEmptyBodies { - @Override - public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) { - renderValueParameter(descriptor, true, builder, true); - return null; - } - - @Override - public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) { - renderVariable(descriptor, true, builder, true); - return null; - } - - @Override - public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) { - renderProperty(descriptor, builder); - return null; - } - - @Override - public Void visitPropertyGetterDescriptor(PropertyGetterDescriptor descriptor, StringBuilder builder) { - if (renderAccessors) { - builder.append("getter for "); - renderProperty(descriptor.getCorrespondingProperty(), builder); - return null; - } else { - return super.visitPropertyGetterDescriptor(descriptor, builder); - } - - } - - @Override - public Void visitPropertySetterDescriptor(PropertySetterDescriptor descriptor, StringBuilder builder) { - if (renderAccessors) { - builder.append("setter for "); - renderProperty(descriptor.getCorrespondingProperty(), builder); - return null; - } else { - return super.visitPropertySetterDescriptor(descriptor, builder); - } - } - - @Override - public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) { - renderFunction(descriptor, builder); - return null; - } - - @Override - public Void visitReceiverParameterDescriptor(ReceiverParameterDescriptor descriptor, StringBuilder data) { - throw new UnsupportedOperationException("Don't render receiver parameters"); - } - - @Override - public Void visitConstructorDescriptor(ConstructorDescriptor constructorDescriptor, StringBuilder builder) { - renderConstructor(constructorDescriptor, builder); - return null; - } - - @Override - public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) { - renderTypeParameter(descriptor, builder, true); - return null; - } - - @Override - public Void visitPackageFragmentDescriptor( - PackageFragmentDescriptor descriptor, StringBuilder builder - ) { - renderPackageFragment(descriptor, builder); - return null; - } - - @Override - public Void visitPackageViewDescriptor( - PackageViewDescriptor descriptor, StringBuilder builder - ) { - renderPackageView(descriptor, builder); - return null; - } - - @Override - public Void visitModuleDeclaration(ModuleDescriptor descriptor, StringBuilder builder) { - renderModuleOrScript(descriptor, builder); - return null; - } - - @Override - public Void visitScriptDescriptor(ScriptDescriptor scriptDescriptor, StringBuilder builder) { - renderModuleOrScript(scriptDescriptor, builder); - return null; - } - - @Override - public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) { - renderClass(descriptor, builder); - return null; - } - } -} diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt new file mode 100644 index 00000000000..99aaba221f7 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt @@ -0,0 +1,1018 @@ +/* + * Copyright 2010-2015 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.renderer + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotated +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.descriptors.annotations.DefaultAnnotationArgumentVisitor +import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.FqNameBase +import org.jetbrains.kotlin.name.FqNameUnsafe +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.constants.* +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.ErrorUtils.UninferredParameterTypeConstructor +import org.jetbrains.kotlin.types.error.MissingDependencyErrorClass +import org.jetbrains.kotlin.utils.* + +import java.util.* + +import org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject +import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE + +public class DescriptorRendererImpl internal constructor( + private val nameShortness: NameShortness, + private val withDefinedIn: Boolean, + private val modifiers: Set, + private val startFromName: Boolean, + private val debugMode: Boolean, + private val classWithPrimaryConstructor: Boolean, + private val verbose: Boolean, + private val unitReturnType: Boolean, + private val normalizedVisibilities: Boolean, + private val showInternalKeyword: Boolean, + private val prettyFunctionTypes: Boolean, + private val uninferredTypeParameterAsName: Boolean, + private val overrideRenderingPolicy: DescriptorRenderer.OverrideRenderingPolicy, + private val handler: DescriptorRenderer.ValueParametersHandler, + private val textFormat: DescriptorRenderer.TextFormat, + excludedAnnotationClasses: Collection, + excludedTypeAnnotationClasses: Collection, + private val includePropertyConstant: Boolean, + private val parameterNameRenderingPolicy: DescriptorRenderer.ParameterNameRenderingPolicy, + private val withoutTypeParameters: Boolean, + private val receiverAfterName: Boolean, + private val renderCompanionObjectName: Boolean, + private val withoutSuperTypes: Boolean, + private val typeNormalizer: Function1, + private val renderDefaultValues: Boolean, + private val flexibleTypesForCode: Boolean, + private val secondaryConstructorsAsPrimary: Boolean, + private val renderAccessors: Boolean +) : DescriptorRenderer { + private val excludedAnnotationClasses: Set + private val excludedTypeAnnotationClasses: Set + + init { + this.excludedAnnotationClasses = HashSet(excludedAnnotationClasses) + this.excludedTypeAnnotationClasses = HashSet(excludedTypeAnnotationClasses) + } + + /* FORMATTING */ + private fun renderKeyword(keyword: String): String { + when (textFormat) { + DescriptorRenderer.TextFormat.PLAIN -> return keyword + DescriptorRenderer.TextFormat.HTML -> return "" + keyword + "" + } + } + + private fun renderError(keyword: String): String { + when (textFormat) { + DescriptorRenderer.TextFormat.PLAIN -> return keyword + DescriptorRenderer.TextFormat.HTML -> return "" + keyword + "" + } + } + + private fun escape(string: String): String { + when (textFormat) { + DescriptorRenderer.TextFormat.PLAIN -> return string + DescriptorRenderer.TextFormat.HTML -> return string.replace("<", "<").replace(">", ">") + } + } + + private fun lt(): String { + return escape("<") + } + + private fun gt(): String { + return escape(">") + } + + private fun arrow(): String { + when (textFormat) { + DescriptorRenderer.TextFormat.PLAIN -> return escape("->") + DescriptorRenderer.TextFormat.HTML -> return "→" + } + } + + private fun renderMessage(message: String): String { + when (textFormat) { + DescriptorRenderer.TextFormat.PLAIN -> return message + DescriptorRenderer.TextFormat.HTML -> return "" + message + "" + } + } + + /* NAMES RENDERING */ + override fun renderName(name: Name): String { + val asString = name.asString() + return escape(if (nameShouldBeEscaped(name)) '`' + asString + '`' else asString) + } + + private fun renderName(descriptor: DeclarationDescriptor, builder: StringBuilder) { + builder.append(renderName(descriptor.getName())) + } + + private fun renderCompanionObjectName(descriptor: DeclarationDescriptor, builder: StringBuilder) { + if (renderCompanionObjectName) { + if (startFromName) { + builder.append("companion object") + } + renderSpaceIfNeeded(builder) + val containingDeclaration = descriptor.getContainingDeclaration() + if (containingDeclaration != null) { + builder.append("of ") + builder.append(renderName(containingDeclaration.getName())) + } + } + if (verbose) { + if (!startFromName) renderSpaceIfNeeded(builder) + builder.append(renderName(descriptor.getName())) + } + } + + override fun renderFqName(fqName: FqNameBase): String { + return renderFqName(fqName.pathSegments()) + } + + private fun renderFqName(pathSegments: List): String { + val buf = StringBuilder() + for (element in pathSegments) { + if (buf.length() != 0) { + buf.append(".") + } + buf.append(renderName(element)) + } + return buf.toString() + } + + override fun renderClassifierName(klass: ClassifierDescriptor): String { + if (klass is MissingDependencyErrorClass) { + return klass.fullFqName.asString() + } + if (ErrorUtils.isError(klass)) { + return klass.getTypeConstructor().toString() + } + when (nameShortness) { + NameShortness.SHORT -> { + val qualifiedNameElements = ArrayList() + + // for nested classes qualified name should be used + var current: DeclarationDescriptor? = klass + do { + qualifiedNameElements.add(current!!.getName()) + current = current.getContainingDeclaration() + } + while (current is ClassDescriptor) + + return renderFqName(qualifiedNameElements.reverse()) + } + + NameShortness.FULLY_QUALIFIED -> return renderFqName(DescriptorUtils.getFqName(klass)) + + NameShortness.SOURCE_CODE_QUALIFIED -> return qualifiedNameForSourceCode(klass) + + else -> throw IllegalArgumentException() + } + } + + /* TYPES RENDERING */ + override fun renderType(type: JetType): String { + return renderNormalizedType(typeNormalizer.invoke(type)) + } + + private fun renderNormalizedType(type: JetType): String { + if (type is LazyType && debugMode) { + return type.toString() + } + if (type.isDynamic()) { + return "dynamic" + } + if (type.isFlexible()) { + if (debugMode) { + return renderFlexibleTypeWithBothBounds(type.flexibility().lowerBound, type.flexibility().upperBound) + } + else if (flexibleTypesForCode) { + val prefix = if (nameShortness == NameShortness.SHORT) "" else Flexibility.FLEXIBLE_TYPE_CLASSIFIER.getPackageFqName().asString() + "." + return prefix + Flexibility.FLEXIBLE_TYPE_CLASSIFIER.getRelativeClassName() + lt() + renderNormalizedType(type.flexibility().lowerBound) + ", " + renderNormalizedType(type.flexibility().upperBound) + gt() + } + else { + return renderFlexibleType(type) + } + } + return renderInflexibleType(type) + } + + private fun renderFlexibleTypeWithBothBounds(lower: JetType, upper: JetType): String { + return "(" + renderNormalizedType(lower) + ".." + renderNormalizedType(upper) + ")" + } + + private fun renderInflexibleType(type: JetType): String { + assert(!type.isFlexible()) { "Flexible types not allowed here: " + renderNormalizedType(type) } + + if (type == CANT_INFER_FUNCTION_PARAM_TYPE || TypeUtils.isDontCarePlaceholder(type)) { + return "???" + } + if (ErrorUtils.isUninferredParameter(type)) { + if (uninferredTypeParameterAsName) { + return renderError((type.getConstructor() as UninferredParameterTypeConstructor).getTypeParameterDescriptor().getName().toString()) + } + return "???" + } + if (type.isError()) { + return renderDefaultType(type) + } + if (shouldRenderAsPrettyFunctionType(type)) { + return renderFunctionType(type) + } + return renderDefaultType(type) + } + + private fun shouldRenderAsPrettyFunctionType(type: JetType): Boolean { + return KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(type) && prettyFunctionTypes + } + + private fun renderFlexibleType(type: JetType): String { + val lower = type.flexibility().lowerBound + val upper = type.flexibility().upperBound + + val lowerRendered = renderInflexibleType(lower) + val upperRendered = renderInflexibleType(upper) + + if (differsOnlyInNullability(lowerRendered, upperRendered)) { + if (upperRendered.startsWith("(")) { + // the case of complex type, e.g. (() -> Unit)? + return "(" + lowerRendered + ")!" + } + return lowerRendered + "!" + } + + val kotlinPrefix = if (nameShortness != NameShortness.SHORT) "kotlin." else "" + val mutablePrefix = "Mutable" + // java.util.List -> (Mutable)List! + val simpleCollection = replacePrefixes(lowerRendered, kotlinPrefix + mutablePrefix, upperRendered, kotlinPrefix, kotlinPrefix + "(" + mutablePrefix + ")") + if (simpleCollection != null) return simpleCollection + // java.util.Map.Entry -> (Mutable)Map.(Mutable)Entry! + val mutableEntry = replacePrefixes(lowerRendered, kotlinPrefix + "MutableMap.MutableEntry", upperRendered, kotlinPrefix + "Map.Entry", kotlinPrefix + "(Mutable)Map.(Mutable)Entry") + if (mutableEntry != null) return mutableEntry + + // Foo[] -> Array<(out) Foo!>! + val array = replacePrefixes(lowerRendered, kotlinPrefix + escape("Array<"), upperRendered, kotlinPrefix + escape("Array): String { + if (typeArguments.isEmpty()) return "" + val sb = StringBuilder() + sb.append(lt()) + appendTypeProjections(typeArguments, sb) + sb.append(gt()) + return sb.toString() + } + + private fun renderDefaultType(type: JetType): String { + val sb = StringBuilder() + + renderAnnotations(type, sb, /* needBrackets = */ true) + + if (type.isError()) { + sb.append(type.getConstructor().toString()) // Debug name of an error type is more informative + } + else { + sb.append(renderTypeName(type.getConstructor())) + } + sb.append(renderTypeArguments(type.getArguments())) + if (type.isMarkedNullable()) { + sb.append("?") + } + return sb.toString() + } + + private fun renderTypeName(typeConstructor: TypeConstructor): String { + val cd = typeConstructor.getDeclarationDescriptor() + if (cd is TypeParameterDescriptor) { + return renderName(cd.getName()) + } + else if (cd is ClassDescriptor) { + return renderClassifierName(cd) + } + else { + assert(cd == null) { "Unexpected classifier: " + cd!!.javaClass } + return typeConstructor.toString() + } + } + + private fun appendTypeProjections(typeProjections: List, builder: StringBuilder) { + val iterator = typeProjections.iterator() + while (iterator.hasNext()) { + val typeProjection = iterator.next() + if (typeProjection.isStarProjection()) { + builder.append("*") + } + else { + if (typeProjection.getProjectionKind() != Variance.INVARIANT) { + builder.append(typeProjection.getProjectionKind()).append(" ") + } + builder.append(renderType(typeProjection.getType())) + } + if (iterator.hasNext()) { + builder.append(", ") + } + } + } + + private fun renderFunctionType(type: JetType): String { + val sb = StringBuilder() + + val receiverType = KotlinBuiltIns.getReceiverType(type) + if (receiverType != null) { + sb.append(renderNormalizedType(receiverType)) + sb.append(".") + } + + sb.append("(") + appendTypeProjections(KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(type), sb) + sb.append(") ").append(arrow()).append(" ") + sb.append(renderNormalizedType(KotlinBuiltIns.getReturnTypeFromFunctionType(type))) + + if (type.isMarkedNullable()) { + return "(" + sb + ")?" + } + return sb.toString() + } + + + /* METHODS FOR ALL KINDS OF DESCRIPTORS */ + private fun appendDefinedIn(descriptor: DeclarationDescriptor, builder: StringBuilder) { + if (descriptor is PackageFragmentDescriptor || descriptor is PackageViewDescriptor) { + return + } + if (descriptor is ModuleDescriptor) { + builder.append(" is a module") + return + } + builder.append(" ").append(renderMessage("defined in")).append(" ") + + val containingDeclaration = descriptor.getContainingDeclaration() + if (containingDeclaration != null) { + val fqName = DescriptorUtils.getFqName(containingDeclaration) + builder.append(if (FqName.ROOT.equalsTo(fqName)) "root package" else renderFqName(fqName)) + } + } + + private fun renderAnnotations(annotated: Annotated, builder: StringBuilder, needBrackets: Boolean = false) { + if (!modifiers.contains(DescriptorRenderer.Modifier.ANNOTATIONS)) return + + val excluded = if (annotated is JetType) excludedTypeAnnotationClasses else excludedAnnotationClasses + + val annotationsBuilder = StringBuilder() + for (annotation in annotated.getAnnotations()) { + val annotationClass = annotation.getType().getConstructor().getDeclarationDescriptor() as ClassDescriptor + + if (!excluded.contains(DescriptorUtils.getFqNameSafe(annotationClass))) { + annotationsBuilder.append(renderAnnotation(annotation)).append(" ") + } + } + + if (!needBrackets) { + builder.append(annotationsBuilder) + } + else if (annotationsBuilder.length() > 0) { + // remove last whitespace + annotationsBuilder.setLength(annotationsBuilder.length() - 1) + + builder.append("@[") + builder.append(annotationsBuilder) + builder.append("] ") + } + } + + override fun renderAnnotation(annotation: AnnotationDescriptor): String { + val sb = StringBuilder() + sb.append(renderType(annotation.getType())) + if (verbose) { + renderAndSortAnnotationArguments(annotation).joinTo(sb, ", ", "(", ")") + } + return sb.toString() + } + + private fun renderAndSortAnnotationArguments(descriptor: AnnotationDescriptor): List { + val valueArguments = descriptor.getAllValueArguments().entrySet() + val resultList = ArrayList(valueArguments.size()) + for (entry in valueArguments) { + val value = entry.getValue() + val typeSuffix = ": " + renderType(value.getType(KotlinBuiltIns.getInstance())) + resultList.add(entry.getKey().getName().asString() + " = " + renderConstant(value) + typeSuffix) + } + Collections.sort(resultList) + return resultList + } + + private fun renderConstant(value: CompileTimeConstant<*>): String { + return value.accept(object : DefaultAnnotationArgumentVisitor() { + override fun visitValue(value: CompileTimeConstant<*>, data: Unit): String { + return value.toString() + } + + override fun visitArrayValue(value: ArrayValue, data: Unit): String { + return value.getValue().map { renderConstant(it) }.joinToString(", ", "{", "}") + } + + override fun visitAnnotationValue(value: AnnotationValue, data: Unit): String { + return renderAnnotation(value.getValue()) + } + + override fun visitJavaClassValue(value: JavaClassValue, data: Unit): String { + return "javaClass<" + renderType(value.getValue()) + ">()" + } + + override fun visitKClassValue(value: KClassValue, data: Unit): String { + return renderType(value.getValue()) + "::class" + } + }, Unit) + } + + private fun renderVisibility(visibility: Visibility, builder: StringBuilder) { + var visibility = visibility + if (!modifiers.contains(DescriptorRenderer.Modifier.VISIBILITY)) return + if (normalizedVisibilities) { + visibility = visibility.normalize() + } + if (!showInternalKeyword && visibility == Visibilities.INTERNAL) return + builder.append(renderKeyword(visibility.toString())).append(" ") + } + + private fun renderModality(modality: Modality, builder: StringBuilder) { + if (!modifiers.contains(DescriptorRenderer.Modifier.MODALITY)) return + val keyword = modality.name().toLowerCase() + builder.append(renderKeyword(keyword)).append(" ") + } + + private fun renderInner(isInner: Boolean, builder: StringBuilder) { + if (!modifiers.contains(DescriptorRenderer.Modifier.INNER)) return + if (isInner) { + builder.append(renderKeyword("inner")).append(" ") + } + } + + private fun renderModalityForCallable(callable: CallableMemberDescriptor, builder: StringBuilder) { + if (!DescriptorUtils.isTopLevelDeclaration(callable) || callable.getModality() != Modality.FINAL) { + if (overridesSomething(callable) && overrideRenderingPolicy == DescriptorRenderer.OverrideRenderingPolicy.RENDER_OVERRIDE && callable.getModality() == Modality.OPEN) { + return + } + renderModality(callable.getModality(), builder) + } + } + + private fun renderOverride(callableMember: CallableMemberDescriptor, builder: StringBuilder) { + if (!modifiers.contains(DescriptorRenderer.Modifier.OVERRIDE)) return + if (overridesSomething(callableMember)) { + if (overrideRenderingPolicy != DescriptorRenderer.OverrideRenderingPolicy.RENDER_OPEN) { + builder.append("override ") + if (verbose) { + builder.append("/*").append(callableMember.getOverriddenDescriptors().size()).append("*/ ") + } + } + } + } + + private fun renderMemberKind(callableMember: CallableMemberDescriptor, builder: StringBuilder) { + if (!modifiers.contains(DescriptorRenderer.Modifier.MEMBER_KIND)) return + if (verbose && callableMember.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { + builder.append("/*").append(callableMember.getKind().name().toLowerCase()).append("*/ ") + } + } + + override fun render(declarationDescriptor: DeclarationDescriptor): String { + val stringBuilder = StringBuilder() + declarationDescriptor.accept(RenderDeclarationDescriptorVisitor(), stringBuilder) + + if (withDefinedIn) { + appendDefinedIn(declarationDescriptor, stringBuilder) + } + return stringBuilder.toString() + } + + + /* TYPE PARAMETERS */ + private fun renderTypeParameter(typeParameter: TypeParameterDescriptor, builder: StringBuilder, topLevel: Boolean) { + if (topLevel) { + builder.append(lt()) + } + + if (verbose) { + builder.append("/*").append(typeParameter.getIndex()).append("*/ ") + } + + if (typeParameter.isReified()) { + builder.append(renderKeyword("reified")).append(" ") + } + val variance = typeParameter.getVariance().label + if (!variance.isEmpty()) { + builder.append(renderKeyword(variance)).append(" ") + } + renderName(typeParameter, builder) + val upperBoundsCount = typeParameter.getUpperBounds().size() + if ((upperBoundsCount > 1 && !topLevel) || upperBoundsCount == 1) { + val upperBound = typeParameter.getUpperBounds().iterator().next() + if (KotlinBuiltIns.getInstance().getDefaultBound() != upperBound) { + builder.append(" : ").append(renderType(upperBound)) + } + } + else if (topLevel) { + var first = true + for (upperBound in typeParameter.getUpperBounds()) { + if (upperBound == KotlinBuiltIns.getInstance().getDefaultBound()) { + continue + } + if (first) { + builder.append(" : ") + } + else { + builder.append(" & ") + } + builder.append(renderType(upperBound)) + first = false + } + } + else { + // rendered with "where" + } + + if (topLevel) { + builder.append(gt()) + } + } + + private fun renderTypeParameters(typeParameters: List, builder: StringBuilder, withSpace: Boolean) { + if (withoutTypeParameters) return + + if (!typeParameters.isEmpty()) { + builder.append(lt()) + val iterator = typeParameters.iterator() + while (iterator.hasNext()) { + val typeParameterDescriptor = iterator.next() + renderTypeParameter(typeParameterDescriptor, builder, false) + if (iterator.hasNext()) { + builder.append(", ") + } + } + builder.append(gt()) + if (withSpace) { + builder.append(" ") + } + } + } + + /* FUNCTIONS */ + private fun renderFunction(function: FunctionDescriptor, builder: StringBuilder) { + if (!startFromName) { + renderAnnotations(function, builder) + renderVisibility(function.getVisibility(), builder) + renderModalityForCallable(function, builder) + renderOverride(function, builder) + renderMemberKind(function, builder) + + builder.append(renderKeyword("fun")).append(" ") + renderTypeParameters(function.getTypeParameters(), builder, true) + renderReceiver(function, builder) + } + + renderName(function, builder) + + renderValueParameters(function, builder) + + renderReceiverAfterName(function, builder) + + val returnType = function.getReturnType() + if (unitReturnType || (returnType == null || !KotlinBuiltIns.isUnit(returnType))) { + builder.append(": ").append(if (returnType == null) "[NULL]" else escape(renderType(returnType))) + } + + renderWhereSuffix(function.getTypeParameters(), builder) + } + + private fun renderReceiverAfterName(callableDescriptor: CallableDescriptor, builder: StringBuilder) { + if (!receiverAfterName) return + + val receiver = callableDescriptor.getExtensionReceiverParameter() + if (receiver != null) { + builder.append(" on ").append(escape(renderType(receiver.getType()))) + } + } + + private fun renderReceiver(callableDescriptor: CallableDescriptor, builder: StringBuilder) { + val receiver = callableDescriptor.getExtensionReceiverParameter() + if (receiver != null) { + val type = receiver.getType() + var result = escape(renderType(type)) + if (shouldRenderAsPrettyFunctionType(type) && !TypeUtils.isNullableType(type)) { + result = "(" + result + ")" + } + builder.append(result).append(".") + } + } + + private fun renderConstructor(constructor: ConstructorDescriptor, builder: StringBuilder) { + renderAnnotations(constructor, builder) + renderVisibility(constructor.getVisibility(), builder) + renderMemberKind(constructor, builder) + + builder.append(renderKeyword("constructor")) + if (secondaryConstructorsAsPrimary) { + val classDescriptor = constructor.getContainingDeclaration() + builder.append(" ") + renderName(classDescriptor, builder) + renderTypeParameters(classDescriptor.getTypeConstructor().getParameters(), builder, false) + } + + renderValueParameters(constructor, builder) + + if (secondaryConstructorsAsPrimary) { + renderWhereSuffix(constructor.getTypeParameters(), builder) + } + } + + private fun renderWhereSuffix(typeParameters: List, builder: StringBuilder) { + if (withoutTypeParameters) return + + val upperBoundStrings = ArrayList(0) + + for (typeParameter in typeParameters) { + if (typeParameter.getUpperBounds().size() > 1) { + var first = true + for (upperBound in typeParameter.getUpperBounds()) { + // first parameter is rendered by renderTypeParameter: + if (!first) { + upperBoundStrings.add(renderName(typeParameter.getName()) + " : " + escape(renderType(upperBound))) + } + first = false + } + } + } + if (!upperBoundStrings.isEmpty()) { + builder.append(" ").append(renderKeyword("where")).append(" ") + upperBoundStrings.joinTo(builder, ", ") + } + } + + override fun renderFunctionParameters(functionDescriptor: FunctionDescriptor): String { + val stringBuilder = StringBuilder() + renderValueParameters(functionDescriptor, stringBuilder) + return stringBuilder.toString() + } + + private fun renderValueParameters(function: FunctionDescriptor, builder: StringBuilder) { + val includeNames = shouldRenderParameterNames(function) + handler.appendBeforeValueParameters(function, builder) + for (parameter in function.getValueParameters()) { + handler.appendBeforeValueParameter(parameter, builder) + renderValueParameter(parameter, includeNames, builder, false) + handler.appendAfterValueParameter(parameter, builder) + } + handler.appendAfterValueParameters(function, builder) + } + + private fun shouldRenderParameterNames(function: FunctionDescriptor): Boolean { + when (parameterNameRenderingPolicy) { + DescriptorRenderer.ParameterNameRenderingPolicy.ALL -> return true + DescriptorRenderer.ParameterNameRenderingPolicy.ONLY_NON_SYNTHESIZED -> return !function.hasSynthesizedParameterNames() + DescriptorRenderer.ParameterNameRenderingPolicy.NONE -> return false + else -> throw UnsupportedOperationException(parameterNameRenderingPolicy.toString()) + } + } + + /* VARIABLES */ + private fun renderValueParameter(valueParameter: ValueParameterDescriptor, includeName: Boolean, builder: StringBuilder, topLevel: Boolean) { + if (topLevel) { + builder.append(renderKeyword("value-parameter")).append(" ") + } + + if (verbose) { + builder.append("/*").append(valueParameter.getIndex()).append("*/ ") + } + + renderAnnotations(valueParameter, builder) + renderVariable(valueParameter, includeName, builder, topLevel) + val withDefaultValue = renderDefaultValues && (if (debugMode) valueParameter.declaresDefaultValue() else valueParameter.hasDefaultValue()) + if (withDefaultValue) { + builder.append(" = ...") + } + } + + private fun renderValVarPrefix(variable: VariableDescriptor, builder: StringBuilder) { + builder.append(renderKeyword(if (variable.isVar()) "var" else "val")).append(" ") + } + + private fun renderVariable(variable: VariableDescriptor, includeName: Boolean, builder: StringBuilder, topLevel: Boolean) { + val realType = variable.getType() + + val varargElementType = if (variable is ValueParameterDescriptor) + variable.getVarargElementType() + else + null + val typeToRender = varargElementType ?: realType + + if (varargElementType != null) { + builder.append(renderKeyword("vararg")).append(" ") + } + if (topLevel && !startFromName) { + renderValVarPrefix(variable, builder) + } + + if (includeName) { + renderName(variable, builder) + builder.append(": ") + } + + builder.append(escape(renderType(typeToRender))) + + renderInitializer(variable, builder) + + if (verbose && varargElementType != null) { + builder.append(" /*").append(escape(renderType(realType))).append("*/") + } + } + + private fun renderProperty(property: PropertyDescriptor, builder: StringBuilder) { + if (!startFromName) { + renderAnnotations(property, builder) + renderVisibility(property.getVisibility(), builder) + renderModalityForCallable(property, builder) + renderOverride(property, builder) + renderMemberKind(property, builder) + renderValVarPrefix(property, builder) + renderTypeParameters(property.getTypeParameters(), builder, true) + renderReceiver(property, builder) + } + + renderName(property, builder) + builder.append(": ").append(escape(renderType(property.getType()))) + + renderReceiverAfterName(property, builder) + + renderInitializer(property, builder) + + renderWhereSuffix(property.getTypeParameters(), builder) + } + + private fun renderInitializer(variable: VariableDescriptor, builder: StringBuilder) { + if (includePropertyConstant) { + val initializer = variable.getCompileTimeInitializer() + if (initializer != null) { + builder.append(" = ").append(escape(renderConstant(initializer))) + } + } + } + + /* CLASSES */ + private fun renderClass(klass: ClassDescriptor, builder: StringBuilder) { + if (!startFromName) { + renderAnnotations(klass, builder) + renderVisibility(klass.getVisibility(), builder) + if (!(klass.getKind() == ClassKind.INTERFACE && klass.getModality() == Modality.ABSTRACT || klass.getKind().isSingleton() && klass.getModality() == Modality.FINAL)) { + renderModality(klass.getModality(), builder) + } + renderInner(klass.isInner(), builder) + renderClassKindPrefix(klass, builder) + } + + if (!isCompanionObject(klass)) { + if (!startFromName) renderSpaceIfNeeded(builder) + renderName(klass, builder) + } + else { + renderCompanionObjectName(klass, builder) + } + + val typeParameters = klass.getTypeConstructor().getParameters() + renderTypeParameters(typeParameters, builder, false) + + if (!klass.getKind().isSingleton() && classWithPrimaryConstructor) { + val primaryConstructor = klass.getUnsubstitutedPrimaryConstructor() + if (primaryConstructor != null) { + builder.append(" ") + renderAnnotations(primaryConstructor, builder, true) + renderVisibility(primaryConstructor.getVisibility(), builder) + builder.append("constructor") + renderValueParameters(primaryConstructor, builder) + } + } + + renderSuperTypes(klass, builder) + renderWhereSuffix(typeParameters, builder) + } + + private fun renderSuperTypes(klass: ClassDescriptor, builder: StringBuilder) { + if (withoutSuperTypes) return + + if (klass != KotlinBuiltIns.getInstance().getNothing()) { + val supertypes = klass.getTypeConstructor().getSupertypes() + + if (supertypes.isEmpty() || supertypes.size() == 1 && KotlinBuiltIns.isAnyOrNullableAny(supertypes.iterator().next())) { + } + else { + renderSpaceIfNeeded(builder) + builder.append(": ") + val iterator = supertypes.iterator() + while (iterator.hasNext()) { + val supertype = iterator.next() + builder.append(renderType(supertype)) + if (iterator.hasNext()) { + builder.append(", ") + } + } + } + } + } + + private fun renderClassKindPrefix(klass: ClassDescriptor, builder: StringBuilder) { + builder.append(renderKeyword(getClassKindPrefix(klass))) + } + + + /* OTHER */ + private fun renderModuleOrScript(moduleOrScript: DeclarationDescriptor, builder: StringBuilder) { + renderName(moduleOrScript, builder) + } + + private fun renderPackageView(packageView: PackageViewDescriptor, builder: StringBuilder) { + builder.append(renderKeyword("package")).append(" ") + builder.append(renderFqName(packageView.getFqName())) + if (debugMode) { + builder.append(" in context of ") + renderName(packageView.getModule(), builder) + } + } + + private fun renderPackageFragment(fragment: PackageFragmentDescriptor, builder: StringBuilder) { + builder.append(renderKeyword("package-fragment")).append(" ") + builder.append(renderFqName(fragment.fqName)) + if (debugMode) { + builder.append(" in ") + renderName(fragment.getContainingDeclaration(), builder) + } + } + + + /* STUPID DISPATCH-ONLY VISITOR */ + private inner class RenderDeclarationDescriptorVisitor : DeclarationDescriptorVisitorEmptyBodies() { + override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, builder: StringBuilder): Void? { + renderValueParameter(descriptor, true, builder, true) + return null + } + + override fun visitVariableDescriptor(descriptor: VariableDescriptor, builder: StringBuilder): Void? { + renderVariable(descriptor, true, builder, true) + return null + } + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, builder: StringBuilder): Void? { + renderProperty(descriptor, builder) + return null + } + + override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, builder: StringBuilder): Void? { + if (renderAccessors) { + builder.append("getter for ") + renderProperty(descriptor.getCorrespondingProperty(), builder) + return null + } + else { + return super.visitPropertyGetterDescriptor(descriptor, builder) + } + + } + + override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, builder: StringBuilder): Void? { + if (renderAccessors) { + builder.append("setter for ") + renderProperty(descriptor.getCorrespondingProperty(), builder) + return null + } + else { + return super.visitPropertySetterDescriptor(descriptor, builder) + } + } + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, builder: StringBuilder): Void? { + renderFunction(descriptor, builder) + return null + } + + override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: StringBuilder): Void { + throw UnsupportedOperationException("Don't render receiver parameters") + } + + override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, builder: StringBuilder): Void? { + renderConstructor(constructorDescriptor, builder) + return null + } + + override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, builder: StringBuilder): Void? { + renderTypeParameter(descriptor, builder, true) + return null + } + + override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, builder: StringBuilder): Void? { + renderPackageFragment(descriptor, builder) + return null + } + + override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, builder: StringBuilder): Void? { + renderPackageView(descriptor, builder) + return null + } + + override fun visitModuleDeclaration(descriptor: ModuleDescriptor, builder: StringBuilder): Void? { + renderModuleOrScript(descriptor, builder) + return null + } + + override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, builder: StringBuilder): Void? { + renderModuleOrScript(scriptDescriptor, builder) + return null + } + + override fun visitClassDescriptor(descriptor: ClassDescriptor, builder: StringBuilder): Void? { + renderClass(descriptor, builder) + return null + } + } + + companion object { + + private fun renderSpaceIfNeeded(builder: StringBuilder) { + val length = builder.length() + if (length == 0 || builder.charAt(length - 1) != ' ') { + builder.append(' ') + } + } + + private fun nameShouldBeEscaped(identifier: Name): Boolean { + if (identifier.isSpecial()) return false + + val name = identifier.asString() + + if (KeywordStringsGenerated.KEYWORDS.contains(name)) return true + + for (i in 0..name.length() - 1) { + val c = name.charAt(i) + if (!Character.isLetterOrDigit(c) && c != '_') return true + } + + return false + } + + private fun replacePrefixes(lowerRendered: String, lowerPrefix: String, upperRendered: String, upperPrefix: String, foldedPrefix: String): String? { + if (lowerRendered.startsWith(lowerPrefix) && upperRendered.startsWith(upperPrefix)) { + val lowerWithoutPrefix = lowerRendered.substring(lowerPrefix.length()) + if (differsOnlyInNullability(lowerWithoutPrefix, upperRendered.substring(upperPrefix.length()))) { + return foldedPrefix + lowerWithoutPrefix + "!" + } + } + return null + } + + private fun differsOnlyInNullability(lower: String, upper: String): Boolean { + return lower == upper.replace("?", "") || upper.endsWith("?") && ((lower + "?") == upper) || (("(" + lower + ")?") == upper) + } + + private fun overridesSomething(callable: CallableMemberDescriptor): Boolean { + return !callable.getOverriddenDescriptors().isEmpty() + } + + public fun getClassKindPrefix(klass: ClassDescriptor): String { + if (klass.isCompanionObject()) { + return "companion object" + } + when (klass.getKind()) { + ClassKind.CLASS -> return "class" + ClassKind.INTERFACE -> return "interface" + ClassKind.ENUM_CLASS -> return "enum class" + ClassKind.OBJECT -> return "object" + ClassKind.ANNOTATION_CLASS -> return "annotation class" + ClassKind.ENUM_ENTRY -> return "enum entry" + else -> throw IllegalStateException("unknown class kind: " + klass.getKind()) + } + } + } +}