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