Migrated JS backend to package views and fragments.

This commit is contained in:
Evgeny Gerashchenko
2013-11-07 23:57:57 +04:00
parent aa2ff87b47
commit 601cd4ce46
16 changed files with 172 additions and 198 deletions
@@ -1,30 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@Deprecated
public interface NamespaceDescriptor extends ClassOrNamespaceDescriptor {
@NotNull
JetScope getMemberScope();
@NotNull
FqName getFqName();
}
@@ -213,10 +213,6 @@ public class DescriptorUtils {
return false; return false;
} }
public static boolean isRootNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
return namespaceDescriptor.getContainingDeclaration() instanceof ModuleDescriptor;
}
public static boolean isFunctionLiteral(@NotNull FunctionDescriptor descriptor) { public static boolean isFunctionLiteral(@NotNull FunctionDescriptor descriptor) {
return descriptor instanceof AnonymousFunctionDescriptor; return descriptor instanceof AnonymousFunctionDescriptor;
} }
@@ -20,9 +20,8 @@ import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.plugin.JetLanguage; import org.jetbrains.jet.plugin.JetLanguage;
import static org.jetbrains.jet.lang.descriptors.ClassKind.TRAIT; import static org.jetbrains.jet.lang.descriptors.ClassKind.TRAIT;
@@ -258,13 +257,8 @@ public final class Namer {
} }
@NotNull @NotNull
static String generateNamespaceName(@NotNull DeclarationDescriptor descriptor) { static String generateNamespaceName(@NotNull FqName packageFqName) {
if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) { return packageFqName.isRoot() ? getRootNamespaceName() : packageFqName.shortName().asString();
return getRootNamespaceName();
}
else {
return descriptor.getName().asString();
}
} }
@NotNull @NotNull
@@ -18,14 +18,15 @@ 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.openapi.util.Factory;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile; import com.intellij.util.containers.ContainerUtil;
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.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.config.LibrarySourcesConfig; import org.jetbrains.k2js.config.LibrarySourcesConfig;
import org.jetbrains.k2js.translate.context.generator.Generator; import org.jetbrains.k2js.translate.context.generator.Generator;
@@ -78,6 +79,8 @@ public final class StaticContext {
@NotNull @NotNull
private final Generator<JsName> names = new NameGenerator(); private final Generator<JsName> names = new NameGenerator();
@NotNull @NotNull
private final Map<FqName, JsName> packageNames = Maps.newHashMap();
@NotNull
private final Generator<JsScope> scopes = new ScopeGenerator(); private final Generator<JsScope> scopes = new ScopeGenerator();
@NotNull @NotNull
private final Generator<JsNameRef> qualifiers = new QualifierGenerator(); private final Generator<JsNameRef> qualifiers = new QualifierGenerator();
@@ -161,9 +164,18 @@ public final class StaticContext {
@NotNull @NotNull
public JsNameRef getQualifiedReference(@NotNull DeclarationDescriptor descriptor) { public JsNameRef getQualifiedReference(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof PackageViewDescriptor) {
return getQualifiedReference(((PackageViewDescriptor) descriptor).getFqName());
}
return new JsNameRef(getNameForDescriptor(descriptor), getQualifierForDescriptor(descriptor)); return new JsNameRef(getNameForDescriptor(descriptor), getQualifierForDescriptor(descriptor));
} }
@NotNull
public JsNameRef getQualifiedReference(@NotNull FqName packageFqName) {
return new JsNameRef(getNameForPackage(packageFqName),
packageFqName.isRoot() ? null : getQualifierForParentPackage(packageFqName.parent()));
}
@NotNull @NotNull
public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) { public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) {
JsName name = names.get(descriptor.getOriginal()); JsName name = names.get(descriptor.getOriginal());
@@ -171,6 +183,39 @@ public final class StaticContext {
return name; return name;
} }
@NotNull
public JsName getNameForPackage(@NotNull final FqName packageFqName) {
return ContainerUtil.getOrCreate(packageNames, packageFqName, new Factory<JsName>() {
@Override
public JsName create() {
String name = Namer.generateNamespaceName(packageFqName);
return getRootScope().declareName(name);
}
});
}
@NotNull
private JsNameRef getQualifierForParentPackage(@NotNull FqName packageFqName) {
JsNameRef result = null;
JsNameRef qualifier = null;
for (FqName pathElement : ContainerUtil.reverse(packageFqName.path())) {
JsNameRef ref = getNameForPackage(pathElement).makeRef();
if (qualifier == null) {
result = ref;
}
else {
qualifier.setQualifier(ref);
}
qualifier = ref;
}
assert result != null : "didn't iterate: " + packageFqName;
return result;
}
private final class NameGenerator extends Generator<JsName> { private final class NameGenerator extends Generator<JsName> {
public NameGenerator() { public NameGenerator() {
@@ -184,18 +229,6 @@ public final class StaticContext {
return standardClasses.getStandardObjectName(data); return standardClasses.getStandardObjectName(data);
} }
}; };
Rule<JsName> namespacesShouldBeDefinedInRootScope = new Rule<JsName>() {
@Override
@Nullable
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
if (!(descriptor instanceof NamespaceDescriptor)) {
return null;
}
String name = Namer.generateNamespaceName(descriptor);
return getRootScope().declareName(name);
}
};
Rule<JsName> memberDeclarationsInsideParentsScope = new Rule<JsName>() { Rule<JsName> memberDeclarationsInsideParentsScope = new Rule<JsName>() {
@Override @Override
@Nullable @Nullable
@@ -328,7 +361,6 @@ public final class StaticContext {
addRule(constructorHasTheSameNameAsTheClass); addRule(constructorHasTheSameNameAsTheClass);
addRule(propertyOrPropertyAccessor); addRule(propertyOrPropertyAccessor);
addRule(predefinedObjectsHasUnobfuscatableNames); addRule(predefinedObjectsHasUnobfuscatableNames);
addRule(namespacesShouldBeDefinedInRootScope);
addRule(overridingDescriptorsReferToOriginalName); addRule(overridingDescriptorsReferToOriginalName);
addRule(memberDeclarationsInsideParentsScope); addRule(memberDeclarationsInsideParentsScope);
} }
@@ -374,10 +406,10 @@ public final class StaticContext {
return getScopeForDescriptor(superclass).innerScope("Scope for class " + descriptor.getName()); return getScopeForDescriptor(superclass).innerScope("Scope for class " + descriptor.getName());
} }
}; };
Rule<JsScope> generateNewScopesForNamespaceDescriptors = new Rule<JsScope>() { Rule<JsScope> generateNewScopesForPackageDescriptors = new Rule<JsScope>() {
@Override @Override
public JsScope apply(@NotNull DeclarationDescriptor descriptor) { public JsScope apply(@NotNull DeclarationDescriptor descriptor) {
if (!(descriptor instanceof NamespaceDescriptor)) { if (!(descriptor instanceof PackageFragmentDescriptor)) {
return null; return null;
} }
return getRootScope().innerScope("Namespace " + descriptor.getName()); return getRootScope().innerScope("Namespace " + descriptor.getName());
@@ -408,7 +440,7 @@ public final class StaticContext {
addRule(createFunctionObjectsForCallableDescriptors); addRule(createFunctionObjectsForCallableDescriptors);
addRule(generateNewScopesForClassesWithNoAncestors); addRule(generateNewScopesForClassesWithNoAncestors);
addRule(generateInnerScopesForDerivedClasses); addRule(generateInnerScopesForDerivedClasses);
addRule(generateNewScopesForNamespaceDescriptors); addRule(generateNewScopesForPackageDescriptors);
addRule(generateInnerScopesForMembers); addRule(generateInnerScopesForMembers);
} }
} }
@@ -433,49 +465,41 @@ public final class StaticContext {
} }
}; };
//TODO: review and refactor //TODO: review and refactor
Rule<JsNameRef> namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule<JsNameRef>() { Rule<JsNameRef> packageLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule<JsNameRef>() {
@Override @Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containingDescriptor = getContainingDeclaration(descriptor); DeclarationDescriptor containingDescriptor = getContainingDeclaration(descriptor);
if (!(containingDescriptor instanceof NamespaceDescriptor)) { if (!(containingDescriptor instanceof PackageFragmentDescriptor)) {
return null; return null;
} }
JsNameRef result = new JsNameRef(getNameForDescriptor(containingDescriptor)); JsNameRef result = getQualifierForParentPackage(((PackageFragmentDescriptor) containingDescriptor).getFqName());
if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) containingDescriptor)) {
String moduleName = getExternalModuleName(descriptor);
if (moduleName == null) {
return result; return result;
} }
JsNameRef qualifier = result; if (LibrarySourcesConfig.UNKNOWN_EXTERNAL_MODULE_NAME.equals(moduleName)) {
while ((containingDescriptor = getContainingDeclaration(containingDescriptor)) instanceof NamespaceDescriptor && return null;
!DescriptorUtils.isRootNamespace((NamespaceDescriptor) containingDescriptor)) {
JsNameRef ref = getNameForDescriptor(containingDescriptor).makeRef();
qualifier.setQualifier(ref);
qualifier = ref;
} }
JsAstUtils.replaceRootReference(
result, new JsArrayAccess(namer.kotlin("modules"), program.getStringLiteral(moduleName)));
return result;
}
private String getExternalModuleName(DeclarationDescriptor descriptor) {
PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
if (element == null && descriptor instanceof PropertyAccessorDescriptor) { if (element == null && descriptor instanceof PropertyAccessorDescriptor) {
element = BindingContextUtils.descriptorToDeclaration(bindingContext, ((PropertyAccessorDescriptor) descriptor) element = BindingContextUtils.descriptorToDeclaration(bindingContext, ((PropertyAccessorDescriptor) descriptor)
.getCorrespondingProperty()); .getCorrespondingProperty());
} }
if (element != null) { if (element == null) {
PsiFile file = element.getContainingFile(); return null;
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)));
}
} }
return element.getContainingFile().getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME);
if (qualifier.getQualifier() == null) {
qualifier.setQualifier(new JsNameRef(Namer.getRootNamespaceName()));
}
return result;
} }
}; };
Rule<JsNameRef> constructorHaveTheSameQualifierAsTheClass = new Rule<JsNameRef>() { Rule<JsNameRef> constructorHaveTheSameQualifierAsTheClass = new Rule<JsNameRef>() {
@@ -501,7 +525,7 @@ public final class StaticContext {
addRule(libraryObjectsHaveKotlinQualifier); addRule(libraryObjectsHaveKotlinQualifier);
addRule(constructorHaveTheSameQualifierAsTheClass); addRule(constructorHaveTheSameQualifierAsTheClass);
addRule(standardObjectsHaveKotlinQualifier); addRule(standardObjectsHaveKotlinQualifier);
addRule(namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier); addRule(packageLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier);
} }
} }
@@ -527,16 +551,6 @@ public final class StaticContext {
return true; return true;
} }
}; };
Rule<Boolean> topLevelNamespaceHaveNoQualifier = new Rule<Boolean>() {
@Override
public Boolean apply(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof NamespaceDescriptor && DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) {
return true;
}
return null;
}
};
addRule(topLevelNamespaceHaveNoQualifier);
addRule(propertiesHaveNoQualifiers); addRule(propertiesHaveNoQualifiers);
addRule(nativeObjectsHaveNoQualifiers); addRule(nativeObjectsHaveNoQualifiers);
} }
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator; import org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
@@ -170,6 +171,11 @@ public class TranslationContext {
return staticContext.getNameForDescriptor(descriptor); return staticContext.getNameForDescriptor(descriptor);
} }
@NotNull
public JsName getNameForPackage(@NotNull FqName fqName) {
return staticContext.getNameForPackage(fqName);
}
@NotNull @NotNull
public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name, boolean fresh) { public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name, boolean fresh) {
return staticContext.declarePropertyOrPropertyAccessorName(descriptor, name, fresh); return staticContext.declarePropertyOrPropertyAccessorName(descriptor, name, fresh);
@@ -180,6 +186,11 @@ public class TranslationContext {
return staticContext.getQualifiedReference(descriptor); return staticContext.getQualifiedReference(descriptor);
} }
@NotNull
public JsNameRef getQualifiedReference(@NotNull FqName packageFqName) {
return staticContext.getQualifiedReference(packageFqName);
}
@Nullable @Nullable
public JsNameRef getQualifierForDescriptor(@NotNull DeclarationDescriptor descriptor) { public JsNameRef getQualifierForDescriptor(@NotNull DeclarationDescriptor descriptor) {
return staticContext.getQualifierForDescriptor(descriptor); return staticContext.getQualifierForDescriptor(descriptor);
@@ -165,13 +165,13 @@ public final class UsageTracker {
return false; return false;
} }
// differs from DescriptorUtils - fails if reach NamespaceDescriptor // differs from DescriptorUtils - fails if reach PackageFragmentDescriptor
private static boolean isAncestor( private static boolean isAncestor(
@NotNull DeclarationDescriptor ancestor, @NotNull DeclarationDescriptor ancestor,
@NotNull DeclarationDescriptor declarationDescriptor @NotNull DeclarationDescriptor declarationDescriptor
) { ) {
DeclarationDescriptor descriptor = declarationDescriptor.getContainingDeclaration(); DeclarationDescriptor descriptor = declarationDescriptor.getContainingDeclaration();
while (descriptor != null && !(descriptor instanceof NamespaceDescriptor)) { while (descriptor != null && !(descriptor instanceof PackageFragmentDescriptor)) {
if (ancestor == descriptor) { if (ancestor == descriptor) {
return true; return true;
} }
@@ -19,7 +19,7 @@ package org.jetbrains.k2js.translate.declaration;
import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.*;
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.NamespaceDescriptor; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.utils.JsAstUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils;
@@ -31,13 +31,13 @@ public class DefineInvocation {
/* package */ /* package */
@NotNull @NotNull
static DefineInvocation createDefineInvocation( static DefineInvocation createDefineInvocation(
@NotNull NamespaceDescriptor descriptor, @NotNull FqName packageFqName,
@Nullable JsExpression initializer, @Nullable JsExpression initializer,
@NotNull JsObjectLiteral members, @NotNull JsObjectLiteral members,
@NotNull TranslationContext context @NotNull TranslationContext context
) { ) {
return new DefineInvocation(initializer == null ? JsLiteral.NULL : initializer, return new DefineInvocation(initializer == null ? JsLiteral.NULL : initializer,
new JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, context.getQualifiedReference(descriptor)), new JsDocComment(JsAstUtils.LENDS_JS_DOC_TAG, context.getQualifiedReference(packageFqName)),
members); members);
} }
@@ -19,10 +19,10 @@ package org.jetbrains.k2js.translate.declaration;
import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.*;
import gnu.trove.THashMap; import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.AbstractTranslator;
@@ -34,8 +34,8 @@ import static org.jetbrains.k2js.translate.declaration.DefineInvocation.createDe
public final class NamespaceDeclarationTranslator extends AbstractTranslator { public final class NamespaceDeclarationTranslator extends AbstractTranslator {
private final Iterable<JetFile> files; private final Iterable<JetFile> files;
private final Map<NamespaceDescriptor,NamespaceTranslator> descriptorToTranslator = private final Map<PackageFragmentDescriptor, NamespaceTranslator> packageFragmentToTranslator =
new LinkedHashMap<NamespaceDescriptor, NamespaceTranslator>(); new LinkedHashMap<PackageFragmentDescriptor, NamespaceTranslator>();
public static List<JsStatement> translateFiles(@NotNull Collection<JetFile> files, @NotNull TranslationContext context) { public static List<JsStatement> translateFiles(@NotNull Collection<JetFile> files, @NotNull TranslationContext context) {
return new NamespaceDeclarationTranslator(files, context).translate(); return new NamespaceDeclarationTranslator(files, context).translate();
@@ -50,51 +50,36 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
@NotNull @NotNull
private List<JsStatement> translate() { private List<JsStatement> translate() {
// predictable order // predictable order
Map<NamespaceDescriptor, DefineInvocation> descriptorToDefineInvocation = new THashMap<NamespaceDescriptor, DefineInvocation>(); Map<FqName, DefineInvocation> packageFqNameToDefineInvocation = new THashMap<FqName, DefineInvocation>();
NamespaceDescriptor rootNamespaceDescriptor = null;
for (JetFile file : files) { for (JetFile file : files) {
// TODO 1 PackageFragmentDescriptor packageFragment = context().bindingContext().get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, file);
//NamespaceDescriptor descriptor = context().bindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
//assert descriptor != null; NamespaceTranslator translator = packageFragmentToTranslator.get(packageFragment);
//NamespaceTranslator translator = descriptorToTranslator.get(descriptor); if (translator == null) {
//if (translator == null) { createRootPackageDefineInvocationIfNeeded(packageFqNameToDefineInvocation);
// if (rootNamespaceDescriptor == null) { translator = new NamespaceTranslator(packageFragment, packageFqNameToDefineInvocation, context());
// rootNamespaceDescriptor = getRootPackageDescriptor(descriptorToDefineInvocation, descriptor); packageFragmentToTranslator.put(packageFragment, translator);
// } }
// translator = new NamespaceTranslator(descriptor, descriptorToDefineInvocation, context());
// descriptorToTranslator.put(descriptor, translator); translator.translate(file);
//}
//
//translator.translate(file);
} }
if (rootNamespaceDescriptor == null) { for (NamespaceTranslator translator : packageFragmentToTranslator.values()) {
return Collections.emptyList(); translator.add(packageFqNameToDefineInvocation);
}
for (NamespaceTranslator translator : descriptorToTranslator.values()) {
translator.add(descriptorToDefineInvocation);
} }
JsVars vars = new JsVars(true); JsVars vars = new JsVars(true);
vars.addIfHasInitializer(getRootPackageDeclaration(descriptorToDefineInvocation.get(rootNamespaceDescriptor))); vars.addIfHasInitializer(getRootPackageDeclaration(packageFqNameToDefineInvocation.get(FqName.ROOT)));
return Collections.<JsStatement>singletonList(vars); return Collections.<JsStatement>singletonList(vars);
} }
@NotNull private void createRootPackageDefineInvocationIfNeeded(@NotNull Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) {
private NamespaceDescriptor getRootPackageDescriptor( if (!packageFqNameToDefineInvocation.containsKey(FqName.ROOT)) {
@NotNull Map<NamespaceDescriptor, DefineInvocation> descriptorToDefineInvocation, packageFqNameToDefineInvocation.put(
@NotNull NamespaceDescriptor descriptor FqName.ROOT, createDefineInvocation(FqName.ROOT, null, new JsObjectLiteral(true), context()));
) {
NamespaceDescriptor rootNamespace = descriptor;
while (DescriptorUtils.isTopLevelDeclaration(rootNamespace)) {
rootNamespace = (NamespaceDescriptor) rootNamespace.getContainingDeclaration();
} }
descriptorToDefineInvocation.put(rootNamespace, createDefineInvocation(rootNamespace, null, new JsObjectLiteral(true), context()));
return rootNamespace;
} }
private JsVar getRootPackageDeclaration(@NotNull DefineInvocation defineInvocation) { private JsVar getRootPackageDeclaration(@NotNull DefineInvocation defineInvocation) {
@@ -22,8 +22,9 @@ import com.intellij.openapi.util.Trinity;
import com.intellij.util.SmartList; import com.intellij.util.SmartList;
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.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.k2js.translate.LabelGenerator; import org.jetbrains.k2js.translate.LabelGenerator;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.AbstractTranslator;
@@ -38,15 +39,15 @@ import static org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator.
final class NamespaceTranslator extends AbstractTranslator { final class NamespaceTranslator extends AbstractTranslator {
@NotNull @NotNull
private final NamespaceDescriptor descriptor; private final PackageFragmentDescriptor descriptor;
private final FileDeclarationVisitor visitor; private final FileDeclarationVisitor visitor;
private final NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>> definitionPlace; private final NotNullLazyValue<Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression>> definitionPlace;
NamespaceTranslator( NamespaceTranslator(
@NotNull final NamespaceDescriptor descriptor, @NotNull final PackageFragmentDescriptor descriptor,
@NotNull final Map<NamespaceDescriptor, DefineInvocation> descriptorToDefineInvocation, @NotNull final Map<FqName, DefineInvocation> packageFqNameToDefineInvocation,
@NotNull TranslationContext context @NotNull TranslationContext context
) { ) {
super(context.newDeclaration(descriptor)); super(context.newDeclaration(descriptor));
@@ -59,12 +60,12 @@ final class NamespaceTranslator extends AbstractTranslator {
@Override @Override
@NotNull @NotNull
public Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression> compute() { public Trinity<List<JsPropertyInitializer>, LabelGenerator, JsExpression> compute() {
DefineInvocation defineInvocation = descriptorToDefineInvocation.get(descriptor); DefineInvocation defineInvocation = packageFqNameToDefineInvocation.get(descriptor.getFqName());
if (defineInvocation == null) { if (defineInvocation == null) {
defineInvocation = createDefinitionPlace(null, descriptorToDefineInvocation); defineInvocation = createDefinitionPlace(null, packageFqNameToDefineInvocation);
} }
return createPlace(defineInvocation.getMembers(), context().getQualifiedReference(descriptor)); return createPlace(defineInvocation.getMembers(), context().getQualifiedReference(descriptor.getFqName()));
} }
}; };
} }
@@ -81,21 +82,22 @@ final class NamespaceTranslator extends AbstractTranslator {
private DefineInvocation createDefinitionPlace( private DefineInvocation createDefinitionPlace(
@Nullable JsExpression initializer, @Nullable JsExpression initializer,
Map<NamespaceDescriptor, DefineInvocation> descriptorToDefineInvocation Map<FqName, DefineInvocation> packageFqNameToDefineInvocation
) { ) {
DefineInvocation place = createDefineInvocation(descriptor, initializer, new JsObjectLiteral(visitor.getResult(), true), context()); FqName fqName = descriptor.getFqName();
descriptorToDefineInvocation.put(descriptor, place); DefineInvocation place = createDefineInvocation(fqName, initializer, new JsObjectLiteral(visitor.getResult(), true), context());
addToParent((NamespaceDescriptor) descriptor.getContainingDeclaration(), getEntry(descriptor, place), descriptorToDefineInvocation); packageFqNameToDefineInvocation.put(fqName, place);
addToParent(fqName.parent(), getEntry(fqName, place), packageFqNameToDefineInvocation);
return place; return place;
} }
public void add(@NotNull Map<NamespaceDescriptor, DefineInvocation> descriptorToDefineInvocation) { public void add(@NotNull Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) {
JsExpression initializer = visitor.computeInitializer(); JsExpression initializer = visitor.computeInitializer();
DefineInvocation defineInvocation = descriptorToDefineInvocation.get(descriptor); DefineInvocation defineInvocation = packageFqNameToDefineInvocation.get(descriptor.getFqName());
if (defineInvocation == null) { if (defineInvocation == null) {
if (initializer != null || !visitor.getResult().isEmpty()) { if (initializer != null || !visitor.getResult().isEmpty()) {
createDefinitionPlace(initializer, descriptorToDefineInvocation); createDefinitionPlace(initializer, packageFqNameToDefineInvocation);
} }
} }
else { else {
@@ -112,15 +114,17 @@ final class NamespaceTranslator extends AbstractTranslator {
} }
} }
private JsPropertyInitializer getEntry(@NotNull NamespaceDescriptor descriptor, DefineInvocation defineInvocation) { private JsPropertyInitializer getEntry(@NotNull FqName fqName, DefineInvocation defineInvocation) {
return new JsPropertyInitializer(context().getNameForDescriptor(descriptor).makeRef(), return new JsPropertyInitializer(context().getNameForPackage(fqName).makeRef(),
new JsInvocation(context().namer().packageDefinitionMethodReference(), defineInvocation.asList())); new JsInvocation(context().namer().packageDefinitionMethodReference(), defineInvocation.asList()));
} }
private boolean addEntryIfParentExists(NamespaceDescriptor parentDescriptor, private static boolean addEntryIfParentExists(
FqName parentFqName,
JsPropertyInitializer entry, JsPropertyInitializer entry,
Map<NamespaceDescriptor, DefineInvocation> descriptorToDeclarationPlace) { Map<FqName, DefineInvocation> packageFqNameToDeclarationPlace
DefineInvocation parentDefineInvocation = descriptorToDeclarationPlace.get(parentDescriptor); ) {
DefineInvocation parentDefineInvocation = packageFqNameToDeclarationPlace.get(parentFqName);
if (parentDefineInvocation != null) { if (parentDefineInvocation != null) {
parentDefineInvocation.getMembers().add(entry); parentDefineInvocation.getMembers().add(entry);
return true; return true;
@@ -128,16 +132,16 @@ final class NamespaceTranslator extends AbstractTranslator {
return false; return false;
} }
private void addToParent(NamespaceDescriptor parentDescriptor, private void addToParent(@NotNull FqName parentFqName,
JsPropertyInitializer entry, JsPropertyInitializer entry,
Map<NamespaceDescriptor, DefineInvocation> descriptorToDefineInvocation) { Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) {
while (!addEntryIfParentExists(parentDescriptor, entry, descriptorToDefineInvocation)) { while (!addEntryIfParentExists(parentFqName, entry, packageFqNameToDefineInvocation)) {
JsObjectLiteral members = new JsObjectLiteral(new SmartList<JsPropertyInitializer>(entry), true); JsObjectLiteral members = new JsObjectLiteral(new SmartList<JsPropertyInitializer>(entry), true);
DefineInvocation defineInvocation = createDefineInvocation(parentDescriptor, null, members, context()); DefineInvocation defineInvocation = createDefineInvocation(parentFqName, null, members, context());
entry = getEntry(parentDescriptor, defineInvocation); entry = getEntry(parentFqName, defineInvocation);
descriptorToDefineInvocation.put(parentDescriptor, defineInvocation); packageFqNameToDefineInvocation.put(parentFqName, defineInvocation);
parentDescriptor = (NamespaceDescriptor) parentDescriptor.getContainingDeclaration(); parentFqName = parentFqName.parent();
} }
} }
@@ -179,8 +179,8 @@ public final class TopLevelFIF extends CompositeFIF {
add(pattern("jet", "Map", "get").checkOverridden(), NATIVE_MAP_GET); add(pattern("jet", "Map", "get").checkOverridden(), NATIVE_MAP_GET);
add(pattern("js", "set").receiverExists(), NATIVE_MAP_SET); add(pattern("js", "set").receiverExists(), NATIVE_MAP_SET);
add(pattern("java", "util", "HashMap", "<init>"), new MapSelectImplementationIntrinsic(false)); add(pattern("java.util", "HashMap", "<init>"), new MapSelectImplementationIntrinsic(false));
add(pattern("java", "util", "HashSet", "<init>"), new MapSelectImplementationIntrinsic(true)); add(pattern("java.util", "HashSet", "<init>"), new MapSelectImplementationIntrinsic(true));
add(pattern("js", "Json", "get"), ArrayFIF.GET_INTRINSIC); add(pattern("js", "Json", "get"), ArrayFIF.GET_INTRINSIC);
add(pattern("js", "Json", "set"), ArrayFIF.SET_INTRINSIC); add(pattern("js", "Json", "set"), ArrayFIF.SET_INTRINSIC);
@@ -18,10 +18,7 @@ package org.jetbrains.k2js.translate.intrinsic.functions.patterns;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.OverridingUtil; import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
@@ -127,11 +124,6 @@ public final class PatternBuilder {
return new DescriptorPredicateImpl(names); return new DescriptorPredicateImpl(names);
} }
private static boolean isRootNamespace(DeclarationDescriptor declarationDescriptor) {
return declarationDescriptor instanceof NamespaceDescriptor && DescriptorUtils.isRootNamespace(
(NamespaceDescriptor) declarationDescriptor);
}
public static class DescriptorPredicateImpl implements DescriptorPredicate { public static class DescriptorPredicateImpl implements DescriptorPredicate {
private final String[] names; private final String[] names;
@@ -156,20 +148,21 @@ public final class PatternBuilder {
private boolean matches(@NotNull CallableDescriptor callable) { private boolean matches(@NotNull CallableDescriptor callable) {
DeclarationDescriptor descriptor = callable; DeclarationDescriptor descriptor = callable;
int nameIndex = names.length - 1; int nameIndex = names.length - 1;
do { while (true) {
if (nameIndex == -1) { if (nameIndex == -1) {
return isRootNamespace(descriptor);
}
else if (isRootNamespace(descriptor)) {
return false; return false;
} }
if (!descriptor.getName().asString().equals(names[nameIndex--])) { if (!descriptor.getName().asString().equals(names[nameIndex])) {
return false; return false;
} }
nameIndex--;
descriptor = descriptor.getContainingDeclaration();
if (descriptor instanceof PackageFragmentDescriptor) {
return nameIndex == 0 && names[0].equals(((PackageFragmentDescriptor) descriptor).getFqName().asString());
}
} }
while ((descriptor = descriptor.getContainingDeclaration()) != null);
return true;
} }
@Override @Override
@@ -38,7 +38,7 @@ public final class CompareToInstrinsic implements BinaryOperationIntrinsic {
} }
FunctionDescriptor functionDescriptor = getFunctionDescriptorForOperationExpression(context.bindingContext(), expression); FunctionDescriptor functionDescriptor = getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
assert functionDescriptor != null; assert functionDescriptor != null;
return JsDescriptorUtils.isStandardDeclaration(functionDescriptor); return JsDescriptorUtils.isBuiltin(functionDescriptor);
} }
@NotNull @NotNull
@@ -48,7 +48,7 @@ public final class EqualsIntrinsic implements BinaryOperationIntrinsic {
} }
FunctionDescriptor functionDescriptor = getFunctionDescriptorForOperationExpression(context.bindingContext(), expression); FunctionDescriptor functionDescriptor = getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
assert functionDescriptor != null; assert functionDescriptor != null;
return JsDescriptorUtils.isStandardDeclaration(functionDescriptor); return JsDescriptorUtils.isBuiltin(functionDescriptor);
} }
@Override @Override
@@ -20,7 +20,7 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
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.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.utils.ErrorReportingUtils; import org.jetbrains.k2js.translate.utils.ErrorReportingUtils;
@@ -112,7 +112,7 @@ public final class QualifiedExpressionTranslator {
if (receiverExpression instanceof JetReferenceExpression) { if (receiverExpression instanceof JetReferenceExpression) {
DeclarationDescriptor descriptorForReferenceExpression = DeclarationDescriptor descriptorForReferenceExpression =
getDescriptorForReferenceExpression(context.bindingContext(), (JetReferenceExpression)receiverExpression); getDescriptorForReferenceExpression(context.bindingContext(), (JetReferenceExpression)receiverExpression);
if (descriptorForReferenceExpression instanceof NamespaceDescriptor) { if (descriptorForReferenceExpression instanceof PackageViewDescriptor) {
return true; return true;
} }
} }
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.Modality; import org.jetbrains.jet.lang.descriptors.Modality;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import java.util.Arrays; import java.util.Arrays;
@@ -244,4 +245,18 @@ public final class JsAstUtils {
public static JsObjectLiteral wrapValue(@NotNull JsExpression label, @NotNull JsExpression value) { public static JsObjectLiteral wrapValue(@NotNull JsExpression label, @NotNull JsExpression value) {
return new JsObjectLiteral(Collections.singletonList(new JsPropertyInitializer(label, value))); return new JsObjectLiteral(Collections.singletonList(new JsPropertyInitializer(label, value)));
} }
public static void replaceRootReference(@NotNull JsNameRef fullQualifier, @NotNull JsExpression newQualifier) {
JsNameRef qualifier = fullQualifier;
while (true) {
JsExpression parent = qualifier.getQualifier();
assert parent instanceof JsNameRef : "unexpected qualifier: " + parent + ", original: " + fullQualifier;
if (((JsNameRef) parent).getQualifier() == null) {
assert Namer.getRootNamespaceName().equals(((JsNameRef) parent).getIdent());
qualifier.setQualifier(newQualifier);
return;
}
qualifier = (JsNameRef) parent;
}
}
} }
@@ -163,17 +163,9 @@ public final class JsDescriptorUtils {
!propertyDescriptor.getModality().isOverridable(); !propertyDescriptor.getModality().isOverridable();
} }
public static boolean isStandardDeclaration(@NotNull DeclarationDescriptor descriptor) { public static boolean isBuiltin(@NotNull DeclarationDescriptor descriptor) {
NamespaceDescriptor namespace = getContainingNamespace(descriptor); PackageFragmentDescriptor containingPackageFragment = DescriptorUtils.getParentOfType(descriptor, PackageFragmentDescriptor.class);
if (namespace == null) { return containingPackageFragment == KotlinBuiltIns.getInstance().getBuiltInsPackageFragment();
return false;
}
return namespace.equals(KotlinBuiltIns.getInstance().getBuiltInsScope().getContainingDeclaration());
}
@Nullable
public static NamespaceDescriptor getContainingNamespace(@NotNull DeclarationDescriptor descriptor) {
return DescriptorUtils.getParentOfType(descriptor, NamespaceDescriptor.class);
} }
@Nullable @Nullable