diff --git a/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java index ea1c42db269..d6c0191d062 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java @@ -151,10 +151,10 @@ public class K2JSCompiler extends CLICompiler args = Lists.newArrayList("-tags", "-verbose", "-version"); + private static String[] constructArguments(@NotNull Module module, @Nullable String outFile, @NotNull VirtualFile srcDir) { + ArrayList args = Lists.newArrayList("-tags", "-verbose", "-version", "-mainCall", "mainWithArgs"); addPathToSourcesDir(args, srcDir); addOutputPath(outFile, args); - addLibLocationAndTarget(project, args); + addLibLocationAndTarget(module, args); return ArrayUtil.toStringArray(args); } - private static void addLibLocationAndTarget(@NotNull Project project, @NotNull ArrayList args) { - Pair libLocationAndTarget = JsModuleDetector.getLibLocationAndTargetForProject(project); - if (libLocationAndTarget.first != null) { - args.add("-libzip"); - args.add(libLocationAndTarget.first); + // we cannot use OrderEnumerator because it has critical bug — try https://gist.github.com/2953261, processor will never be called for module dependency + private static void collectModuleDependencies(Module dependentModule, Set modules) { + for (OrderEntry entry : ModuleRootManager.getInstance(dependentModule).getOrderEntries()) { + if (entry instanceof ModuleOrderEntry) { + ModuleOrderEntry moduleEntry = (ModuleOrderEntry) entry; + if (!moduleEntry.getScope().isForProductionCompile()) { + continue; + } + + Module module = moduleEntry.getModule(); + if (module == null) { + continue; + } + + if (modules.add(module) && moduleEntry.isExported()) { + collectModuleDependencies(module, modules); + } + } } + } + + private static void addLibLocationAndTarget(@NotNull Module module, @NotNull ArrayList args) { + Pair libLocationAndTarget = JsModuleDetector.getLibLocationAndTargetForProject(module); + + StringBuilder sb = StringBuilderSpinAllocator.alloc(); + AccessToken token = ReadAction.start(); + try { + THashSet modules = new THashSet(); + collectModuleDependencies(module, modules); + if (!modules.isEmpty()) { + VirtualFile[] files = CompilerManager.getInstance(module.getProject()).createModulesCompileScope( + modules.toArray(new Module[modules.size()]), false).getFiles(JetFileType.INSTANCE, true); + for (VirtualFile file : files) { + sb.append(file.getPath()).append(','); + } + } + + if (libLocationAndTarget.first != null) { + for (String file : libLocationAndTarget.first) { + sb.append(file).append(','); + } + } + + if (sb.length() > 0) { + args.add("-libraryFiles"); + args.add(sb.substring(0, sb.length() - 1)); + } + } + finally { + token.finish(); + StringBuilderSpinAllocator.dispose(sb); + } + if (libLocationAndTarget.second != null) { args.add("-target"); args.add(libLocationAndTarget.second); diff --git a/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java b/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java index db29e72d794..74f003e8b21 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java +++ b/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java @@ -19,14 +19,14 @@ package org.jetbrains.jet.plugin.project; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.k2js.config.EcmaVersion; -import org.jetbrains.k2js.config.ZippedLibrarySourcesConfig; +import org.jetbrains.k2js.config.LibrarySourcesConfig; import static org.jetbrains.jet.plugin.project.JsModuleDetector.getLibLocationAndTargetForProject; /** * @author Pavel Talanov */ -public final class IDEAConfig extends ZippedLibrarySourcesConfig { +public final class IDEAConfig extends LibrarySourcesConfig { public IDEAConfig(@NotNull Project project) { super(project, getLibLocationAndTargetForProject(project).first, EcmaVersion.defaultVersion()); } diff --git a/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java b/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java index 796791c1179..c401ff1ad43 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java +++ b/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java @@ -57,15 +57,22 @@ public final class JsModuleDetector { } @NotNull - public static Pair getLibLocationAndTargetForProject(@NotNull Project project) { + public static Pair getLibLocationAndTargetForProject(@NotNull Project project) { Module module = getJSModule(project); if (module == null) { return Pair.empty(); } + else { + return getLibLocationAndTargetForProject(module); + } + } + + @NotNull + public static Pair getLibLocationAndTargetForProject(@NotNull Module module) { K2JSModuleComponent jsModuleComponent = K2JSModuleComponent.getInstance(module); String pathToJavaScriptLibrary = jsModuleComponent.getPathToJavaScriptLibrary(); String basePath = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath(); - return Pair.create(basePath + pathToJavaScriptLibrary, jsModuleComponent.getEcmaVersion().toString()); + return Pair.create(new String[] {basePath + pathToJavaScriptLibrary}, jsModuleComponent.getEcmaVersion().toString()); } @Nullable diff --git a/js/js.translator/src/org/jetbrains/k2js/config/ZippedLibrarySourcesConfig.java b/js/js.translator/src/org/jetbrains/k2js/config/LibrarySourcesConfig.java similarity index 61% rename from js/js.translator/src/org/jetbrains/k2js/config/ZippedLibrarySourcesConfig.java rename to js/js.translator/src/org/jetbrains/k2js/config/LibrarySourcesConfig.java index 723e0171ba7..17bc500c55b 100644 --- a/js/js.translator/src/org/jetbrains/k2js/config/ZippedLibrarySourcesConfig.java +++ b/js/js.translator/src/org/jetbrains/k2js/config/LibrarySourcesConfig.java @@ -18,6 +18,7 @@ package org.jetbrains.k2js.config; import com.google.common.collect.Lists; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,6 +28,7 @@ import org.jetbrains.k2js.utils.JetFileUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; @@ -36,33 +38,53 @@ import java.util.zip.ZipFile; /** * @author Pavel Talanov */ -public class ZippedLibrarySourcesConfig extends Config { - @Nullable - protected final String pathToLibZip; +public class LibrarySourcesConfig extends Config { + public static final Key EXTERNAL_LIB = new Key("externalLib"); - public ZippedLibrarySourcesConfig(@NotNull Project project, @Nullable String pathToZip, @NotNull EcmaVersion ecmaVersion) { + @Nullable + private final String[] files; + + public LibrarySourcesConfig(@NotNull Project project, @Nullable String[] files, @NotNull EcmaVersion ecmaVersion) { super(project, ecmaVersion); - pathToLibZip = pathToZip; + this.files = files; } @NotNull @Override public List generateLibFiles() { - if (pathToLibZip == null) { + if (files == null) { return Collections.emptyList(); } - try { - File file = new File(pathToLibZip); - ZipFile zipFile = new ZipFile(file); + + List jetFiles = new ArrayList(); + for (String path : files) { + File file = new File(path); try { - return traverseArchive(zipFile); + String name = file.getName(); + if (name.endsWith(".jar") || name.endsWith(".zip")) { + jetFiles.addAll(readZip(file)); + } + else { + JetFile psiFile = JetFileUtils.createPsiFile(path, FileUtil.loadFile(file), getProject()); + psiFile.putUserData(EXTERNAL_LIB, true); + jetFiles.add(psiFile); + } } - finally { - zipFile.close(); + catch (IOException e) { + throw new RuntimeException(e); } } - catch (IOException e) { - return Collections.emptyList(); + + return jetFiles; + } + + private List readZip(File file) throws IOException { + ZipFile zipFile = new ZipFile(file); + try { + return traverseArchive(zipFile); + } + finally { + zipFile.close(); } } @@ -76,6 +98,7 @@ public class ZippedLibrarySourcesConfig extends Config { InputStream stream = file.getInputStream(entry); String text = FileUtil.loadTextAndClose(stream); JetFile jetFile = JetFileUtils.createPsiFile(entry.getName(), text, getProject()); + jetFile.putUserData(EXTERNAL_LIB, true); result.add(jetFile); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java b/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java index ddd6dc3a352..1ecf6050d93 100644 --- a/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java @@ -96,13 +96,11 @@ public final class K2JSTranslator { throws TranslationException { JetStandardLibrary.initialize(config.getProject()); BindingContext bindingContext = AnalyzerFacadeForJS.analyzeFilesAndCheckErrors(filesToTranslate, config); - Collection files = AnalyzerFacadeForJS.withJsLibAdded(filesToTranslate, config); - - return Translation.generateAst(bindingContext, Lists.newArrayList(files), mainCallParameters, config.getTarget(), rawStatements); + return Translation.generateAst(bindingContext, filesToTranslate, mainCallParameters, config.getTarget(), rawStatements); } @NotNull private Project getProject() { return config.getProject(); } -} +} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java index 5c90678041e..67d5b0566bf 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java @@ -144,7 +144,7 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { @NotNull public List classDeclarationsForNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { List result = Lists.newArrayList(); - for (ClassDescriptor classDescriptor : getAllClassesDefinedInNamespace(namespaceDescriptor)) { + for (ClassDescriptor classDescriptor : getAllClassesDefinedInNamespace(namespaceDescriptor, bindingContext())) { result.add(getClassNameToClassObject(classDescriptor)); } return result; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java index 76cad438282..6edbad6fac6 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java @@ -31,6 +31,7 @@ import org.jetbrains.k2js.translate.utils.JsAstUtils; import org.jetbrains.k2js.translate.utils.JsDescriptorUtils; import org.jetbrains.k2js.translate.utils.TranslationUtils; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -64,33 +65,28 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { private List getAllClasses() { List result = Lists.newArrayList(); for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) { - result.addAll(getAllClassesDefinedInNamespace(namespaceDescriptor)); + result.addAll(getAllClassesDefinedInNamespace(namespaceDescriptor, context().bindingContext())); } return result; } @NotNull private List translate() { - List result = classesDeclarations(); - result.addAll(namespacesDeclarations()); + List result = new ArrayList(); + classesDeclarations(result); + namespacesDeclarations(result); return result; } - @NotNull - private List classesDeclarations() { - List result = Lists.newArrayList(); + private void classesDeclarations(List statements) { classDeclarationTranslator.generateDeclarations(); - result.add(classDeclarationTranslator.getDeclarationsStatement()); - return result; + statements.add(classDeclarationTranslator.getDeclarationsStatement()); } - @NotNull - private List namespacesDeclarations() { - List result = Lists.newArrayList(); + private void namespacesDeclarations(List statements) { List namespaceTranslators = getTranslatorsForNonEmptyNamespaces(); - result.addAll(declarationStatements(namespaceTranslators, context())); - result.addAll(initializeStatements(namespaceTranslators)); - return result; + statements.addAll(declarationStatements(namespaceTranslators, context())); + statements.addAll(initializeStatements()); } @NotNull @@ -121,7 +117,7 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { } @NotNull - private List initializeStatements(@NotNull List namespaceTranslators) { + private List initializeStatements() { List result = Lists.newArrayList(); for (NamespaceDescriptor descriptor : filterNonEmptyNamespaces(namespaceDescriptors)) { JsNameRef initializeMethodReference = Namer.initializeMethodReference(); @@ -144,10 +140,10 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { } @NotNull - private static List filterNonEmptyNamespaces(@NotNull List namespaceDescriptors) { + private List filterNonEmptyNamespaces(@NotNull List namespaceDescriptors) { List result = Lists.newArrayList(); for (NamespaceDescriptor descriptor : namespaceDescriptors) { - if (!JsDescriptorUtils.isNamespaceEmpty(descriptor)) { + if (!JsDescriptorUtils.isNamespaceEmpty(descriptor, context().bindingContext())) { result.add(descriptor); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java index 8c81898db1d..f72784bcfd3 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java @@ -128,7 +128,7 @@ public final class NamespaceTranslator extends AbstractTranslator { return Collections.emptyList(); } List result = Lists.newArrayList(); - List nestedNamespaces = JsDescriptorUtils.getNestedNamespaces(descriptor); + List nestedNamespaces = JsDescriptorUtils.getNestedNamespaces(descriptor, context().bindingContext()); for (NamespaceDescriptor nestedNamespace : nestedNamespaces) { NamespaceTranslator nestedNamespaceTranslator = new NamespaceTranslator(nestedNamespace, classDeclarationTranslator, context()); result.add(nestedNamespaceTranslator.getDeclarationAsInitializer()); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index 063b8724b0c..a5e0f1de3b2 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -110,7 +110,7 @@ public final class BindingUtils { public static List getDeclarationsForNamespace(@NotNull BindingContext bindingContext, @NotNull NamespaceDescriptor namespace) { List declarations = new ArrayList(); - for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespace)) { + for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespace, bindingContext)) { if (descriptor instanceof NamespaceDescriptor) { continue; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java index 59860ed1ea6..2c488397016 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java @@ -17,14 +17,19 @@ package org.jetbrains.k2js.translate.utils; import com.google.common.collect.Lists; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.expressions.OperatorConventions; +import org.jetbrains.k2js.config.LibrarySourcesConfig; import org.jetbrains.k2js.translate.context.Namer; import java.util.ArrayList; @@ -193,22 +198,24 @@ public final class JsDescriptorUtils { } @NotNull - public static List getAllClassesDefinedInNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { + public static List getAllClassesDefinedInNamespace(@NotNull NamespaceDescriptor namespaceDescriptor, + @NotNull BindingContext context) { List classDescriptors = Lists.newArrayList(); - for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) { + for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor, context)) { if (descriptor instanceof ClassDescriptor) { - classDescriptors.add((ClassDescriptor)descriptor); + classDescriptors.add((ClassDescriptor) descriptor); } } return classDescriptors; } @NotNull - public static List getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor) { + public static List getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor, + @NotNull BindingContext context) { List result = Lists.newArrayList(); - for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) { + for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor, context)) { if (descriptor instanceof NamespaceDescriptor) { - result.add((NamespaceDescriptor)descriptor); + result.add((NamespaceDescriptor) descriptor); } } return result; @@ -227,22 +234,29 @@ public final class JsDescriptorUtils { } @NotNull - public static List getContainedDescriptorsWhichAreNotPredefined(@NotNull NamespaceDescriptor namespace) { + public static List getContainedDescriptorsWhichAreNotPredefined(@NotNull NamespaceDescriptor namespace, + @NotNull BindingContext context) { List result = Lists.newArrayList(); for (DeclarationDescriptor descriptor : namespace.getMemberScope().getAllDescriptors()) { if (!AnnotationsUtils.isPredefinedObject(descriptor)) { - result.add(descriptor); + PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(context, descriptor); + if (psiElement != null) { + PsiFile file = psiElement.getContainingFile(); + if (file.getUserData(LibrarySourcesConfig.EXTERNAL_LIB) == null) { + result.add(descriptor); + } + } } } return result; } //TODO: at the moment this check is very ineffective - public static boolean isNamespaceEmpty(@NotNull NamespaceDescriptor namespace) { - List containedDescriptors = getContainedDescriptorsWhichAreNotPredefined(namespace); + public static boolean isNamespaceEmpty(@NotNull NamespaceDescriptor namespace, @NotNull BindingContext context) { + List containedDescriptors = getContainedDescriptorsWhichAreNotPredefined(namespace, context); for (DeclarationDescriptor descriptor : containedDescriptors) { if (descriptor instanceof NamespaceDescriptor) { - if (!isNamespaceEmpty((NamespaceDescriptor)descriptor)) { + if (!isNamespaceEmpty((NamespaceDescriptor) descriptor, context)) { return false; } } diff --git a/js/js.translator/testFiles/kotlin_lib.js b/js/js.translator/testFiles/kotlin_lib.js index 9d929114313..6a16d9011aa 100644 --- a/js/js.translator/testFiles/kotlin_lib.js +++ b/js/js.translator/testFiles/kotlin_lib.js @@ -14,6 +14,11 @@ * limitations under the License. */ +// todo org.jetbrains.k2js.test.semantics.WebDemoExamples2Test#testBuilder +var kotlin = {set:function (receiver, key, value) { + return receiver.put(key, value); +}}; + (function () { "use strict";