KT-2752: refactor support of modules and root packages

This commit is contained in:
Alexey Andreev
2016-06-22 14:43:28 +03:00
parent c657716ae0
commit c14795f66d
4 changed files with 42 additions and 38 deletions
@@ -27,24 +27,24 @@ import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import java.util.* import java.util.*
class FQNGenerator { class FQNGenerator {
private val cache: MutableMap<DeclarationDescriptor, FQNPart> = WeakHashMap() private val cache: MutableMap<DeclarationDescriptor, FQNPart?> = WeakHashMap()
fun generate(descriptor: DeclarationDescriptor) = cache.getOrPut(descriptor) { generateCacheMiss(descriptor.original) } 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)) { if (isNativeObject(descriptor) && isCompanionObject(descriptor)) {
return generate(descriptor.containingDeclaration!!) return generate(descriptor.containingDeclaration!!)
} }
when (descriptor) { when (descriptor) {
is ModuleDescriptor -> return FQNPart(listOf(descriptor.name.asString()), true, descriptor, descriptor) is ModuleDescriptor -> return null
is PackageFragmentDescriptor -> { is PackageFragmentDescriptor -> {
return if (!descriptor.name.isSpecial) { return if (!descriptor.name.isSpecial) {
FQNPart(descriptor.fqName.pathSegments().map { it.asString() }, true, descriptor, FQNPart(descriptor.fqName.pathSegments().map { it.asString() }, true, descriptor, descriptor.containingDeclaration)
descriptor.containingDeclaration)
} }
else { else {
generate(descriptor.containingDeclaration) null
} }
} }
is FakeCallableDescriptorForObject -> return generate(descriptor.getReferencedDescriptor()) is FakeCallableDescriptorForObject -> return generate(descriptor.getReferencedDescriptor())
@@ -46,7 +46,7 @@ class JsNameClashChecker : SimpleDeclarationChecker {
} }
private fun checkDescriptor(descriptor: DeclarationDescriptor, declaration: KtDeclaration, diagnosticHolder: DiagnosticSink) { 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)) { if (fqn.shared && fqn.scope is ClassOrPackageFragmentDescriptor && isOpaque(fqn.descriptor)) {
val scope = getScope(fqn.scope) val scope = getScope(fqn.scope)
val name = fqn.names.last() val name = fqn.names.last()
@@ -66,7 +66,7 @@ class JsNameClashChecker : SimpleDeclarationChecker {
.mapNotNull { it as? CallableMemberDescriptor } .mapNotNull { it as? CallableMemberDescriptor }
.filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE } .filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
for (override in fakeOverrides) { for (override in fakeOverrides) {
val overrideFqn = fqnGenerator.generate(override) val overrideFqn = fqnGenerator.generate(override)!!
val scope = getScope(overrideFqn.scope) val scope = getScope(overrideFqn.scope)
val name = overrideFqn.names.last() val name = overrideFqn.names.last()
val existing = scope[name] 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)) { if (fqn.shared && isOpaque(fqn.descriptor)) {
target[fqn.names.last()] = fqn.descriptor target[fqn.names.last()] = fqn.descriptor
(fqn.descriptor as? CallableMemberDescriptor)?.let { checkOverrideClashes(it, target) } (fqn.descriptor as? CallableMemberDescriptor)?.let { checkOverrideClashes(it, target) }
@@ -125,7 +125,7 @@ class JsNameClashChecker : SimpleDeclarationChecker {
var overridden = descriptor.overriddenDescriptors var overridden = descriptor.overriddenDescriptors
while (overridden.isNotEmpty()) { while (overridden.isNotEmpty()) {
for (overridenDescriptor in overridden) { for (overridenDescriptor in overridden) {
val overriddenFqn = fqnGenerator.generate(overridenDescriptor) val overriddenFqn = fqnGenerator.generate(overridenDescriptor)!!
if (overriddenFqn.shared) { if (overriddenFqn.shared) {
val existing = target[overriddenFqn.names.last()] val existing = target[overriddenFqn.names.last()]
if (existing != null) { if (existing != null) {
@@ -222,7 +222,7 @@ public final class StaticContext {
@NotNull @NotNull
private JsExpression buildQualifiedExpression(@NotNull DeclarationDescriptor descriptor) { private JsExpression buildQualifiedExpression(@NotNull DeclarationDescriptor descriptor) {
FQNPart part = fqnGenerator.generate(descriptor); FQNPart part = fqnGenerator.generate(descriptor);
if (part.getDescriptor() instanceof ModuleDescriptor) { if (part == null) {
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor); ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
if (currentModule == module) { if (currentModule == module) {
return pureFqn(Namer.getRootPackageName(), null); return pureFqn(Namer.getRootPackageName(), null);
@@ -232,37 +232,36 @@ public final class StaticContext {
return result != null ? result : JsAstUtils.pureFqn(rootScope.declareName(Namer.getRootPackageName()), null); return result != null ? result : JsAstUtils.pureFqn(rootScope.declareName(Namer.getRootPackageName()), null);
} }
} }
JsExpression expression;
List<JsName> 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 { else {
JsExpression expression; if (part.getDescriptor() instanceof CallableDescriptor && part.getScope() instanceof FunctionDescriptor) {
List<JsName> 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; expression = null;
partNames = getNameForFQNPart(part);
} }
else { else {
if (part.getDescriptor() instanceof CallableDescriptor && part.getScope() instanceof FunctionDescriptor) { expression = getQualifiedExpression(part.getScope());
expression = null;
}
else {
expression = getQualifiedExpression(part.getScope());
}
partNames = getNameForFQNPart(part);
} }
for (JsName partName : partNames) { partNames = getNameForFQNPart(part);
expression = new JsNameRef(partName, expression);
applySideEffects(expression, part.getDescriptor());
}
assert expression != null : "Since partNames is not empty, expression must be non-null";
return expression;
} }
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) { private static boolean isNative(DeclarationDescriptor descriptor) {
@@ -284,7 +283,11 @@ public final class StaticContext {
@NotNull @NotNull
public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) { 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 @NotNull
@@ -293,6 +296,7 @@ public final class StaticContext {
if (name == null) { if (name == null) {
FQNPart fqn = fqnGenerator.generate(property); 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"; assert fqn.getNames().size() == 1 : "Private names must always consist of exactly one name";
JsScope scope = getScopeForDescriptor(fqn.getScope()); JsScope scope = getScopeForDescriptor(fqn.getScope());
@@ -170,7 +170,7 @@ class UsageTracker(
// Append 'closure$' prefix to avoid name clash between closure and member fields in case of local classes // Append 'closure$' prefix to avoid name clash between closure and member fields in case of local classes
else -> { else -> {
val mangled = FQNGenerator().generate(this).names.last() val mangled = FQNGenerator().generate(this)!!.names.last()
"closure\$$mangled" "closure\$$mangled"
} }
} }