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