001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.jet.renderer; 018 019 import com.google.common.collect.Lists; 020 import com.google.common.collect.Sets; 021 import com.intellij.openapi.util.text.StringUtil; 022 import org.jetbrains.annotations.NotNull; 023 import org.jetbrains.jet.lang.descriptors.*; 024 import org.jetbrains.jet.lang.descriptors.annotations.Annotated; 025 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 026 import org.jetbrains.jet.lang.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies; 027 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 028 import org.jetbrains.jet.lang.resolve.name.FqName; 029 import org.jetbrains.jet.lang.resolve.name.FqNameBase; 030 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; 031 import org.jetbrains.jet.lang.resolve.name.Name; 032 import org.jetbrains.jet.lang.types.*; 033 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 034 035 import java.util.*; 036 037 import static org.jetbrains.jet.lang.types.TypeUtils.CANT_INFER_LAMBDA_PARAM_TYPE; 038 import static org.jetbrains.jet.lang.types.TypeUtils.CANT_INFER_TYPE_PARAMETER; 039 040 public class DescriptorRendererImpl implements DescriptorRenderer { 041 private final boolean shortNames; 042 private final boolean withDefinedIn; 043 private final Set<DescriptorRenderer.Modifier> modifiers; 044 private final boolean startFromName; 045 private final boolean debugMode; 046 private final boolean classWithPrimaryConstructor; 047 private final boolean verbose; 048 private final boolean unitReturnType; 049 private final boolean normalizedVisibilities; 050 private final boolean showInternalKeyword; 051 @NotNull 052 private final OverrideRenderingPolicy overrideRenderingPolicy; 053 @NotNull 054 private final ValueParametersHandler handler; 055 @NotNull 056 private final TextFormat textFormat; 057 @NotNull 058 private final Set<FqName> excludedAnnotationClasses; 059 060 /* package */ DescriptorRendererImpl( 061 boolean shortNames, 062 boolean withDefinedIn, 063 Set<DescriptorRenderer.Modifier> modifiers, 064 boolean startFromName, 065 boolean debugMode, 066 boolean classWithPrimaryConstructor, 067 boolean verbose, 068 boolean unitReturnType, 069 boolean normalizedVisibilities, 070 boolean showInternalKeyword, 071 @NotNull OverrideRenderingPolicy overrideRenderingPolicy, 072 @NotNull ValueParametersHandler handler, 073 @NotNull TextFormat textFormat, 074 @NotNull Collection<FqName> excludedAnnotationClasses 075 ) { 076 this.shortNames = shortNames; 077 this.withDefinedIn = withDefinedIn; 078 this.modifiers = modifiers; 079 this.startFromName = startFromName; 080 this.handler = handler; 081 this.classWithPrimaryConstructor = classWithPrimaryConstructor; 082 this.verbose = verbose; 083 this.unitReturnType = unitReturnType; 084 this.normalizedVisibilities = normalizedVisibilities; 085 this.showInternalKeyword = showInternalKeyword; 086 this.overrideRenderingPolicy = overrideRenderingPolicy; 087 this.debugMode = debugMode; 088 this.textFormat = textFormat; 089 this.excludedAnnotationClasses = Sets.newHashSet(excludedAnnotationClasses); 090 } 091 092 093 /* FORMATTING */ 094 @NotNull 095 private String renderKeyword(@NotNull String keyword) { 096 switch (textFormat) { 097 case PLAIN: 098 return keyword; 099 case HTML: 100 return "<b>" + keyword + "</b>"; 101 } 102 throw new IllegalStateException("Unexpected textFormat: " + textFormat); 103 } 104 105 @NotNull 106 private String escape(@NotNull String string) { 107 switch (textFormat) { 108 case PLAIN: 109 return string; 110 case HTML: 111 return string.replaceAll("<", "<").replaceAll(">", ">"); 112 } 113 throw new IllegalStateException("Unexpected textFormat: " + textFormat); 114 } 115 116 @NotNull 117 private String lt() { 118 return escape("<"); 119 } 120 121 @NotNull 122 private String arrow() { 123 switch (textFormat) { 124 case PLAIN: 125 return escape("->"); 126 case HTML: 127 return "→"; 128 } 129 throw new IllegalStateException("Unexpected textFormat: " + textFormat); 130 } 131 132 @NotNull 133 private String renderMessage(@NotNull String message) { 134 switch (textFormat) { 135 case PLAIN: 136 return message; 137 case HTML: 138 return "<i>" + message + "</i>"; 139 } 140 throw new IllegalStateException("Unexpected textFormat: " + textFormat); 141 } 142 143 144 /* NAMES RENDERING */ 145 @NotNull 146 private String renderName(@NotNull Name identifier) { 147 String asString = identifier.toString(); 148 return escape(KeywordStringsGenerated.KEYWORDS.contains(asString) ? '`' + asString + '`' : asString); 149 } 150 151 private void renderName(@NotNull DeclarationDescriptor descriptor, @NotNull StringBuilder builder) { 152 builder.append(renderName(descriptor.getName())); 153 } 154 155 @NotNull 156 private String renderFqName(@NotNull FqNameBase fqName) { 157 return renderFqName(fqName.pathSegments()); 158 } 159 160 161 @NotNull 162 private String renderFqName(@NotNull List<Name> pathSegments) { 163 StringBuilder buf = new StringBuilder(); 164 for (Name element : pathSegments) { 165 if (buf.length() != 0) { 166 buf.append("."); 167 } 168 buf.append(renderName(element)); 169 } 170 return buf.toString(); 171 } 172 173 @NotNull 174 private String renderClassName(@NotNull ClassDescriptor klass) { 175 if (ErrorUtils.isError(klass)) { 176 return klass.getTypeConstructor().toString(); 177 } 178 if (shortNames) { 179 List<Name> qualifiedNameElements = Lists.newArrayList(); 180 181 // for nested classes qualified name should be used 182 DeclarationDescriptor current = klass; 183 do { 184 if (((ClassDescriptor) current).getKind() != ClassKind.CLASS_OBJECT) { 185 qualifiedNameElements.add(current.getName()); 186 } 187 current = current.getContainingDeclaration(); 188 } 189 while (current instanceof ClassDescriptor); 190 191 Collections.reverse(qualifiedNameElements); 192 return renderFqName(qualifiedNameElements); 193 } 194 return renderFqName(DescriptorUtils.getFqName(klass)); 195 } 196 197 /* TYPES RENDERING */ 198 @NotNull 199 @Override 200 public String renderType(@NotNull JetType type) { 201 return escape(renderTypeWithoutEscape(type)); 202 } 203 204 private String renderTypeWithoutEscape(@NotNull JetType type) { 205 if (type == CANT_INFER_LAMBDA_PARAM_TYPE || type == CANT_INFER_TYPE_PARAMETER) { 206 return "???"; 207 } 208 if (type.isError()) { 209 return type.toString(); 210 } 211 if (KotlinBuiltIns.getInstance().isExactFunctionOrExtensionFunctionType(type)) { 212 return renderFunctionType(type); 213 } 214 return renderDefaultType(type); 215 } 216 217 @NotNull 218 private String renderDefaultType(@NotNull JetType type) { 219 StringBuilder sb = new StringBuilder(); 220 221 sb.append(renderTypeName(type.getConstructor())); 222 if (!type.getArguments().isEmpty()) { 223 sb.append("<"); 224 appendTypeProjections(type.getArguments(), sb); 225 sb.append(">"); 226 } 227 if (type.isNullable()) { 228 sb.append("?"); 229 } 230 return sb.toString(); 231 } 232 233 @NotNull 234 private String renderTypeName(@NotNull TypeConstructor typeConstructor) { 235 ClassifierDescriptor cd = typeConstructor.getDeclarationDescriptor(); 236 if (cd instanceof TypeParameterDescriptor) { 237 return renderName(cd.getName()); 238 } 239 else if (cd instanceof ClassDescriptor) { 240 return renderClassName((ClassDescriptor) cd); 241 } 242 else { 243 assert cd == null: "Unexpected classifier: " + cd.getClass(); 244 return typeConstructor.toString(); 245 } 246 } 247 248 private void appendTypeProjections(@NotNull List<TypeProjection> typeProjections, @NotNull StringBuilder builder) { 249 for (Iterator<TypeProjection> iterator = typeProjections.iterator(); iterator.hasNext(); ) { 250 TypeProjection typeProjection = iterator.next(); 251 if (typeProjection.getProjectionKind() != Variance.INVARIANT) { 252 builder.append(typeProjection.getProjectionKind()).append(" "); 253 } 254 builder.append(renderType(typeProjection.getType())); 255 if (iterator.hasNext()) { 256 builder.append(", "); 257 } 258 } 259 } 260 261 @NotNull 262 private String renderFunctionType(@NotNull JetType type) { 263 StringBuilder sb = new StringBuilder(); 264 265 JetType receiverType = KotlinBuiltIns.getInstance().getReceiverType(type); 266 if (receiverType != null) { 267 sb.append(renderType(receiverType)); 268 sb.append("."); 269 } 270 271 sb.append("("); 272 appendTypeProjections(KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(type), sb); 273 sb.append(") " + arrow() + " "); 274 sb.append(renderType(KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(type))); 275 276 if (type.isNullable()) { 277 return "(" + sb + ")?"; 278 } 279 return sb.toString(); 280 } 281 282 283 /* METHODS FOR ALL KINDS OF DESCRIPTORS */ 284 private void appendDefinedIn(@NotNull DeclarationDescriptor descriptor, @NotNull StringBuilder builder) { 285 if (descriptor instanceof PackageFragmentDescriptor || descriptor instanceof PackageViewDescriptor) { 286 return; 287 } 288 if (descriptor instanceof ModuleDescriptor) { 289 builder.append(" is a module"); 290 return; 291 } 292 builder.append(" ").append(renderMessage("defined in")).append(" "); 293 294 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 295 if (containingDeclaration != null) { 296 FqNameUnsafe fqName = DescriptorUtils.getFqName(containingDeclaration); 297 builder.append(FqName.ROOT.equalsTo(fqName) ? "root package" : renderFqName(fqName)); 298 } 299 } 300 301 private void renderAnnotations(@NotNull Annotated annotated, @NotNull StringBuilder builder) { 302 if (!modifiers.contains(Modifier.ANNOTATIONS)) return; 303 for (AnnotationDescriptor annotation : annotated.getAnnotations()) { 304 ClassDescriptor annotationClass = (ClassDescriptor) annotation.getType().getConstructor().getDeclarationDescriptor(); 305 assert annotationClass != null; 306 307 if (!excludedAnnotationClasses.contains(DescriptorUtils.getFqNameSafe(annotationClass))) { 308 builder.append(renderType(annotation.getType())); 309 if (verbose) { 310 builder.append("(").append(StringUtil.join(DescriptorUtils.getSortedValueArguments(annotation, this), ", ")).append(")"); 311 } 312 builder.append(" "); 313 } 314 } 315 } 316 317 private void renderVisibility(@NotNull Visibility visibility, @NotNull StringBuilder builder) { 318 if (!modifiers.contains(Modifier.VISIBILITY)) return; 319 if (normalizedVisibilities) { 320 visibility = visibility.normalize(); 321 } 322 if (!showInternalKeyword && visibility == Visibilities.INTERNAL) return; 323 builder.append(renderKeyword(visibility.toString())).append(" "); 324 } 325 326 private void renderModality(@NotNull Modality modality, @NotNull StringBuilder builder) { 327 if (!modifiers.contains(Modifier.MODALITY)) return; 328 String keyword = modality.name().toLowerCase(); 329 builder.append(renderKeyword(keyword)).append(" "); 330 } 331 332 private void renderInner(boolean isInner, @NotNull StringBuilder builder) { 333 if (!modifiers.contains(Modifier.INNER)) return; 334 if (isInner) { 335 builder.append(renderKeyword("inner")).append(" "); 336 } 337 } 338 339 private void renderModalityForCallable(@NotNull CallableMemberDescriptor callable, @NotNull StringBuilder builder) { 340 if (!DescriptorUtils.isTopLevelDeclaration(callable) || callable.getModality() != Modality.FINAL) { 341 if (overridesSomething(callable) 342 && overrideRenderingPolicy == OverrideRenderingPolicy.RENDER_OVERRIDE 343 && callable.getModality() == Modality.OPEN) { 344 return; 345 } 346 renderModality(callable.getModality(), builder); 347 } 348 } 349 350 private boolean overridesSomething(CallableMemberDescriptor callable) { 351 return !callable.getOverriddenDescriptors().isEmpty(); 352 } 353 354 private void renderOverride(@NotNull CallableMemberDescriptor callableMember, @NotNull StringBuilder builder) { 355 if (!modifiers.contains(Modifier.OVERRIDE)) return; 356 if (overridesSomething(callableMember)) { 357 if (overrideRenderingPolicy != OverrideRenderingPolicy.RENDER_OPEN) { 358 builder.append("override "); 359 if (verbose) { 360 builder.append("/*").append(callableMember.getOverriddenDescriptors().size()).append("*/ "); 361 } 362 } 363 } 364 } 365 366 private void renderMemberKind(CallableMemberDescriptor callableMember, StringBuilder builder) { 367 if (!modifiers.contains(Modifier.MEMBER_KIND)) return; 368 if (verbose && callableMember.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { 369 builder.append("/*").append(callableMember.getKind().name().toLowerCase()).append("*/ "); 370 } 371 } 372 373 @NotNull 374 @Override 375 public String render(@NotNull DeclarationDescriptor declarationDescriptor) { 376 StringBuilder stringBuilder = new StringBuilder(); 377 declarationDescriptor.accept(new RenderDeclarationDescriptorVisitor(), stringBuilder); 378 379 if (withDefinedIn) { 380 appendDefinedIn(declarationDescriptor, stringBuilder); 381 } 382 return stringBuilder.toString(); 383 } 384 385 386 /* TYPE PARAMETERS */ 387 private void renderTypeParameter(@NotNull TypeParameterDescriptor typeParameter, @NotNull StringBuilder builder, boolean topLevel) { 388 if (topLevel) { 389 builder.append(lt()); 390 } 391 392 if (verbose) { 393 builder.append("/*").append(typeParameter.getIndex()).append("*/ "); 394 } 395 396 if (typeParameter.isReified()) { 397 builder.append(renderKeyword("reified")).append(" "); 398 } 399 String variance = typeParameter.getVariance().toString(); 400 if (!variance.isEmpty()) { 401 builder.append(renderKeyword(variance)).append(" "); 402 } 403 renderName(typeParameter, builder); 404 int upperBoundsCount = typeParameter.getUpperBounds().size(); 405 if ((upperBoundsCount > 1 && !topLevel) || upperBoundsCount == 1) { 406 JetType upperBound = typeParameter.getUpperBounds().iterator().next(); 407 if (!KotlinBuiltIns.getInstance().getDefaultBound().equals(upperBound)) { 408 builder.append(" : ").append(renderType(upperBound)); 409 } 410 } 411 else if (topLevel) { 412 boolean first = true; 413 for (JetType upperBound : typeParameter.getUpperBounds()) { 414 if (upperBound.equals(KotlinBuiltIns.getInstance().getDefaultBound())) { 415 continue; 416 } 417 if (first) { 418 builder.append(" : "); 419 } 420 else { 421 builder.append(" & "); 422 } 423 builder.append(renderType(upperBound)); 424 first = false; 425 } 426 } 427 else { 428 // rendered with "where" 429 } 430 431 if (topLevel) { 432 builder.append(">"); 433 } 434 } 435 436 private void renderTypeParameters( 437 @NotNull List<TypeParameterDescriptor> typeParameters, 438 @NotNull StringBuilder builder, 439 boolean withSpace 440 ) { 441 if (!typeParameters.isEmpty()) { 442 builder.append(lt()); 443 for (Iterator<TypeParameterDescriptor> iterator = typeParameters.iterator(); iterator.hasNext(); ) { 444 TypeParameterDescriptor typeParameterDescriptor = iterator.next(); 445 renderTypeParameter(typeParameterDescriptor, builder, false); 446 if (iterator.hasNext()) { 447 builder.append(", "); 448 } 449 } 450 builder.append(">"); 451 if (withSpace) { 452 builder.append(" "); 453 } 454 } 455 } 456 457 /* FUNCTIONS */ 458 private void renderFunction(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) { 459 if (!startFromName) { 460 renderAnnotations(function, builder); 461 renderVisibility(function.getVisibility(), builder); 462 renderModalityForCallable(function, builder); 463 renderOverride(function, builder); 464 renderMemberKind(function, builder); 465 466 builder.append(renderKeyword("fun")).append(" "); 467 renderTypeParameters(function.getTypeParameters(), builder, true); 468 469 ReceiverParameterDescriptor receiver = function.getReceiverParameter(); 470 if (receiver != null) { 471 builder.append(escape(renderType(receiver.getType()))).append("."); 472 } 473 } 474 475 renderName(function, builder); 476 renderValueParameters(function, builder); 477 JetType returnType = function.getReturnType(); 478 if (unitReturnType || !KotlinBuiltIns.getInstance().isUnit(returnType)) { 479 builder.append(": ").append(returnType == null ? "[NULL]" : escape(renderType(returnType))); 480 } 481 renderWhereSuffix(function.getTypeParameters(), builder); 482 } 483 484 private void renderConstructor(@NotNull ConstructorDescriptor constructor, @NotNull StringBuilder builder) { 485 renderAnnotations(constructor, builder); 486 renderVisibility(constructor.getVisibility(), builder); 487 renderMemberKind(constructor, builder); 488 489 builder.append(renderKeyword("constructor")).append(" "); 490 491 ClassDescriptor classDescriptor = constructor.getContainingDeclaration(); 492 renderName(classDescriptor, builder); 493 494 renderTypeParameters(classDescriptor.getTypeConstructor().getParameters(), builder, false); 495 renderValueParameters(constructor, builder); 496 renderWhereSuffix(constructor.getTypeParameters(), builder); 497 } 498 499 private void renderWhereSuffix(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull StringBuilder builder) { 500 List<String> upperBoundStrings = Lists.newArrayList(); 501 502 for (TypeParameterDescriptor typeParameter : typeParameters) { 503 if (typeParameter.getUpperBounds().size() > 1) { 504 boolean first = true; 505 for (JetType upperBound : typeParameter.getUpperBounds()) { 506 // first parameter is rendered by renderTypeParameter: 507 if (!first) { 508 upperBoundStrings.add(renderName(typeParameter.getName()) + " : " + escape(renderType(upperBound))); 509 } 510 first = false; 511 } 512 } 513 } 514 if (!upperBoundStrings.isEmpty()) { 515 builder.append(" ").append(renderKeyword("where")).append(" "); 516 builder.append(StringUtil.join(upperBoundStrings, ", ")); 517 } 518 } 519 520 @NotNull 521 @Override 522 public String renderFunctionParameters(@NotNull FunctionDescriptor functionDescriptor) { 523 StringBuilder stringBuilder = new StringBuilder(); 524 renderValueParameters(functionDescriptor, stringBuilder); 525 return stringBuilder.toString(); 526 } 527 528 private void renderValueParameters(@NotNull FunctionDescriptor function, @NotNull StringBuilder builder) { 529 handler.appendBeforeValueParameters(function, builder); 530 for (ValueParameterDescriptor parameter : function.getValueParameters()) { 531 handler.appendBeforeValueParameter(parameter, builder); 532 renderValueParameter(parameter, builder, false); 533 handler.appendAfterValueParameter(parameter, builder); 534 } 535 handler.appendAfterValueParameters(function, builder); 536 } 537 538 /* VARIABLES */ 539 private void renderValueParameter(@NotNull ValueParameterDescriptor valueParameter, @NotNull StringBuilder builder, boolean topLevel) { 540 if (topLevel) { 541 builder.append(renderKeyword("value-parameter")).append(" "); 542 } 543 544 if (verbose) { 545 builder.append("/*").append(valueParameter.getIndex()).append("*/ "); 546 } 547 548 renderAnnotations(valueParameter, builder); 549 renderVariable(valueParameter, builder, topLevel); 550 boolean withDefaultValue = debugMode ? valueParameter.declaresDefaultValue() : valueParameter.hasDefaultValue(); 551 if (withDefaultValue) { 552 builder.append(" = ..."); 553 } 554 } 555 556 private void renderValVarPrefix(@NotNull VariableDescriptor variable, @NotNull StringBuilder builder) { 557 builder.append(renderKeyword(variable.isVar() ? "var" : "val")).append(" "); 558 } 559 560 private void renderVariable(@NotNull VariableDescriptor variable, @NotNull StringBuilder builder, boolean topLevel) { 561 JetType realType = variable.getType(); 562 563 JetType varargElementType = variable instanceof ValueParameterDescriptor 564 ? ((ValueParameterDescriptor) variable).getVarargElementType() 565 : null; 566 JetType typeToRender = varargElementType != null ? varargElementType : realType; 567 568 if (varargElementType != null) { 569 builder.append(renderKeyword("vararg")).append(" "); 570 } 571 if (topLevel && !startFromName) { 572 renderValVarPrefix(variable, builder); 573 } 574 575 renderName(variable, builder); 576 builder.append(": ").append(escape(renderType(typeToRender))); 577 578 if (verbose && varargElementType != null) { 579 builder.append(" /*").append(escape(renderType(realType))).append("*/"); 580 } 581 } 582 583 private void renderProperty(@NotNull PropertyDescriptor property, @NotNull StringBuilder builder) { 584 if (!startFromName) { 585 renderAnnotations(property, builder); 586 renderVisibility(property.getVisibility(), builder); 587 renderModalityForCallable(property, builder); 588 renderOverride(property, builder); 589 renderMemberKind(property, builder); 590 591 renderValVarPrefix(property, builder); 592 } 593 594 renderTypeParameters(property.getTypeParameters(), builder, true); 595 596 ReceiverParameterDescriptor receiver = property.getReceiverParameter(); 597 if (receiver != null) { 598 builder.append(escape(renderType(receiver.getType()))).append("."); 599 } 600 renderName(property, builder); 601 builder.append(": ").append(escape(renderType(property.getType()))); 602 603 renderWhereSuffix(property.getTypeParameters(), builder); 604 } 605 606 607 /* CLASSES */ 608 private void renderClass(@NotNull ClassDescriptor klass, @NotNull StringBuilder builder) { 609 if (!startFromName) { 610 renderAnnotations(klass, builder); 611 renderVisibility(klass.getVisibility(), builder); 612 if (!(klass.getKind() == ClassKind.TRAIT && klass.getModality() == Modality.ABSTRACT 613 || klass.getKind().isSingleton() && klass.getModality() == Modality.FINAL)) { 614 renderModality(klass.getModality(), builder); 615 } 616 renderInner(klass.isInner(), builder); 617 builder.append(renderKeyword(getClassKindPrefix(klass))); 618 } 619 620 if (klass.getKind() != ClassKind.CLASS_OBJECT || verbose) { 621 builder.append(" "); 622 renderName(klass, builder); 623 } 624 625 List<TypeParameterDescriptor> typeParameters = klass.getTypeConstructor().getParameters(); 626 renderTypeParameters(typeParameters, builder, false); 627 628 if (!klass.getKind().isSingleton() && classWithPrimaryConstructor) { 629 ConstructorDescriptor primaryConstructor = klass.getUnsubstitutedPrimaryConstructor(); 630 if (primaryConstructor != null) { 631 renderValueParameters(primaryConstructor, builder); 632 } 633 } 634 635 if (!klass.equals(KotlinBuiltIns.getInstance().getNothing())) { 636 Collection<JetType> supertypes = klass.getTypeConstructor().getSupertypes(); 637 if (supertypes.isEmpty() || supertypes.size() == 1 && KotlinBuiltIns.getInstance().isAnyOrNullableAny( 638 supertypes.iterator().next())) { 639 } 640 else { 641 builder.append(" : "); 642 for (Iterator<JetType> iterator = supertypes.iterator(); iterator.hasNext(); ) { 643 JetType supertype = iterator.next(); 644 builder.append(renderType(supertype)); 645 if (iterator.hasNext()) { 646 builder.append(", "); 647 } 648 } 649 } 650 } 651 652 renderWhereSuffix(typeParameters, builder); 653 } 654 655 @NotNull 656 private static String getClassKindPrefix(@NotNull ClassDescriptor klass) { 657 switch (klass.getKind()) { 658 case CLASS: 659 return "class"; 660 case TRAIT: 661 return "trait"; 662 case ENUM_CLASS: 663 return "enum class"; 664 case OBJECT: 665 return "object"; 666 case ANNOTATION_CLASS: 667 return "annotation class"; 668 case CLASS_OBJECT: 669 return "class object"; 670 case ENUM_ENTRY: 671 return "enum entry"; 672 default: 673 throw new IllegalStateException("unknown class kind: " + klass.getKind()); 674 } 675 } 676 677 678 /* OTHER */ 679 private void renderModuleOrScript(@NotNull DeclarationDescriptor moduleOrScript, @NotNull StringBuilder builder) { 680 renderName(moduleOrScript, builder); 681 } 682 683 private void renderPackageView(@NotNull PackageViewDescriptor packageView, @NotNull StringBuilder builder) { 684 builder.append(renderKeyword("package")).append(" "); 685 builder.append(renderFqName(packageView.getFqName())); 686 if (debugMode) { 687 builder.append(" in context of "); 688 renderName(packageView.getModule(), builder); 689 } 690 } 691 692 private void renderPackageFragment(@NotNull PackageFragmentDescriptor fragment, @NotNull StringBuilder builder) { 693 builder.append(renderKeyword("package-fragment")).append(" "); 694 builder.append(renderFqName(fragment.getFqName())); 695 if (debugMode) { 696 builder.append(" in "); 697 renderName(fragment.getContainingDeclaration(), builder); 698 } 699 } 700 701 702 /* STUPID DISPATCH-ONLY VISITOR */ 703 private class RenderDeclarationDescriptorVisitor extends DeclarationDescriptorVisitorEmptyBodies<Void, StringBuilder> { 704 @Override 705 public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) { 706 renderValueParameter(descriptor, builder, true); 707 return null; 708 } 709 710 @Override 711 public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) { 712 renderVariable(descriptor, builder, true); 713 return null; 714 } 715 716 @Override 717 public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) { 718 renderProperty(descriptor, builder); 719 return null; 720 } 721 722 @Override 723 public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) { 724 renderFunction(descriptor, builder); 725 return null; 726 } 727 728 @Override 729 public Void visitReceiverParameterDescriptor(ReceiverParameterDescriptor descriptor, StringBuilder data) { 730 throw new UnsupportedOperationException("Don't render receiver parameters"); 731 } 732 733 @Override 734 public Void visitConstructorDescriptor(ConstructorDescriptor constructorDescriptor, StringBuilder builder) { 735 renderConstructor(constructorDescriptor, builder); 736 return null; 737 } 738 739 @Override 740 public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) { 741 renderTypeParameter(descriptor, builder, true); 742 return null; 743 } 744 745 @Override 746 public Void visitPackageFragmentDescriptor( 747 PackageFragmentDescriptor descriptor, StringBuilder builder 748 ) { 749 renderPackageFragment(descriptor, builder); 750 return null; 751 } 752 753 @Override 754 public Void visitPackageViewDescriptor( 755 PackageViewDescriptor descriptor, StringBuilder builder 756 ) { 757 renderPackageView(descriptor, builder); 758 return null; 759 } 760 761 @Override 762 public Void visitModuleDeclaration(ModuleDescriptor descriptor, StringBuilder builder) { 763 renderModuleOrScript(descriptor, builder); 764 return null; 765 } 766 767 @Override 768 public Void visitScriptDescriptor(ScriptDescriptor scriptDescriptor, StringBuilder builder) { 769 renderModuleOrScript(scriptDescriptor, builder); 770 return null; 771 } 772 773 @Override 774 public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) { 775 renderClass(descriptor, builder); 776 return null; 777 } 778 } 779 }