KT-2752: refactor support of modules and root packages
This commit is contained in:
@@ -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())
|
||||||
|
|||||||
+4
-4
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user