001 /* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.k2js.translate.declaration; 018 019 import com.google.dart.compiler.backend.js.ast.*; 020 import gnu.trove.THashMap; 021 import org.jetbrains.annotations.NotNull; 022 import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor; 023 import org.jetbrains.jet.lang.psi.JetFile; 024 import org.jetbrains.jet.lang.resolve.BindingContext; 025 import org.jetbrains.jet.lang.resolve.BindingContextUtils; 026 import org.jetbrains.jet.lang.resolve.name.FqName; 027 import org.jetbrains.k2js.translate.context.Namer; 028 import org.jetbrains.k2js.translate.context.TranslationContext; 029 import org.jetbrains.k2js.translate.general.AbstractTranslator; 030 031 import java.util.*; 032 033 import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar; 034 035 public final class PackageDeclarationTranslator extends AbstractTranslator { 036 private final Iterable<JetFile> files; 037 private final Map<PackageFragmentDescriptor, PackageTranslator> packageFragmentToTranslator = 038 new LinkedHashMap<PackageFragmentDescriptor, PackageTranslator>(); 039 040 public static List<JsStatement> translateFiles(@NotNull Collection<JetFile> files, @NotNull TranslationContext context) { 041 return new PackageDeclarationTranslator(files, context).translate(); 042 } 043 044 private PackageDeclarationTranslator(@NotNull Iterable<JetFile> files, @NotNull TranslationContext context) { 045 super(context); 046 047 this.files = files; 048 } 049 050 @NotNull 051 private List<JsStatement> translate() { 052 // predictable order 053 Map<FqName, DefineInvocation> packageFqNameToDefineInvocation = new THashMap<FqName, DefineInvocation>(); 054 055 for (JetFile file : files) { 056 PackageFragmentDescriptor packageFragment = 057 BindingContextUtils.getNotNull(context().bindingContext(), BindingContext.FILE_TO_PACKAGE_FRAGMENT, file); 058 059 PackageTranslator translator = packageFragmentToTranslator.get(packageFragment); 060 if (translator == null) { 061 createRootPackageDefineInvocationIfNeeded(packageFqNameToDefineInvocation); 062 translator = PackageTranslator.create(packageFragment, context()); 063 packageFragmentToTranslator.put(packageFragment, translator); 064 } 065 066 translator.translate(file); 067 } 068 069 for (PackageTranslator translator : packageFragmentToTranslator.values()) { 070 translator.add(packageFqNameToDefineInvocation); 071 } 072 073 JsVars vars = new JsVars(true); 074 vars.addIfHasInitializer(getRootPackageDeclaration(packageFqNameToDefineInvocation.get(FqName.ROOT))); 075 076 return Collections.<JsStatement>singletonList(vars); 077 } 078 079 private void createRootPackageDefineInvocationIfNeeded(@NotNull Map<FqName, DefineInvocation> packageFqNameToDefineInvocation) { 080 if (!packageFqNameToDefineInvocation.containsKey(FqName.ROOT)) { 081 packageFqNameToDefineInvocation.put( 082 FqName.ROOT, DefineInvocation.create(FqName.ROOT, null, new JsObjectLiteral(true), context())); 083 } 084 } 085 086 private JsVar getRootPackageDeclaration(@NotNull DefineInvocation defineInvocation) { 087 JsExpression rootPackageVar = new JsInvocation(context().namer().rootPackageDefinitionMethodReference(), defineInvocation.asList()); 088 return new JsVar(context().scope().declareName(Namer.getRootPackageName()), rootPackageVar); 089 } 090 }