001 /* 002 * Copyright 2010-2016 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.kotlin.js.translate.context; 018 019 import com.google.common.collect.Lists; 020 import com.google.common.collect.Maps; 021 import com.google.dart.compiler.backend.js.ast.*; 022 import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata; 023 import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties; 024 import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind; 025 import com.intellij.openapi.util.Factory; 026 import com.intellij.util.containers.ContainerUtil; 027 import com.intellij.util.containers.HashMap; 028 import org.jetbrains.annotations.NotNull; 029 import org.jetbrains.annotations.Nullable; 030 import org.jetbrains.kotlin.builtins.ReflectionTypes; 031 import org.jetbrains.kotlin.descriptors.*; 032 import org.jetbrains.kotlin.js.config.JsConfig; 033 import org.jetbrains.kotlin.js.config.LibrarySourcesConfig; 034 import org.jetbrains.kotlin.js.translate.context.generator.Generator; 035 import org.jetbrains.kotlin.js.translate.context.generator.Rule; 036 import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics; 037 import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; 038 import org.jetbrains.kotlin.name.FqName; 039 import org.jetbrains.kotlin.resolve.BindingContext; 040 import org.jetbrains.kotlin.resolve.BindingTrace; 041 import org.jetbrains.kotlin.resolve.DescriptorUtils; 042 import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject; 043 044 import java.util.List; 045 import java.util.Map; 046 import java.util.Set; 047 048 import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.*; 049 import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn; 050 import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.*; 051 import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getMangledName; 052 import static org.jetbrains.kotlin.js.translate.utils.ManglingUtils.getSuggestedName; 053 import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; 054 import static org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt.isDynamic; 055 056 /** 057 * Aggregates all the static parts of the context. 058 */ 059 public final class StaticContext { 060 061 public static StaticContext generateStaticContext(@NotNull BindingTrace bindingTrace, @NotNull JsConfig config, @NotNull ModuleDescriptor moduleDescriptor) { 062 JsProgram program = new JsProgram("main"); 063 Namer namer = Namer.newInstance(program.getRootScope()); 064 Intrinsics intrinsics = new Intrinsics(); 065 StandardClasses standardClasses = StandardClasses.bindImplementations(namer.getKotlinScope()); 066 return new StaticContext(program, bindingTrace, namer, intrinsics, standardClasses, program.getRootScope(), config, moduleDescriptor); 067 } 068 069 @NotNull 070 private final JsProgram program; 071 072 @NotNull 073 private final BindingTrace bindingTrace; 074 @NotNull 075 private final Namer namer; 076 077 @NotNull 078 private final Intrinsics intrinsics; 079 080 @NotNull 081 private final StandardClasses standardClasses; 082 083 @NotNull 084 private final ReflectionTypes reflectionTypes; 085 086 @NotNull 087 private final JsScope rootScope; 088 089 @NotNull 090 private final Generator<JsName> names = new NameGenerator(); 091 @NotNull 092 private final Map<FqName, JsName> packageNames = Maps.newHashMap(); 093 @NotNull 094 private final Generator<JsScope> scopes = new ScopeGenerator(); 095 @NotNull 096 private final Generator<JsExpression> qualifiers = new QualifierGenerator(); 097 @NotNull 098 private final Generator<Boolean> qualifierIsNull = new QualifierIsNullGenerator(); 099 100 @NotNull 101 private final Map<JsScope, JsFunction> scopeToFunction = Maps.newHashMap(); 102 103 @NotNull 104 private final Map<MemberDescriptor, List<DeclarationDescriptor>> classOrConstructorClosure = Maps.newHashMap(); 105 106 @NotNull 107 private final Map<ClassDescriptor, List<DeferredCallSite>> deferredCallSites = new HashMap<ClassDescriptor, List<DeferredCallSite>>(); 108 109 @NotNull 110 private final JsConfig config; 111 112 //TODO: too many parameters in constructor 113 private StaticContext( 114 @NotNull JsProgram program, 115 @NotNull BindingTrace bindingTrace, 116 @NotNull Namer namer, 117 @NotNull Intrinsics intrinsics, 118 @NotNull StandardClasses standardClasses, 119 @NotNull JsScope rootScope, 120 @NotNull JsConfig config, 121 @NotNull ModuleDescriptor moduleDescriptor 122 ) { 123 this.program = program; 124 this.bindingTrace = bindingTrace; 125 this.namer = namer; 126 this.intrinsics = intrinsics; 127 this.rootScope = rootScope; 128 this.standardClasses = standardClasses; 129 this.config = config; 130 this.reflectionTypes = new ReflectionTypes(moduleDescriptor); 131 } 132 133 @NotNull 134 public JsProgram getProgram() { 135 return program; 136 } 137 138 @NotNull 139 public BindingTrace getBindingTrace() { 140 return bindingTrace; 141 } 142 143 @NotNull 144 public BindingContext getBindingContext() { 145 return bindingTrace.getBindingContext(); 146 } 147 148 @NotNull 149 public Intrinsics getIntrinsics() { 150 return intrinsics; 151 } 152 153 @NotNull 154 public Namer getNamer() { 155 return namer; 156 } 157 158 @NotNull 159 public ReflectionTypes getReflectionTypes() { 160 return reflectionTypes; 161 } 162 163 @NotNull 164 private JsScope getRootScope() { 165 return rootScope; 166 } 167 168 @NotNull 169 public JsScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) { 170 JsScope scope = scopes.get(descriptor.getOriginal()); 171 assert scope != null : "Must have a scope for descriptor"; 172 return scope; 173 } 174 175 @NotNull 176 public JsFunction getFunctionWithScope(@NotNull CallableDescriptor descriptor) { 177 JsScope scope = getScopeForDescriptor(descriptor); 178 JsFunction function = scopeToFunction.get(scope); 179 assert scope.equals(function.getScope()) : "Inconsistency."; 180 return function; 181 } 182 183 @NotNull 184 public JsNameRef getQualifiedReference(@NotNull DeclarationDescriptor descriptor) { 185 if (descriptor instanceof PackageViewDescriptor) { 186 return getQualifiedReference(((PackageViewDescriptor) descriptor).getFqName()); 187 } 188 if (descriptor instanceof PackageFragmentDescriptor) { 189 return getQualifiedReference(((PackageFragmentDescriptor) descriptor).getFqName()); 190 } 191 192 JsNameRef result = new JsNameRef(getNameForDescriptor(descriptor), getQualifierForDescriptor(descriptor)); 193 applySideEffects(result, descriptor); 194 return result; 195 } 196 197 @NotNull 198 public JsNameRef getQualifiedReference(@NotNull FqName packageFqName) { 199 JsName packageName = getNameForPackage(packageFqName); 200 return pureFqn(packageName, packageFqName.isRoot() ? null : getQualifierForParentPackage(packageFqName.parent())); 201 } 202 203 @NotNull 204 public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) { 205 JsName name = names.get(descriptor.getOriginal()); 206 assert name != null : "Must have name for descriptor"; 207 return name; 208 } 209 210 @NotNull 211 public JsName getNameForPackage(@NotNull final FqName packageFqName) { 212 return ContainerUtil.getOrCreate(packageNames, packageFqName, new Factory<JsName>() { 213 @Override 214 public JsName create() { 215 String name = Namer.generatePackageName(packageFqName); 216 return getRootScope().declareName(name); 217 } 218 }); 219 } 220 221 @NotNull 222 private JsNameRef getQualifierForParentPackage(@NotNull FqName packageFqName) { 223 JsNameRef result = null; 224 JsNameRef qualifier = null; 225 226 FqName fqName = packageFqName; 227 228 while (true) { 229 JsNameRef ref = pureFqn(getNameForPackage(fqName), null); 230 231 if (qualifier == null) { 232 result = ref; 233 } 234 else { 235 qualifier.setQualifier(ref); 236 } 237 238 qualifier = ref; 239 240 if (fqName.isRoot()) break; 241 fqName = fqName.parent(); 242 } 243 244 return result; 245 } 246 247 @NotNull 248 public JsConfig getConfig() { 249 return config; 250 } 251 252 private final class NameGenerator extends Generator<JsName> { 253 254 public NameGenerator() { 255 Rule<JsName> namesForDynamic = new Rule<JsName>() { 256 @Override 257 @Nullable 258 public JsName apply(@NotNull DeclarationDescriptor descriptor) { 259 if (isDynamic(descriptor)) { 260 String name = descriptor.getName().asString(); 261 return JsDynamicScope.INSTANCE.declareName(name); 262 } 263 264 return null; 265 } 266 }; 267 268 Rule<JsName> localClasses = new Rule<JsName>() { 269 @Nullable 270 @Override 271 public JsName apply(@NotNull DeclarationDescriptor descriptor) { 272 if (!DescriptorUtils.isDescriptorWithLocalVisibility(descriptor) || 273 !DescriptorUtils.isClass(descriptor)) { 274 return null; 275 } 276 277 String suggested = getSuggestedName(descriptor); 278 279 descriptor = getParentOfType(descriptor, ClassOrPackageFragmentDescriptor.class, true); 280 assert descriptor != null; 281 282 JsScope scope = getScopeForDescriptor(descriptor); 283 return scope.declareFreshName(suggested); 284 } 285 }; 286 287 Rule<JsName> namesForStandardClasses = new Rule<JsName>() { 288 @Override 289 @Nullable 290 public JsName apply(@NotNull DeclarationDescriptor data) { 291 if (!standardClasses.isStandardObject(data)) { 292 return null; 293 } 294 return standardClasses.getStandardObjectName(data); 295 } 296 }; 297 Rule<JsName> memberDeclarationsInsideParentsScope = new Rule<JsName>() { 298 @Override 299 @Nullable 300 public JsName apply(@NotNull DeclarationDescriptor descriptor) { 301 JsScope scope = getEnclosingScope(descriptor); 302 return scope.declareFreshName(getSuggestedName(descriptor)); 303 } 304 }; 305 Rule<JsName> constructorOrNativeCompanionObjectHasTheSameNameAsTheClass = new Rule<JsName>() { 306 @Override 307 public JsName apply(@NotNull DeclarationDescriptor descriptor) { 308 if (descriptor instanceof ConstructorDescriptor && ((ConstructorDescriptor) descriptor).isPrimary() || 309 DescriptorUtils.isCompanionObject(descriptor) && isNativeObject(descriptor)) { 310 //noinspection ConstantConditions 311 return getNameForDescriptor(descriptor.getContainingDeclaration()); 312 } 313 return null; 314 } 315 }; 316 317 // ecma 5 property name never declares as obfuscatable: 318 // 1) property cannot be overloaded, so, name collision is not possible 319 // 2) main reason: if property doesn't have any custom accessor, value holder will have the same name as accessor, so, the same name will be declared more than once 320 // 321 // But extension property may obfuscatable, because transform into function. Example: String.foo = 1, Int.foo = 2 322 Rule<JsName> propertyOrPropertyAccessor = new Rule<JsName>() { 323 @Override 324 public JsName apply(@NotNull DeclarationDescriptor descriptor) { 325 PropertyDescriptor propertyDescriptor; 326 if (descriptor instanceof PropertyAccessorDescriptor) { 327 propertyDescriptor = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty(); 328 } 329 else if (descriptor instanceof PropertyDescriptor) { 330 propertyDescriptor = (PropertyDescriptor) descriptor; 331 } 332 else { 333 return null; 334 } 335 336 String nameFromAnnotation = getNameForAnnotatedObjectWithOverrides(propertyDescriptor); 337 if (nameFromAnnotation != null) { 338 return declarePropertyOrPropertyAccessorName(descriptor, nameFromAnnotation, false); 339 } 340 341 String propertyName = getSuggestedName(propertyDescriptor); 342 343 if (!isExtension(propertyDescriptor)) { 344 if (Visibilities.isPrivate(propertyDescriptor.getVisibility())) { 345 propertyName = getMangledName(propertyDescriptor, propertyName); 346 } 347 return declarePropertyOrPropertyAccessorName(descriptor, propertyName, false); 348 } else { 349 assert !(descriptor instanceof PropertyDescriptor) : "descriptor should not be instance of PropertyDescriptor: " + descriptor; 350 351 boolean isGetter = descriptor instanceof PropertyGetterDescriptor; 352 String accessorName = Namer.getNameForAccessor(propertyName, isGetter, false); 353 return declarePropertyOrPropertyAccessorName(descriptor, accessorName, false); 354 } 355 } 356 }; 357 358 Rule<JsName> predefinedObjectsHasUnobfuscatableNames = new Rule<JsName>() { 359 @Override 360 public JsName apply(@NotNull DeclarationDescriptor descriptor) { 361 // The mixing of override and rename by annotation(e.g. native) is forbidden. 362 if (descriptor instanceof CallableMemberDescriptor && 363 !((CallableMemberDescriptor) descriptor).getOverriddenDescriptors().isEmpty()) { 364 return null; 365 } 366 367 if (descriptor instanceof ConstructorDescriptor) { 368 DeclarationDescriptor classDescriptor = descriptor.getContainingDeclaration(); 369 assert classDescriptor != null; 370 descriptor = classDescriptor; 371 } 372 373 String name = getNameForAnnotatedObjectWithOverrides(descriptor); 374 if (name != null) return getEnclosingScope(descriptor).declareName(name); 375 return null; 376 } 377 }; 378 379 Rule<JsName> overridingDescriptorsReferToOriginalName = new Rule<JsName>() { 380 @Override 381 public JsName apply(@NotNull DeclarationDescriptor descriptor) { 382 //TODO: refactor 383 if (!(descriptor instanceof FunctionDescriptor)) { 384 return null; 385 } 386 FunctionDescriptor overriddenDescriptor = getOverriddenDescriptor((FunctionDescriptor) descriptor); 387 if (overriddenDescriptor == null) { 388 return null; 389 } 390 391 JsScope scope = getEnclosingScope(descriptor); 392 JsName result = getNameForDescriptor(overriddenDescriptor); 393 scope.declareName(result.getIdent()); 394 return result; 395 } 396 }; 397 398 Rule<JsName> fakeCallableDescriptor = new Rule<JsName>() { 399 @Nullable 400 @Override 401 public JsName apply(@NotNull DeclarationDescriptor descriptor) { 402 if (!(descriptor instanceof FakeCallableDescriptorForObject)) { 403 return null; 404 } 405 406 FakeCallableDescriptorForObject fakeCallableDescriptor = (FakeCallableDescriptorForObject) descriptor; 407 return getNameForDescriptor(fakeCallableDescriptor.getReferencedDescriptor()); 408 } 409 }; 410 411 addRule(namesForDynamic); 412 addRule(localClasses); 413 addRule(namesForStandardClasses); 414 addRule(constructorOrNativeCompanionObjectHasTheSameNameAsTheClass); 415 addRule(propertyOrPropertyAccessor); 416 addRule(predefinedObjectsHasUnobfuscatableNames); 417 addRule(overridingDescriptorsReferToOriginalName); 418 addRule(fakeCallableDescriptor); 419 addRule(memberDeclarationsInsideParentsScope); 420 } 421 } 422 423 @NotNull 424 public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name, boolean fresh) { 425 JsScope scope = getEnclosingScope(descriptor); 426 return fresh ? scope.declareFreshName(name) : scope.declareName(name); 427 } 428 429 @NotNull 430 private JsScope getEnclosingScope(@NotNull DeclarationDescriptor descriptor) { 431 DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor); 432 return getScopeForDescriptor(containingDeclaration.getOriginal()); 433 } 434 435 private final class ScopeGenerator extends Generator<JsScope> { 436 437 public ScopeGenerator() { 438 Rule<JsScope> generateNewScopesForClassesWithNoAncestors = new Rule<JsScope>() { 439 @Override 440 public JsScope apply(@NotNull DeclarationDescriptor descriptor) { 441 if (!(descriptor instanceof ClassDescriptor)) { 442 return null; 443 } 444 if (getSuperclass((ClassDescriptor) descriptor) == null) { 445 return getRootScope().innerObjectScope("Scope for class " + descriptor.getName()); 446 } 447 return null; 448 } 449 }; 450 Rule<JsScope> generateInnerScopesForDerivedClasses = new Rule<JsScope>() { 451 @Override 452 public JsScope apply(@NotNull DeclarationDescriptor descriptor) { 453 if (!(descriptor instanceof ClassDescriptor)) { 454 return null; 455 } 456 ClassDescriptor superclass = getSuperclass((ClassDescriptor) descriptor); 457 if (superclass == null) { 458 return null; 459 } 460 return getScopeForDescriptor(superclass).innerObjectScope("Scope for class " + descriptor.getName()); 461 } 462 }; 463 Rule<JsScope> generateNewScopesForPackageDescriptors = new Rule<JsScope>() { 464 @Override 465 public JsScope apply(@NotNull DeclarationDescriptor descriptor) { 466 if (!(descriptor instanceof PackageFragmentDescriptor)) { 467 return null; 468 } 469 return getRootScope().innerObjectScope("Package " + descriptor.getName()); 470 } 471 }; 472 //TODO: never get there 473 Rule<JsScope> generateInnerScopesForMembers = new Rule<JsScope>() { 474 @Override 475 public JsScope apply(@NotNull DeclarationDescriptor descriptor) { 476 JsScope enclosingScope = getEnclosingScope(descriptor); 477 return enclosingScope.innerObjectScope("Scope for member " + descriptor.getName()); 478 } 479 }; 480 Rule<JsScope> createFunctionObjectsForCallableDescriptors = new Rule<JsScope>() { 481 @Override 482 public JsScope apply(@NotNull DeclarationDescriptor descriptor) { 483 if (!(descriptor instanceof CallableDescriptor)) { 484 return null; 485 } 486 JsScope enclosingScope = getEnclosingScope(descriptor); 487 488 JsFunction correspondingFunction = JsAstUtils.createFunctionWithEmptyBody(enclosingScope); 489 assert (!scopeToFunction.containsKey(correspondingFunction.getScope())) : "Scope to function value overridden for " + descriptor; 490 scopeToFunction.put(correspondingFunction.getScope(), correspondingFunction); 491 return correspondingFunction.getScope(); 492 } 493 }; 494 addRule(createFunctionObjectsForCallableDescriptors); 495 addRule(generateNewScopesForClassesWithNoAncestors); 496 addRule(generateInnerScopesForDerivedClasses); 497 addRule(generateNewScopesForPackageDescriptors); 498 addRule(generateInnerScopesForMembers); 499 } 500 } 501 502 @Nullable 503 public JsExpression getQualifierForDescriptor(@NotNull DeclarationDescriptor descriptor) { 504 if (qualifierIsNull.get(descriptor.getOriginal()) != null) { 505 return null; 506 } 507 return qualifiers.get(descriptor.getOriginal()); 508 } 509 510 private final class QualifierGenerator extends Generator<JsExpression> { 511 public QualifierGenerator() { 512 Rule<JsExpression> standardObjectsHaveKotlinQualifier = new Rule<JsExpression>() { 513 @Override 514 public JsExpression apply(@NotNull DeclarationDescriptor descriptor) { 515 if (!standardClasses.isStandardObject(descriptor)) { 516 return null; 517 } 518 return Namer.kotlinObject(); 519 } 520 }; 521 //TODO: review and refactor 522 Rule<JsExpression> packageLevelDeclarationsHaveEnclosingPackagesNamesAsQualifier = new Rule<JsExpression>() { 523 @Override 524 public JsExpression apply(@NotNull DeclarationDescriptor descriptor) { 525 if (isNativeObject(descriptor)) return null; 526 527 DeclarationDescriptor containingDescriptor = getContainingDeclaration(descriptor); 528 if (!(containingDescriptor instanceof PackageFragmentDescriptor)) { 529 return null; 530 } 531 532 JsNameRef result = getQualifierForParentPackage(((PackageFragmentDescriptor) containingDescriptor).getFqName()); 533 534 String moduleName = getExternalModuleName(descriptor); 535 if (moduleName == null) { 536 return result; 537 } 538 539 if (LibrarySourcesConfig.UNKNOWN_EXTERNAL_MODULE_NAME.equals(moduleName)) { 540 return null; 541 } 542 543 return JsAstUtils.replaceRootReference( 544 result, namer.getModuleReference(program.getStringLiteral(moduleName))); 545 } 546 }; 547 Rule<JsExpression> constructorOrCompanionObjectHasTheSameQualifierAsTheClass = new Rule<JsExpression>() { 548 @Override 549 public JsExpression apply(@NotNull DeclarationDescriptor descriptor) { 550 if (descriptor instanceof ConstructorDescriptor || 551 isNativeObject(descriptor) && DescriptorUtils.isCompanionObject(descriptor)) { 552 //noinspection ConstantConditions 553 return getQualifierForDescriptor(descriptor.getContainingDeclaration()); 554 } 555 return null; 556 } 557 }; 558 Rule<JsExpression> libraryObjectsHaveKotlinQualifier = new Rule<JsExpression>() { 559 @Override 560 public JsExpression apply(@NotNull DeclarationDescriptor descriptor) { 561 if (isLibraryObject(descriptor)) { 562 return Namer.kotlinObject(); 563 } 564 return null; 565 } 566 }; 567 Rule<JsExpression> nativeObjectsHaveNativePartOfFullQualifier = new Rule<JsExpression>() { 568 @Override 569 public JsExpression apply(@NotNull DeclarationDescriptor descriptor) { 570 if (descriptor instanceof ConstructorDescriptor || !isNativeObject(descriptor)) return null; 571 572 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 573 if (containingDeclaration != null && isNativeObject(containingDeclaration)) { 574 return isCompanionObject(descriptor) ? getQualifierForDescriptor(containingDeclaration) : 575 getQualifiedReference(containingDeclaration); 576 } 577 578 return null; 579 } 580 }; 581 Rule<JsExpression> staticMembersHaveContainerQualifier = new Rule<JsExpression>() { 582 @Override 583 public JsExpression apply(@NotNull DeclarationDescriptor descriptor) { 584 if (descriptor instanceof CallableDescriptor && !isNativeObject(descriptor)) { 585 CallableDescriptor callableDescriptor = (CallableDescriptor) descriptor; 586 if (DescriptorUtils.isStaticDeclaration(callableDescriptor)) { 587 return getQualifiedReference(callableDescriptor.getContainingDeclaration()); 588 } 589 } 590 591 return null; 592 } 593 }; 594 Rule<JsExpression> nestedClassesHaveContainerQualifier = new Rule<JsExpression>() { 595 @Nullable 596 @Override 597 public JsExpression apply(@NotNull DeclarationDescriptor descriptor) { 598 if (!(descriptor instanceof ClassDescriptor)) { 599 return null; 600 } 601 DeclarationDescriptor container = getParentOfType(descriptor, ClassDescriptor.class); 602 if (container == null) { 603 return null; 604 } 605 606 if (isNativeObject(descriptor)) { 607 return null; 608 } 609 return getQualifiedReference(container); 610 } 611 }; 612 613 Rule<JsExpression> localClassesHavePackageQualifier = new Rule<JsExpression>() { 614 @Nullable 615 @Override 616 public JsExpression apply(@NotNull DeclarationDescriptor descriptor) { 617 if (!DescriptorUtils.isDescriptorWithLocalVisibility(descriptor) || !(descriptor instanceof ClassDescriptor)) { 618 return null; 619 } 620 621 descriptor = getParentOfType(descriptor, PackageFragmentDescriptor.class, true); 622 assert descriptor != null; 623 return getQualifiedReference(descriptor); 624 } 625 }; 626 627 addRule(libraryObjectsHaveKotlinQualifier); 628 addRule(constructorOrCompanionObjectHasTheSameQualifierAsTheClass); 629 addRule(standardObjectsHaveKotlinQualifier); 630 addRule(packageLevelDeclarationsHaveEnclosingPackagesNamesAsQualifier); 631 addRule(nativeObjectsHaveNativePartOfFullQualifier); 632 addRule(staticMembersHaveContainerQualifier); 633 addRule(nestedClassesHaveContainerQualifier); 634 addRule(localClassesHavePackageQualifier); 635 } 636 } 637 638 private static JsExpression applySideEffects(JsExpression expression, DeclarationDescriptor descriptor) { 639 if (expression instanceof HasMetadata) { 640 if (descriptor instanceof FunctionDescriptor || 641 descriptor instanceof PackageFragmentDescriptor || 642 descriptor instanceof ClassDescriptor 643 ) { 644 MetadataProperties.setSideEffects((HasMetadata) expression, SideEffectKind.PURE); 645 } 646 } 647 return expression; 648 } 649 650 private static class QualifierIsNullGenerator extends Generator<Boolean> { 651 652 private QualifierIsNullGenerator() { 653 Rule<Boolean> propertiesInClassHaveNoQualifiers = new Rule<Boolean>() { 654 @Override 655 public Boolean apply(@NotNull DeclarationDescriptor descriptor) { 656 if ((descriptor instanceof PropertyDescriptor) && descriptor.getContainingDeclaration() instanceof ClassDescriptor) { 657 return true; 658 } 659 return null; 660 } 661 }; 662 addRule(propertiesInClassHaveNoQualifiers); 663 } 664 } 665 666 public void putClassOrConstructorClosure(@NotNull MemberDescriptor localClass, @NotNull List<DeclarationDescriptor> closure) { 667 classOrConstructorClosure.put(localClass, Lists.newArrayList(closure)); 668 } 669 670 @Nullable 671 public List<DeclarationDescriptor> getClassOrConstructorClosure(@NotNull MemberDescriptor descriptor) { 672 List<DeclarationDescriptor> result = classOrConstructorClosure.get(descriptor); 673 return result != null ? Lists.newArrayList(result) : null; 674 } 675 676 @NotNull 677 public Map<ClassDescriptor, List<DeferredCallSite>> getDeferredCallSites() { 678 return deferredCallSites; 679 } 680 }