From c14795f66d9f2d5e9de849c7bd0a886a340764ad Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Wed, 22 Jun 2016 14:43:28 +0300 Subject: [PATCH] KT-2752: refactor support of modules and root packages --- .../kotlin/js/naming/FQNGenerator.kt | 12 ++-- .../resolve/diagnostics/JsNameClashChecker.kt | 8 +-- .../js/translate/context/StaticContext.java | 58 ++++++++++--------- .../js/translate/context/UsageTracker.kt | 2 +- 4 files changed, 42 insertions(+), 38 deletions(-) diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/FQNGenerator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/FQNGenerator.kt index 0ff5748399a..1c211cccb63 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/FQNGenerator.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/FQNGenerator.kt @@ -27,24 +27,24 @@ import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import java.util.* class FQNGenerator { - private val cache: MutableMap = WeakHashMap() + private val cache: MutableMap = WeakHashMap() fun generate(descriptor: DeclarationDescriptor) = cache.getOrPut(descriptor) { generateCacheMiss(descriptor.original) } - private fun generateCacheMiss(descriptor: DeclarationDescriptor): FQNPart { + private fun generateCacheMiss(descriptor: DeclarationDescriptor): FQNPart? { + // Members of companion objects of classes are treated as static members of these classes if (isNativeObject(descriptor) && isCompanionObject(descriptor)) { return generate(descriptor.containingDeclaration!!) } when (descriptor) { - is ModuleDescriptor -> return FQNPart(listOf(descriptor.name.asString()), true, descriptor, descriptor) + is ModuleDescriptor -> return null is PackageFragmentDescriptor -> { return if (!descriptor.name.isSpecial) { - FQNPart(descriptor.fqName.pathSegments().map { it.asString() }, true, descriptor, - descriptor.containingDeclaration) + FQNPart(descriptor.fqName.pathSegments().map { it.asString() }, true, descriptor, descriptor.containingDeclaration) } else { - generate(descriptor.containingDeclaration) + null } } is FakeCallableDescriptorForObject -> return generate(descriptor.getReferencedDescriptor()) diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsNameClashChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsNameClashChecker.kt index 3e665a14a1d..5c9aed331a0 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsNameClashChecker.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsNameClashChecker.kt @@ -46,7 +46,7 @@ class JsNameClashChecker : SimpleDeclarationChecker { } private fun checkDescriptor(descriptor: DeclarationDescriptor, declaration: KtDeclaration, diagnosticHolder: DiagnosticSink) { - val fqn = fqnGenerator.generate(descriptor) + val fqn = fqnGenerator.generate(descriptor)!! if (fqn.shared && fqn.scope is ClassOrPackageFragmentDescriptor && isOpaque(fqn.descriptor)) { val scope = getScope(fqn.scope) val name = fqn.names.last() @@ -66,7 +66,7 @@ class JsNameClashChecker : SimpleDeclarationChecker { .mapNotNull { it as? CallableMemberDescriptor } .filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE } for (override in fakeOverrides) { - val overrideFqn = fqnGenerator.generate(override) + val overrideFqn = fqnGenerator.generate(override)!! val scope = getScope(overrideFqn.scope) val name = overrideFqn.names.last() val existing = scope[name] @@ -114,7 +114,7 @@ class JsNameClashChecker : SimpleDeclarationChecker { } } - val fqn = fqnGenerator.generate(descriptor) + val fqn = fqnGenerator.generate(descriptor) ?: return if (fqn.shared && isOpaque(fqn.descriptor)) { target[fqn.names.last()] = fqn.descriptor (fqn.descriptor as? CallableMemberDescriptor)?.let { checkOverrideClashes(it, target) } @@ -125,7 +125,7 @@ class JsNameClashChecker : SimpleDeclarationChecker { var overridden = descriptor.overriddenDescriptors while (overridden.isNotEmpty()) { for (overridenDescriptor in overridden) { - val overriddenFqn = fqnGenerator.generate(overridenDescriptor) + val overriddenFqn = fqnGenerator.generate(overridenDescriptor)!! if (overriddenFqn.shared) { val existing = target[overriddenFqn.names.last()] if (existing != null) { diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java index d99227dd83f..7f9ae518690 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java @@ -222,7 +222,7 @@ public final class StaticContext { @NotNull private JsExpression buildQualifiedExpression(@NotNull DeclarationDescriptor descriptor) { FQNPart part = fqnGenerator.generate(descriptor); - if (part.getDescriptor() instanceof ModuleDescriptor) { + if (part == null) { ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor); if (currentModule == module) { return pureFqn(Namer.getRootPackageName(), null); @@ -232,37 +232,36 @@ public final class StaticContext { return result != null ? result : JsAstUtils.pureFqn(rootScope.declareName(Namer.getRootPackageName()), null); } } + + JsExpression expression; + List partNames; + if (standardClasses.isStandardObject(part.getDescriptor())) { + expression = Namer.kotlinObject(); + partNames = Collections.singletonList(standardClasses.getStandardObjectName(part.getDescriptor())); + } + else if (isLibraryObject(part.getDescriptor())) { + expression = Namer.kotlinObject(); + partNames = getNameForFQNPart(part); + } + else if (isNative(part.getDescriptor()) && !isNativeObject(part.getScope())) { + expression = null; + partNames = getNameForFQNPart(part); + } else { - JsExpression expression; - List partNames; - if (standardClasses.isStandardObject(part.getDescriptor())) { - expression = Namer.kotlinObject(); - partNames = Collections.singletonList(standardClasses.getStandardObjectName(part.getDescriptor())); - } - else if (isLibraryObject(part.getDescriptor())) { - expression = Namer.kotlinObject(); - partNames = getNameForFQNPart(part); - } - else if (isNative(part.getDescriptor()) && !isNativeObject(part.getScope())) { + if (part.getDescriptor() instanceof CallableDescriptor && part.getScope() instanceof FunctionDescriptor) { expression = null; - partNames = getNameForFQNPart(part); } else { - if (part.getDescriptor() instanceof CallableDescriptor && part.getScope() instanceof FunctionDescriptor) { - expression = null; - } - else { - expression = getQualifiedExpression(part.getScope()); - } - partNames = getNameForFQNPart(part); + expression = getQualifiedExpression(part.getScope()); } - for (JsName partName : partNames) { - expression = new JsNameRef(partName, expression); - applySideEffects(expression, part.getDescriptor()); - } - assert expression != null : "Since partNames is not empty, expression must be non-null"; - return expression; + partNames = getNameForFQNPart(part); } + for (JsName partName : partNames) { + expression = new JsNameRef(partName, expression); + applySideEffects(expression, part.getDescriptor()); + } + assert expression != null : "Since partNames is not empty, expression must be non-null"; + return expression; } private static boolean isNative(DeclarationDescriptor descriptor) { @@ -284,7 +283,11 @@ public final class StaticContext { @NotNull public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) { - return getNameForFQNPart(fqnGenerator.generate(descriptor)).get(0); + FQNPart fqn = fqnGenerator.generate(descriptor); + if (fqn == null) { + throw new IllegalArgumentException("Can't generate name for root declarations: " + descriptor); + } + return getNameForFQNPart(fqn).get(0); } @NotNull @@ -293,6 +296,7 @@ public final class StaticContext { if (name == null) { FQNPart fqn = fqnGenerator.generate(property); + assert fqn != null : "Properties are non-root declarations: " + property; assert fqn.getNames().size() == 1 : "Private names must always consist of exactly one name"; JsScope scope = getScopeForDescriptor(fqn.getScope()); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/UsageTracker.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/UsageTracker.kt index 9e7760218dc..68b76944f6c 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/UsageTracker.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/UsageTracker.kt @@ -170,7 +170,7 @@ class UsageTracker( // Append 'closure$' prefix to avoid name clash between closure and member fields in case of local classes else -> { - val mangled = FQNGenerator().generate(this).names.last() + val mangled = FQNGenerator().generate(this)!!.names.last() "closure\$$mangled" } }