Additional logic in static context related to modules. Hacky fix for nameclashes when inheriting descriptors.

Adapted from https://github.com/develar/kotlin/commit/d3521123a6e4d551b30743b68b6bb23b9678553b.
This commit is contained in:
Pavel V. Talanov
2012-08-07 15:05:26 +04:00
parent 0a92843245
commit 5b2469227e
2 changed files with 70 additions and 26 deletions
@@ -42,7 +42,7 @@ public class LibrarySourcesConfig extends Config {
@NotNull @NotNull
public static final Key<String> EXTERNAL_MODULE_NAME = new Key<String>("externalModule"); public static final Key<String> EXTERNAL_MODULE_NAME = new Key<String>("externalModule");
@NotNull @NotNull
private static final String UNKNOWN_EXTERNAL_MODULE_NAME = "<unknown>"; public static final String UNKNOWN_EXTERNAL_MODULE_NAME = "<unknown>";
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jet.asJava.JetLightClass"); private static final Logger LOG = Logger.getInstance("#org.jetbrains.jet.asJava.JetLightClass");
@@ -18,12 +18,16 @@ package org.jetbrains.k2js.translate.context;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.config.LibrarySourcesConfig;
import org.jetbrains.k2js.translate.context.generator.Generator; import org.jetbrains.k2js.translate.context.generator.Generator;
import org.jetbrains.k2js.translate.context.generator.Rule; import org.jetbrains.k2js.translate.context.generator.Rule;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
@@ -46,11 +50,10 @@ public final class StaticContext {
public static StaticContext generateStaticContext(@NotNull BindingContext bindingContext, @NotNull EcmaVersion ecmaVersion) { public static StaticContext generateStaticContext(@NotNull BindingContext bindingContext, @NotNull EcmaVersion ecmaVersion) {
JsProgram program = new JsProgram("main"); JsProgram program = new JsProgram("main");
JsRootScope rootScope = program.getRootScope(); Namer namer = Namer.newInstance(program.getRootScope());
Namer namer = Namer.newInstance(rootScope);
Intrinsics intrinsics = new Intrinsics(); Intrinsics intrinsics = new Intrinsics();
StandardClasses standardClasses = StandardClasses.bindImplementations(namer.getKotlinScope()); StandardClasses standardClasses = StandardClasses.bindImplementations(namer.getKotlinScope());
return new StaticContext(program, bindingContext, namer, intrinsics, standardClasses, rootScope, ecmaVersion); return new StaticContext(program, bindingContext, namer, intrinsics, standardClasses, program.getRootScope(), ecmaVersion);
} }
@NotNull @NotNull
@@ -133,9 +136,9 @@ public final class StaticContext {
@NotNull @NotNull
public JsScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) { public JsScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) {
JsScope namingScope = scopes.get(descriptor.getOriginal()); JsScope scope = scopes.get(descriptor.getOriginal());
assert namingScope != null : "Must have a scope for descriptor"; assert scope != null : "Must have a scope for descriptor";
return namingScope; return scope;
} }
@NotNull @NotNull
@@ -189,11 +192,8 @@ public final class StaticContext {
@Override @Override
@Nullable @Nullable
public JsName apply(@NotNull DeclarationDescriptor descriptor) { public JsName apply(@NotNull DeclarationDescriptor descriptor) {
JsScope namingScope = getEnclosingScope(descriptor); JsScope scope = getEnclosingScope(descriptor);
if (descriptor instanceof ClassDescriptor) { return scope.declareFreshName(descriptor.getName().getName());
return namingScope.declareName(descriptor.getName().getName());
}
return namingScope.declareFreshName(descriptor.getName().getName());
} }
}; };
Rule<JsName> constructorHasTheSameNameAsTheClass = new Rule<JsName>() { Rule<JsName> constructorHasTheSameNameAsTheClass = new Rule<JsName>() {
@@ -213,9 +213,14 @@ public final class StaticContext {
if (!(descriptor instanceof PropertyAccessorDescriptor)) { if (!(descriptor instanceof PropertyAccessorDescriptor)) {
return null; return null;
} }
boolean isGetter = descriptor instanceof PropertyGetterDescriptor;
PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) descriptor; PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) descriptor;
String propertyName = accessorDescriptor.getCorrespondingProperty().getName().getName(); String propertyName = accessorDescriptor.getCorrespondingProperty().getName().getName();
if (accessorDescriptor.getCorrespondingProperty().isObjectDeclaration()) {
return declareName(descriptor, propertyName);
}
boolean isGetter = descriptor instanceof PropertyGetterDescriptor;
String accessorName = Namer.getNameForAccessor(propertyName, isGetter, String accessorName = Namer.getNameForAccessor(propertyName, isGetter,
!accessorDescriptor.getReceiverParameter().exists() && isEcma5()); !accessorDescriptor.getReceiverParameter().exists() && isEcma5());
return declareName(descriptor, accessorName); return declareName(descriptor, accessorName);
@@ -279,7 +284,11 @@ public final class StaticContext {
if (overriddenDescriptor == null) { if (overriddenDescriptor == null) {
return null; return null;
} }
return getNameForDescriptor(overriddenDescriptor);
JsScope scope = getEnclosingScope(descriptor);
JsName result = getNameForDescriptor(overriddenDescriptor);
scope.declareName(result.getIdent());
return result;
} }
}; };
addRule(namesForStandardClasses); addRule(namesForStandardClasses);
@@ -300,7 +309,6 @@ public final class StaticContext {
return getScopeForDescriptor(containingDeclaration.getOriginal()); return getScopeForDescriptor(containingDeclaration.getOriginal());
} }
private final class ScopeGenerator extends Generator<JsScope> { private final class ScopeGenerator extends Generator<JsScope> {
public ScopeGenerator() { public ScopeGenerator() {
@@ -353,11 +361,11 @@ public final class StaticContext {
return null; return null;
} }
JsScope enclosingScope = getEnclosingScope(descriptor); JsScope enclosingScope = getEnclosingScope(descriptor);
JsFunction correspondingFunction = JsAstUtils.createFunctionWithEmptyBody(enclosingScope); JsFunction correspondingFunction = JsAstUtils.createFunctionWithEmptyBody(enclosingScope);
JsScope newScope = correspondingFunction.getScope(); assert (!scopeToFunction.containsKey(correspondingFunction.getScope())) : "Scope to function value overridden for " + descriptor;
assert (!scopeToFunction.containsKey(newScope)) : "Scope to function value overridden for " + descriptor; scopeToFunction.put(correspondingFunction.getScope(), correspondingFunction);
scopeToFunction.put(newScope, correspondingFunction); return correspondingFunction.getScope();
return newScope;
} }
}; };
addRule(createFunctionObjectsForCallableDescriptors); addRule(createFunctionObjectsForCallableDescriptors);
@@ -387,17 +395,54 @@ public final class StaticContext {
return namer.kotlinObject(); return namer.kotlinObject();
} }
}; };
//TODO: review and refactor
Rule<JsNameRef> namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule<JsNameRef>() { Rule<JsNameRef> namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule<JsNameRef>() {
@Override @Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor); DeclarationDescriptor containingDescriptor = getContainingDeclaration(descriptor);
if (!(containingDeclaration instanceof NamespaceDescriptor)) { if (!(containingDescriptor instanceof NamespaceDescriptor)) {
return null; return null;
} }
JsName containingDeclarationName = getNameForDescriptor(containingDeclaration);
JsNameRef qualifier = containingDeclarationName.makeRef(); final JsNameRef result = new JsNameRef(getNameForDescriptor(containingDescriptor));
qualifier.setQualifier(getQualifierForDescriptor(containingDeclaration)); if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) containingDescriptor)) {
return qualifier; return result;
}
JsNameRef qualifier = result;
while ((containingDescriptor = getContainingDeclaration(containingDescriptor)) instanceof NamespaceDescriptor &&
!DescriptorUtils.isRootNamespace((NamespaceDescriptor) containingDescriptor)) {
JsNameRef ref = getNameForDescriptor(containingDescriptor).makeRef();
qualifier.setQualifier(ref);
qualifier = ref;
}
PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
if (element == null && descriptor instanceof PropertyAccessorDescriptor) {
element = BindingContextUtils.descriptorToDeclaration(bindingContext, ((PropertyAccessorDescriptor) descriptor)
.getCorrespondingProperty());
}
if (element != null) {
PsiFile file = element.getContainingFile();
String moduleName = file.getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME);
if (LibrarySourcesConfig.UNKNOWN_EXTERNAL_MODULE_NAME.equals(moduleName)) {
return null;
}
else if (moduleName != null) {
qualifier.setQualifier(new JsArrayAccess(namer.kotlin("modules"), program.getStringLiteral(moduleName)));
}
else if (result == qualifier && result.getIdent().equals("kotlin")) {
// todo WebDemoExamples2Test#testBuilder, package "kotlin" from kotlin/js/js.libraries/src/stdlib/JUMaps.kt must be inlined
return qualifier;
}
}
if (qualifier.getQualifier() == null) {
qualifier.setQualifier(new JsNameRef(Namer.getRootNamespaceName()));
}
return result;
} }
}; };
Rule<JsNameRef> constructorHaveTheSameQualifierAsTheClass = new Rule<JsNameRef>() { Rule<JsNameRef> constructorHaveTheSameQualifierAsTheClass = new Rule<JsNameRef>() {
@@ -412,7 +457,6 @@ public final class StaticContext {
} }
}; };
Rule<JsNameRef> libraryObjectsHaveKotlinQualifier = new Rule<JsNameRef>() { Rule<JsNameRef> libraryObjectsHaveKotlinQualifier = new Rule<JsNameRef>() {
@Override @Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
if (isLibraryObject(descriptor)) { if (isLibraryObject(descriptor)) {