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