KT-2298 js inter-module communication
This commit is contained in:
@@ -22,6 +22,7 @@ import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import jet.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -40,6 +41,7 @@ import org.jetbrains.k2js.config.*;
|
||||
import org.jetbrains.k2js.facade.K2JSTranslator;
|
||||
import org.jetbrains.k2js.facade.MainCallParameters;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
|
||||
@@ -101,7 +103,6 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments, K2JSCompile
|
||||
return ExitCode.INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
MainCallParameters mainCallParameters = arguments.createMainCallParameters();
|
||||
return translateAndGenerateOutputFile(mainCallParameters, messageCollector, environmentForJS, config, outputFile);
|
||||
}
|
||||
@@ -151,10 +152,11 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments, K2JSCompile
|
||||
@NotNull
|
||||
private static Config getConfig(@NotNull K2JSCompilerArguments arguments, @NotNull Project project) {
|
||||
EcmaVersion ecmaVersion = EcmaVersion.fromString(arguments.target);
|
||||
String moduleId = FileUtil.getNameWithoutExtension(new File(arguments.outputFile));
|
||||
if (arguments.libraryFiles == null) {
|
||||
// lets discover the JS library definitions on the classpath
|
||||
return new ClassPathLibraryDefintionsConfig(project, ecmaVersion);
|
||||
return new ClassPathLibraryDefintionsConfig(project, moduleId, ecmaVersion);
|
||||
}
|
||||
return new LibrarySourcesConfig(project, arguments.libraryFiles, ecmaVersion);
|
||||
return new LibrarySourcesConfig(project, moduleId, arguments.libraryFiles, ecmaVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,10 +174,13 @@ public final class K2JSCompiler implements TranslatingCompiler {
|
||||
THashSet<Module> modules = new THashSet<Module>();
|
||||
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(',');
|
||||
for (Module dependency : modules) {
|
||||
sb.append('@').append(dependency.getName()).append(',');
|
||||
VirtualFile[] files = CompilerManager.getInstance(module.getProject()).createModuleCompileScope(dependency, false)
|
||||
.getFiles(JetFileType.INSTANCE, true);
|
||||
for (VirtualFile file : files) {
|
||||
sb.append(file.getPath()).append(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,6 @@ import static org.jetbrains.jet.plugin.project.JsModuleDetector.getLibLocationAn
|
||||
*/
|
||||
public final class IDEAConfig extends LibrarySourcesConfig {
|
||||
public IDEAConfig(@NotNull Project project) {
|
||||
super(project, getLibLocationAndTargetForProject(project).first, EcmaVersion.defaultVersion());
|
||||
super(project, "default", getLibLocationAndTargetForProject(project).first, EcmaVersion.defaultVersion());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
|
||||
runFunctionOutputTest(EcmaVersion.all(), kotlinFilename, namespaceName, functionName, expectedResult);
|
||||
}
|
||||
|
||||
protected void runFunctionOutputTest(@NotNull EnumSet<EcmaVersion> ecmaVersions, @NotNull String kotlinFilename,
|
||||
protected void runFunctionOutputTest(@NotNull Iterable<EcmaVersion> ecmaVersions, @NotNull String kotlinFilename,
|
||||
@NotNull String namespaceName,
|
||||
@NotNull String functionName,
|
||||
@NotNull Object expectedResult) throws Exception {
|
||||
@@ -50,7 +50,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
|
||||
runRhinoTests(kotlinFilename, ecmaVersions, new RhinoFunctionResultChecker(namespaceName, functionName, expectedResult));
|
||||
}
|
||||
|
||||
public void checkFooBoxIsTrue(@NotNull String filename, @NotNull EnumSet<EcmaVersion> ecmaVersions) throws Exception {
|
||||
public void checkFooBoxIsTrue(@NotNull String filename, @NotNull Iterable<EcmaVersion> ecmaVersions) throws Exception {
|
||||
runFunctionOutputTest(ecmaVersions, filename, "foo", "box", true);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
|
||||
checkFooBoxIsTrue(getTestName(true) + ".kt", EcmaVersion.all());
|
||||
}
|
||||
|
||||
protected void fooBoxTest(@NotNull EnumSet<EcmaVersion> ecmaVersions) throws Exception {
|
||||
protected void fooBoxTest(@NotNull Iterable<EcmaVersion> ecmaVersions) throws Exception {
|
||||
checkFooBoxIsTrue(getTestName(true) + ".kt", ecmaVersions);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
|
||||
runRhinoTests(kotlinFilename, ecmaVersions, new RhinoSystemOutputChecker(expectedResult));
|
||||
}
|
||||
|
||||
protected void performTestWithMain(@NotNull EnumSet<EcmaVersion> ecmaVersions,
|
||||
protected void performTestWithMain(@NotNull Iterable<EcmaVersion> ecmaVersions,
|
||||
@NotNull String testName,
|
||||
@NotNull String testId,
|
||||
@NotNull String... args) throws Exception {
|
||||
|
||||
@@ -41,7 +41,7 @@ public final class TestConfig extends Config {
|
||||
private /*var*/ List<JetFile> jsLibFiles = null;
|
||||
|
||||
public TestConfig(@NotNull Project project, @NotNull EcmaVersion version) {
|
||||
super(project, version);
|
||||
super(project, "main", version);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -39,11 +39,6 @@ class RhinoFunctionManager {
|
||||
this.functionName = functionName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFunctionName() {
|
||||
return functionName;
|
||||
}
|
||||
|
||||
private Script compileScript(int optimizationLevel) {
|
||||
long startNano = System.nanoTime();
|
||||
Context context = Context.enter();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.k2js.test.rhino;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.k2js.translate.context.Namer;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
@@ -59,10 +60,14 @@ public class RhinoFunctionResultChecker implements RhinoResultChecker {
|
||||
}
|
||||
|
||||
private String functionCallString() {
|
||||
String result = functionName + "()";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (namespaceName != null) {
|
||||
result = "Kotlin.defs." + namespaceName + "." + result;
|
||||
sb.append("Kotlin.modules.main");
|
||||
if (namespaceName != Namer.getRootNamespaceName()) {
|
||||
sb.append('.').append(namespaceName);
|
||||
}
|
||||
sb.append('.');
|
||||
}
|
||||
return result;
|
||||
return sb.append(functionName).append("()").toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.k2js.test.BasicTest;
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -49,12 +48,7 @@ public final class RhinoUtils {
|
||||
new Supplier<String>() {
|
||||
@Override
|
||||
public String get() {
|
||||
try {
|
||||
return FileUtil.loadFile(new File(BasicTest.JSLINT_LIB));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return fileToString(BasicTest.JSLINT_LIB);
|
||||
}
|
||||
},
|
||||
"JSLINT"
|
||||
@@ -64,15 +58,19 @@ public final class RhinoUtils {
|
||||
|
||||
}
|
||||
|
||||
private static String fileToString(String file) {
|
||||
try {
|
||||
return FileUtil.loadFile(new File(file));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void runFileWithRhino(@NotNull String inputFile,
|
||||
@NotNull Context context,
|
||||
@NotNull Scriptable scope) throws Exception {
|
||||
FileReader reader = new FileReader(inputFile);
|
||||
try {
|
||||
context.evaluateReader(scope, reader, inputFile, 1, null);
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
context.evaluateString(scope, fileToString(inputFile), inputFile, 1, null);
|
||||
}
|
||||
|
||||
public static void runRhinoTest(@NotNull List<String> fileNames,
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.k2js.analyze;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -39,10 +38,10 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.k2js.config.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
@@ -125,7 +124,7 @@ public final class AnalyzerFacadeForJS {
|
||||
|
||||
@NotNull
|
||||
public static Collection<JetFile> withJsLibAdded(@NotNull Collection<JetFile> files, @NotNull Config config) {
|
||||
Set<JetFile> allFiles = Sets.newHashSet();
|
||||
Collection<JetFile> allFiles = new ArrayList<JetFile>();
|
||||
allFiles.addAll(files);
|
||||
allFiles.addAll(config.getLibFiles());
|
||||
return allFiles;
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ import java.util.*;
|
||||
public class ClassPathLibraryDefintionsConfig extends Config {
|
||||
public static final String META_INF_SERVICES_FILE = "META-INF/services/org.jetbrains.kotlin.js.libraryDefinitions";
|
||||
|
||||
public ClassPathLibraryDefintionsConfig(@NotNull Project project, @NotNull EcmaVersion version) {
|
||||
super(project, version);
|
||||
public ClassPathLibraryDefintionsConfig(@NotNull Project project, @NotNull String moduleId, @NotNull EcmaVersion version) {
|
||||
super(project, moduleId, version);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -34,7 +34,7 @@ public abstract class Config {
|
||||
|
||||
@NotNull
|
||||
public static Config getEmptyConfig(@NotNull Project project, @NotNull EcmaVersion ecmaVersion) {
|
||||
return new Config(project, ecmaVersion) {
|
||||
return new Config(project, "main", ecmaVersion) {
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<JetFile> generateLibFiles() {
|
||||
@@ -117,9 +117,13 @@ public abstract class Config {
|
||||
@NotNull
|
||||
private final EcmaVersion target;
|
||||
|
||||
public Config(@NotNull Project project, @NotNull EcmaVersion ecmaVersion) {
|
||||
@NotNull
|
||||
private final String moduleId;
|
||||
|
||||
public Config(@NotNull Project project, @NotNull String moduleId, @NotNull EcmaVersion ecmaVersion) {
|
||||
this.project = project;
|
||||
this.target = ecmaVersion;
|
||||
this.moduleId = moduleId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -132,6 +136,11 @@ public abstract class Config {
|
||||
return target;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getModuleId() {
|
||||
return moduleId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract List<JetFile> generateLibFiles();
|
||||
|
||||
|
||||
@@ -39,13 +39,17 @@ import java.util.zip.ZipFile;
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public class LibrarySourcesConfig extends Config {
|
||||
public static final Key<Boolean> EXTERNAL_LIB = new Key<Boolean>("externalLib");
|
||||
public static final Key<String> EXTERNAL_MODULE_NAME = new Key<String>("externalModule");
|
||||
public static final String UNKNOWN_EXTERNAL_MODULE_NAME = "<unknown>";
|
||||
|
||||
@Nullable
|
||||
private final String[] files;
|
||||
|
||||
public LibrarySourcesConfig(@NotNull Project project, @Nullable String[] files, @NotNull EcmaVersion ecmaVersion) {
|
||||
super(project, ecmaVersion);
|
||||
public LibrarySourcesConfig(@NotNull Project project,
|
||||
@NotNull String moduleId,
|
||||
@Nullable String[] files,
|
||||
@NotNull EcmaVersion ecmaVersion) {
|
||||
super(project, moduleId, ecmaVersion);
|
||||
this.files = files;
|
||||
}
|
||||
|
||||
@@ -57,16 +61,22 @@ public class LibrarySourcesConfig extends Config {
|
||||
}
|
||||
|
||||
List<JetFile> jetFiles = new ArrayList<JetFile>();
|
||||
String moduleName = UNKNOWN_EXTERNAL_MODULE_NAME;
|
||||
for (String path : files) {
|
||||
File file = new File(path);
|
||||
try {
|
||||
String name = file.getName();
|
||||
if (path.charAt(0) == '@') {
|
||||
moduleName = path.substring(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
psiFile.putUserData(EXTERNAL_MODULE_NAME, moduleName);
|
||||
jetFiles.add(psiFile);
|
||||
}
|
||||
}
|
||||
@@ -98,7 +108,7 @@ public class LibrarySourcesConfig 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);
|
||||
jetFile.putUserData(EXTERNAL_MODULE_NAME, UNKNOWN_EXTERNAL_MODULE_NAME);
|
||||
result.add(jetFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.jetbrains.k2js.utils.JetFileUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.facade.FacadeUtils.parseString;
|
||||
@@ -96,7 +95,7 @@ public final class K2JSTranslator {
|
||||
throws TranslationException {
|
||||
JetStandardLibrary.initialize(config.getProject());
|
||||
BindingContext bindingContext = AnalyzerFacadeForJS.analyzeFilesAndCheckErrors(filesToTranslate, config);
|
||||
return Translation.generateAst(bindingContext, filesToTranslate, mainCallParameters, config.getTarget(), rawStatements);
|
||||
return Translation.generateAst(bindingContext, filesToTranslate, mainCallParameters, config, rawStatements);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -32,14 +32,13 @@ public final class Namer {
|
||||
private static final String INITIALIZE_METHOD_NAME = "initialize";
|
||||
private static final String CLASS_OBJECT_NAME = "createClass";
|
||||
private static final String TRAIT_OBJECT_NAME = "createTrait";
|
||||
private static final String NAMESPACE_OBJECT_NAME = "createNamespace";
|
||||
private static final String OBJECT_OBJECT_NAME = "createObject";
|
||||
private static final String SETTER_PREFIX = "set_";
|
||||
private static final String GETTER_PREFIX = "get_";
|
||||
private static final String BACKING_FIELD_PREFIX = "$";
|
||||
private static final String SUPER_METHOD_NAME = "super_init";
|
||||
private static final String KOTLIN_OBJECT_NAME = "Kotlin";
|
||||
private static final String ROOT_NAMESPACE = "Root";
|
||||
private static final String ROOT_NAMESPACE = "_";
|
||||
private static final String RECEIVER_PARAMETER_NAME = "receiver";
|
||||
private static final String CLASSES_OBJECT_NAME = "classes";
|
||||
private static final String THROW_NPE_FUN_NAME = "throwNPE";
|
||||
@@ -112,7 +111,7 @@ public final class Namer {
|
||||
@NotNull
|
||||
private final JsName traitName;
|
||||
@NotNull
|
||||
private final JsName namespaceName;
|
||||
private final JsExpression definePackage;
|
||||
@NotNull
|
||||
private final JsName objectName;
|
||||
|
||||
@@ -129,7 +128,9 @@ public final class Namer {
|
||||
kotlinName = rootScope.declareName(KOTLIN_OBJECT_NAME);
|
||||
kotlinScope = new JsScope(rootScope, "Kotlin standard object");
|
||||
traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
|
||||
namespaceName = kotlinScope.declareName(NAMESPACE_OBJECT_NAME);
|
||||
|
||||
definePackage = kotlin("definePackage");
|
||||
|
||||
className = kotlinScope.declareName(CLASS_OBJECT_NAME);
|
||||
objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
|
||||
|
||||
@@ -151,8 +152,8 @@ public final class Namer {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression namespaceCreationMethodReference() {
|
||||
return kotlin(namespaceName);
|
||||
public JsExpression packageDefinitionMethodReference() {
|
||||
return definePackage;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -169,14 +170,17 @@ public final class Namer {
|
||||
|
||||
@NotNull
|
||||
private JsExpression kotlin(@NotNull JsName name) {
|
||||
JsNameRef reference = name.makeRef();
|
||||
reference.setQualifier(kotlinName.makeRef());
|
||||
return reference;
|
||||
return kotlin(name.makeRef());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression kotlin(@NotNull String name) {
|
||||
return kotlin(kotlinScope.declareName(name));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression kotlin(@NotNull JsExpression reference) {
|
||||
setQualifier(reference, kotlinName.makeRef());
|
||||
setQualifier(reference, kotlinObject());
|
||||
return reference;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,13 +18,17 @@ package org.jetbrains.k2js.translate.context;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
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.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.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
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.Rule;
|
||||
import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
|
||||
@@ -105,6 +109,11 @@ public final class StaticContext {
|
||||
return ecmaVersion == EcmaVersion.v5;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public EcmaVersion getEcmaVersion() {
|
||||
return ecmaVersion;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsProgram getProgram() {
|
||||
return program;
|
||||
@@ -179,8 +188,16 @@ public final class StaticContext {
|
||||
if (!(descriptor instanceof NamespaceDescriptor)) {
|
||||
return null;
|
||||
}
|
||||
String nameForNamespace = getNameForNamespace((NamespaceDescriptor) descriptor);
|
||||
return getRootScope().declareUnobfuscatableName(nameForNamespace);
|
||||
|
||||
String name;
|
||||
if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) {
|
||||
name = Namer.getRootNamespaceName();
|
||||
}
|
||||
else {
|
||||
name = descriptor.getName().getName();
|
||||
}
|
||||
|
||||
return getRootScope().declareUnobfuscatableName(name);
|
||||
}
|
||||
};
|
||||
Rule<JsName> memberDeclarationsInsideParentsScope = new Rule<JsName>() {
|
||||
@@ -385,14 +402,50 @@ public final class StaticContext {
|
||||
Rule<JsNameRef> namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule<JsNameRef>() {
|
||||
@Override
|
||||
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
|
||||
DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor);
|
||||
if (!(containingDeclaration instanceof NamespaceDescriptor)) {
|
||||
DeclarationDescriptor containingDescriptor = getContainingDeclaration(descriptor);
|
||||
if (!(containingDescriptor instanceof NamespaceDescriptor)) {
|
||||
return null;
|
||||
}
|
||||
JsName containingDeclarationName = getNameForDescriptor(containingDeclaration);
|
||||
JsNameRef qualifier = containingDeclarationName.makeRef();
|
||||
qualifier.setQualifier(getQualifierForDescriptor(containingDeclaration));
|
||||
return qualifier;
|
||||
|
||||
final JsNameRef result = new JsNameRef(getNameForDescriptor(containingDescriptor));
|
||||
if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) containingDescriptor)) {
|
||||
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>() {
|
||||
@@ -448,10 +501,7 @@ public final class StaticContext {
|
||||
Rule<Boolean> topLevelNamespaceHaveNoQualifier = new Rule<Boolean>() {
|
||||
@Override
|
||||
public Boolean apply(@NotNull DeclarationDescriptor descriptor) {
|
||||
if (!(descriptor instanceof NamespaceDescriptor)) {
|
||||
return null;
|
||||
}
|
||||
if (DescriptorUtils.isTopLevelNamespace((NamespaceDescriptor) descriptor)) {
|
||||
if (descriptor instanceof NamespaceDescriptor && DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) {
|
||||
return true;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.k2js.config.EcmaVersion;
|
||||
import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -58,6 +59,10 @@ public final class TranslationContext {
|
||||
return staticContext.isEcma5();
|
||||
}
|
||||
|
||||
public boolean isNotEcma3() {
|
||||
return staticContext.getEcmaVersion() != EcmaVersion.v3;
|
||||
}
|
||||
|
||||
private TranslationContext(@NotNull StaticContext staticContext,
|
||||
@NotNull DynamicContext dynamicContext,
|
||||
@NotNull AliasingContext context) {
|
||||
|
||||
+11
-14
@@ -18,13 +18,11 @@ package org.jetbrains.k2js.translate.declaration;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.k2js.translate.context.Namer;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
@@ -32,12 +30,12 @@ import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.k2js.translate.general.Translation;
|
||||
import org.jetbrains.k2js.translate.utils.BindingUtils;
|
||||
import org.jetbrains.k2js.translate.utils.ClassSortingUtils;
|
||||
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
|
||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getAllClassesDefinedInNamespace;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
@@ -142,18 +140,17 @@ public final class ClassDeclarationTranslator extends AbstractTranslator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JsPropertyInitializer> classDeclarationsForNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
|
||||
List<JsPropertyInitializer> result = Lists.newArrayList();
|
||||
for (ClassDescriptor classDescriptor : getAllClassesDefinedInNamespace(namespaceDescriptor, bindingContext())) {
|
||||
result.add(getClassNameToClassObject(classDescriptor));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsPropertyInitializer getClassNameToClassObject(@NotNull ClassDescriptor classDescriptor) {
|
||||
public JsPropertyInitializer getClassNameToClassObject(@NotNull ClassDescriptor classDescriptor) {
|
||||
JsName className = context().getNameForDescriptor(classDescriptor);
|
||||
JsNameRef alreadyDefinedClassReference = qualified(className, getDeclarationsObjectName().makeRef());
|
||||
return new JsPropertyInitializer(className.makeRef(), alreadyDefinedClassReference);
|
||||
JsExpression value;
|
||||
if (context().isEcma5()) {
|
||||
value = JsAstUtils.createDataDescriptor(alreadyDefinedClassReference, false, context());
|
||||
}
|
||||
else {
|
||||
value = alreadyDefinedClassReference;
|
||||
}
|
||||
|
||||
return new JsPropertyInitializer(className.makeRef(), value);
|
||||
}
|
||||
}
|
||||
|
||||
+20
-2
@@ -19,6 +19,8 @@ package org.jetbrains.k2js.translate.declaration;
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
@@ -39,6 +41,17 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPropertyInitializer>> {
|
||||
@Nullable
|
||||
private final ClassDeclarationTranslator classDeclarationTranslator;
|
||||
|
||||
public DeclarationBodyVisitor() {
|
||||
classDeclarationTranslator = null;
|
||||
}
|
||||
|
||||
public DeclarationBodyVisitor(ClassDeclarationTranslator classDeclarationTranslator) {
|
||||
this.classDeclarationTranslator = classDeclarationTranslator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JsPropertyInitializer> traverseClass(@NotNull JetClassOrObject jetClass,
|
||||
@NotNull TranslationContext context) {
|
||||
@@ -51,7 +64,7 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPrope
|
||||
|
||||
@NotNull
|
||||
public List<JsPropertyInitializer> traverseNamespace(@NotNull NamespaceDescriptor namespace,
|
||||
@NotNull TranslationContext context) {
|
||||
@NotNull TranslationContext context) {
|
||||
List<JsPropertyInitializer> properties = new ArrayList<JsPropertyInitializer>();
|
||||
for (JetDeclaration declaration : getDeclarationsForNamespace(context.bindingContext(), namespace)) {
|
||||
properties.addAll(declaration.accept(this, context));
|
||||
@@ -62,7 +75,12 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPrope
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JsPropertyInitializer> visitClass(@NotNull JetClass expression, @NotNull TranslationContext context) {
|
||||
return Collections.emptyList();
|
||||
if (classDeclarationTranslator == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
ClassDescriptor classDescriptor = getClassDescriptor(context.bindingContext(), expression);
|
||||
return Collections.singletonList(classDeclarationTranslator.getClassNameToClassObject(classDescriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+23
-29
@@ -24,12 +24,10 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.k2js.translate.context.Namer;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
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;
|
||||
@@ -37,7 +35,6 @@ import java.util.Set;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getAllNonNativeNamespaceDescriptors;
|
||||
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getAllClassesDefinedInNamespace;
|
||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
@@ -85,8 +82,8 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
|
||||
|
||||
private void namespacesDeclarations(List<JsStatement> statements) {
|
||||
List<NamespaceTranslator> namespaceTranslators = getTranslatorsForNonEmptyNamespaces();
|
||||
statements.addAll(declarationStatements(namespaceTranslators, context()));
|
||||
statements.addAll(initializeStatements());
|
||||
declarationStatements(namespaceTranslators, statements);
|
||||
initializeStatements(namespaceTranslators, statements);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -98,34 +95,31 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
|
||||
return namespaceTranslators;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<JsStatement> declarationStatements(@NotNull List<NamespaceTranslator> namespaceTranslators, TranslationContext context) {
|
||||
List<JsStatement> result = Lists.newArrayList();
|
||||
|
||||
JsNameRef defs = JsAstUtils.qualified(context.jsScope().declareName("defs"), context.namer().kotlinObject());
|
||||
for (NamespaceTranslator translator : namespaceTranslators) {
|
||||
JsVars vars = translator.getDeclarationAsVar();
|
||||
|
||||
JsVars.JsVar var = vars.iterator().next();
|
||||
JsNameRef ref = new JsNameRef(var.getName());
|
||||
ref.setQualifier(defs);
|
||||
|
||||
result.add(vars);
|
||||
result.add(JsAstUtils.assignment(ref, new JsNameRef(var.getName())).makeStmt());
|
||||
private void declarationStatements(@NotNull List<NamespaceTranslator> namespaceTranslators,
|
||||
@NotNull List<JsStatement> statements) {
|
||||
JsObjectLiteral objectLiteral = new JsObjectLiteral();
|
||||
JsNameRef packageMapNameRef = context().jsScope().declareName("_").makeRef();
|
||||
JsExpression packageMapValue;
|
||||
if (context().isNotEcma3()) {
|
||||
packageMapValue = AstUtil.newInvocation(JsAstUtils.CREATE_OBJECT, context().program().getNullLiteral(), objectLiteral);
|
||||
}
|
||||
else {
|
||||
packageMapValue = objectLiteral;
|
||||
}
|
||||
statements.add(JsAstUtils.newVar(packageMapNameRef.getName(), packageMapValue));
|
||||
|
||||
for (NamespaceTranslator translator : namespaceTranslators) {
|
||||
translator.addNamespaceDeclaration(objectLiteral.getPropertyInitializers());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<JsStatement> initializeStatements() {
|
||||
List<JsStatement> result = Lists.newArrayList();
|
||||
for (NamespaceDescriptor descriptor : filterNonEmptyNamespaces(namespaceDescriptors)) {
|
||||
JsNameRef initializeMethodReference = Namer.initializeMethodReference();
|
||||
JsNameRef fqNamespaceNameRef = TranslationUtils.getQualifiedReference(context(), descriptor);
|
||||
setQualifier(initializeMethodReference, fqNamespaceNameRef);
|
||||
result.add(AstUtil.newInvocation(initializeMethodReference).makeStmt());
|
||||
private static void initializeStatements(@NotNull List<NamespaceTranslator> namespaceTranslators,
|
||||
@NotNull List<JsStatement> statements) {
|
||||
for (NamespaceTranslator translator : namespaceTranslators) {
|
||||
for (JsExpression expression : translator.getInitializers()) {
|
||||
statements.add(expression.makeStmt());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+47
-44
@@ -25,15 +25,14 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.k2js.translate.general.Translation;
|
||||
import org.jetbrains.k2js.translate.initializer.InitializerUtils;
|
||||
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.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newObjectLiteral;
|
||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newVar;
|
||||
|
||||
/**
|
||||
* @author Pavel.Talanov
|
||||
@@ -49,6 +48,9 @@ public final class NamespaceTranslator extends AbstractTranslator {
|
||||
@NotNull
|
||||
private final ClassDeclarationTranslator classDeclarationTranslator;
|
||||
|
||||
@NotNull
|
||||
private final List<JsExpression> initializers = new ArrayList<JsExpression>();
|
||||
|
||||
/*package*/ NamespaceTranslator(@NotNull NamespaceDescriptor descriptor,
|
||||
@NotNull ClassDeclarationTranslator classDeclarationTranslator,
|
||||
@NotNull TranslationContext context) {
|
||||
@@ -58,80 +60,81 @@ public final class NamespaceTranslator extends AbstractTranslator {
|
||||
this.classDeclarationTranslator = classDeclarationTranslator;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public JsVars getDeclarationAsVar() {
|
||||
return newVar(namespaceName, getNamespaceDeclaration());
|
||||
public List<JsExpression> getInitializers() {
|
||||
return initializers;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsPropertyInitializer getDeclarationAsInitializer() {
|
||||
addNamespaceInitializer();
|
||||
return new JsPropertyInitializer(namespaceName.makeRef(), getNamespaceDeclaration());
|
||||
}
|
||||
|
||||
public void addNamespaceDeclaration(List<JsPropertyInitializer> list) {
|
||||
addNamespaceInitializer();
|
||||
|
||||
if (DescriptorUtils.isRootNamespace(descriptor)) {
|
||||
list.addAll(getFunctionsAndClasses());
|
||||
return;
|
||||
}
|
||||
|
||||
JsExpression value = getNamespaceDeclaration();
|
||||
if (context().isNotEcma3()) {
|
||||
value = JsAstUtils.createDataDescriptor(value, false, context());
|
||||
}
|
||||
|
||||
list.add(new JsPropertyInitializer(namespaceName.makeRef(), value));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsInvocation getNamespaceDeclaration() {
|
||||
JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation();
|
||||
addNamespaceInitializersAndProperties(namespaceDeclaration);
|
||||
namespaceDeclaration.getArguments().add(getClassesAndNestedNamespaces());
|
||||
addIfNeed(getFunctionsAndClasses(), namespaceDeclaration.getArguments());
|
||||
addIfNeed(getNestedNamespaceDeclarations(), namespaceDeclaration.getArguments());
|
||||
return namespaceDeclaration;
|
||||
}
|
||||
|
||||
private void addNamespaceInitializersAndProperties(@NotNull JsInvocation namespaceDeclaration) {
|
||||
private void addNamespaceInitializer() {
|
||||
JsFunction initializer = Translation.generateNamespaceInitializerMethod(descriptor, context());
|
||||
List<JsPropertyInitializer> properties = new DeclarationBodyVisitor().traverseNamespace(descriptor, context());
|
||||
if (context().isEcma5()) {
|
||||
addEcma5InitializersAndProperties(namespaceDeclaration.getArguments(), initializer, properties);
|
||||
}
|
||||
else {
|
||||
addEcma3InitializersAndProperties(namespaceDeclaration, initializer, properties);
|
||||
if (!initializer.getBody().getStatements().isEmpty()) {
|
||||
JsNameRef call = new JsNameRef("call");
|
||||
call.setQualifier(initializer);
|
||||
JsInvocation invocation = new JsInvocation();
|
||||
invocation.setQualifier(call);
|
||||
invocation.getArguments().add(TranslationUtils.getQualifiedReference(context(), descriptor));
|
||||
initializers.add(invocation);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addEcma3InitializersAndProperties(@NotNull JsInvocation namespaceDeclaration,
|
||||
@NotNull JsFunction initializer,
|
||||
@NotNull List<JsPropertyInitializer> properties) {
|
||||
List<JsPropertyInitializer> propertyList = new ArrayList<JsPropertyInitializer>();
|
||||
propertyList.add(InitializerUtils.generateInitializeMethod(initializer));
|
||||
propertyList.addAll(properties);
|
||||
namespaceDeclaration.getArguments().add(newObjectLiteral(propertyList));
|
||||
}
|
||||
|
||||
private void addEcma5InitializersAndProperties(@NotNull List<JsExpression> expressions,
|
||||
@NotNull JsFunction initializer,
|
||||
@NotNull List<JsPropertyInitializer> properties) {
|
||||
expressions.add(initializer.getBody().getStatements().isEmpty() ? context().program().getNullLiteral() : initializer);
|
||||
expressions.add(properties.isEmpty() ? context().program().getNullLiteral() : newObjectLiteral(properties));
|
||||
private List<JsPropertyInitializer> getFunctionsAndClasses() {
|
||||
return new DeclarationBodyVisitor(classDeclarationTranslator).traverseNamespace(descriptor, context());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsInvocation namespaceCreateMethodInvocation() {
|
||||
return AstUtil.newInvocation(context().namer().namespaceCreationMethodReference());
|
||||
return AstUtil.newInvocation(context().namer().packageDefinitionMethodReference());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsObjectLiteral getClassesAndNestedNamespaces() {
|
||||
JsObjectLiteral classesAndNestedNamespaces = new JsObjectLiteral();
|
||||
classesAndNestedNamespaces.getPropertyInitializers().addAll(getClassesDefined());
|
||||
classesAndNestedNamespaces.getPropertyInitializers().addAll(getNestedNamespaceDeclarations());
|
||||
return classesAndNestedNamespaces;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<JsPropertyInitializer> getClassesDefined() {
|
||||
return classDeclarationTranslator.classDeclarationsForNamespace(descriptor);
|
||||
private void addIfNeed(@NotNull List<JsPropertyInitializer> declarations, @NotNull List<JsExpression> expressions) {
|
||||
// ecma5 expects strict number of arguments, but ecma3 doesn't
|
||||
if (!declarations.isEmpty()) {
|
||||
expressions.add(newObjectLiteral(declarations));
|
||||
}
|
||||
else if (context().isNotEcma3()) {
|
||||
expressions.add(context().program().getNullLiteral());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<JsPropertyInitializer> getNestedNamespaceDeclarations() {
|
||||
if (DescriptorUtils.isRootNamespace(descriptor)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<JsPropertyInitializer> result = Lists.newArrayList();
|
||||
List<NamespaceDescriptor> nestedNamespaces = JsDescriptorUtils.getNestedNamespaces(descriptor, context().bindingContext());
|
||||
for (NamespaceDescriptor nestedNamespace : nestedNamespaces) {
|
||||
NamespaceTranslator nestedNamespaceTranslator = new NamespaceTranslator(nestedNamespace, classDeclarationTranslator, context());
|
||||
result.add(nestedNamespaceTranslator.getDeclarationAsInitializer());
|
||||
|
||||
initializers.addAll(nestedNamespaceTranslator.getInitializers());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.general;
|
||||
import com.google.dart.compiler.backend.js.JsNamer;
|
||||
import com.google.dart.compiler.backend.js.JsPrettyNamer;
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.util.AstUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
@@ -28,7 +29,7 @@ import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.k2js.config.EcmaVersion;
|
||||
import org.jetbrains.k2js.config.Config;
|
||||
import org.jetbrains.k2js.facade.MainCallParameters;
|
||||
import org.jetbrains.k2js.facade.exceptions.MainFunctionNotFoundException;
|
||||
import org.jetbrains.k2js.facade.exceptions.TranslationException;
|
||||
@@ -148,10 +149,10 @@ public final class Translation {
|
||||
@NotNull
|
||||
public static JsProgram generateAst(@NotNull BindingContext bindingContext,
|
||||
@NotNull List<JetFile> files, @NotNull MainCallParameters mainCallParameters,
|
||||
@NotNull EcmaVersion ecmaVersion, List<String> rawStatements)
|
||||
@NotNull Config config, List<String> rawStatements)
|
||||
throws TranslationException {
|
||||
try {
|
||||
return doGenerateAst(bindingContext, files, mainCallParameters, ecmaVersion, rawStatements);
|
||||
return doGenerateAst(bindingContext, files, mainCallParameters, config, rawStatements);
|
||||
}
|
||||
catch (UnsupportedOperationException e) {
|
||||
throw new UnsupportedFeatureException("Unsupported feature used.", e);
|
||||
@@ -164,10 +165,10 @@ public final class Translation {
|
||||
@NotNull
|
||||
private static JsProgram doGenerateAst(@NotNull BindingContext bindingContext, @NotNull List<JetFile> files,
|
||||
@NotNull MainCallParameters mainCallParameters,
|
||||
@NotNull EcmaVersion ecmaVersion, List<String> rawStatements) throws MainFunctionNotFoundException {
|
||||
@NotNull Config config, List<String> rawStatements) throws MainFunctionNotFoundException {
|
||||
//TODO: move some of the code somewhere
|
||||
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
|
||||
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, ecmaVersion);
|
||||
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, config.getTarget());
|
||||
JsProgram program = staticContext.getProgram();
|
||||
JsBlock block = program.getGlobalBlock();
|
||||
|
||||
@@ -177,6 +178,8 @@ public final class Translation {
|
||||
|
||||
TranslationContext context = TranslationContext.rootContext(staticContext);
|
||||
statements.addAll(translateFiles(files, context));
|
||||
defineModule(statements, context, config);
|
||||
|
||||
if (mainCallParameters.shouldBeGenerated()) {
|
||||
statements.add(generateCallToMain(context, files, mainCallParameters.arguments()));
|
||||
}
|
||||
@@ -186,6 +189,14 @@ public final class Translation {
|
||||
return context.program();
|
||||
}
|
||||
|
||||
private static void defineModule(@NotNull List<JsStatement> statements,
|
||||
@NotNull TranslationContext context,
|
||||
@NotNull Config config) {
|
||||
statements.add(AstUtil.newInvocation(context.namer().kotlin("defineModule"),
|
||||
context.program().getStringLiteral(config.getModuleId()),
|
||||
context.jsScope().declareName("_").makeRef()).makeStmt());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JsStatement generateCallToMain(@NotNull TranslationContext context, @NotNull List<JetFile> files,
|
||||
@NotNull List<String> arguments) throws MainFunctionNotFoundException {
|
||||
@@ -214,12 +225,12 @@ public final class Translation {
|
||||
JsAstUtils.setArguments(translatedCall, Collections.<JsExpression>singletonList(arrayLiteral));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static void generateTestCalls(@NotNull TranslationContext context,
|
||||
@NotNull List<JetFile> files,
|
||||
@NotNull JsBlock block,
|
||||
List<String> rawStatements) {
|
||||
ClassDescriptor lastClassDescriptor = null;
|
||||
boolean declaredVar = false;
|
||||
List<JetNamedFunction> functions = JetTestFunctionDetector.findTestFunctions(context.bindingContext(), files);
|
||||
for (JetNamedFunction function : functions) {
|
||||
FunctionDescriptor functionDescriptor = getFunctionDescriptor(context.bindingContext(), function);
|
||||
@@ -228,9 +239,16 @@ public final class Translation {
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||
String className = getQualifiedName(classDescriptor);
|
||||
if (lastClassDescriptor != classDescriptor) {
|
||||
lastClassDescriptor = classDescriptor;
|
||||
String prefix = "";
|
||||
if (!declaredVar) {
|
||||
prefix = "var ";
|
||||
declaredVar = true;
|
||||
}
|
||||
rawStatements.add(prefix + "_testCase = new Kotlin.main." + className + "();");
|
||||
}
|
||||
rawStatements.add("QUnit.test( \"" + className + "." + funName + "()\" , function() {");
|
||||
String prefix = " var ";
|
||||
rawStatements.add(prefix + "_testCase = new Kotlin.defs." + className + "();");
|
||||
//rawStatements.add(" expect(0);");
|
||||
rawStatements.add(" _testCase." + funName + "();");
|
||||
} else {
|
||||
|
||||
@@ -213,7 +213,7 @@ public final class CallTranslator extends AbstractTranslator {
|
||||
|
||||
@NotNull
|
||||
private JsInvocation generateCallMethodInvocation() {
|
||||
JsNameRef callMethodNameRef = AstUtil.newQualifiedNameRef("call");
|
||||
JsNameRef callMethodNameRef = new JsNameRef("call");
|
||||
JsInvocation callMethodInvocation = new JsInvocation();
|
||||
callMethodInvocation.setQualifier(callMethodNameRef);
|
||||
setQualifier(callMethodInvocation, callParameters.getFunctionReference());
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package org.jetbrains.k2js.translate.utils;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.OrderedSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -321,7 +321,7 @@ public final class BindingUtils {
|
||||
@NotNull
|
||||
public static Set<NamespaceDescriptor> getAllNonNativeNamespaceDescriptors(@NotNull BindingContext context,
|
||||
@NotNull List<JetFile> files) {
|
||||
Set<NamespaceDescriptor> descriptorSet = Sets.newHashSet();
|
||||
Set<NamespaceDescriptor> descriptorSet = new OrderedSet<NamespaceDescriptor>();
|
||||
for (JetFile file : files) {
|
||||
//TODO: can't be
|
||||
NamespaceDescriptor namespaceDescriptor = getNamespaceDescriptor(context, file);
|
||||
|
||||
@@ -33,11 +33,13 @@ import java.util.*;
|
||||
*/
|
||||
public final class JsAstUtils {
|
||||
private static final JsNameRef DEFINE_PROPERTY = new JsNameRef("defineProperty");
|
||||
public static final JsNameRef CREATE_OBJECT = new JsNameRef("create");
|
||||
private static final JsNameRef EMPTY_REF = new JsNameRef("");
|
||||
|
||||
static {
|
||||
JsNameRef globalObjectReference = new JsNameRef("Object");
|
||||
DEFINE_PROPERTY.setQualifier(globalObjectReference);
|
||||
CREATE_OBJECT.setQualifier(globalObjectReference);
|
||||
}
|
||||
|
||||
private JsAstUtils() {
|
||||
@@ -301,21 +303,26 @@ public final class JsAstUtils {
|
||||
return createPropertyDataDescriptor(descriptor.getModality().isOverridable(), descriptor, value, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsObjectLiteral createDataDescriptor(@NotNull JsExpression value, boolean writable, @NotNull TranslationContext context) {
|
||||
JsObjectLiteral dataDescriptor = new JsObjectLiteral();
|
||||
dataDescriptor.getPropertyInitializers().add(new JsPropertyInitializer(context.program().getStringLiteral("value"), value));
|
||||
if (writable) {
|
||||
dataDescriptor.getPropertyInitializers().add(context.namer().writablePropertyDescriptorField());
|
||||
}
|
||||
return dataDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JsObjectLiteral createPropertyDataDescriptor(boolean writable,
|
||||
@NotNull DeclarationDescriptor descriptor,
|
||||
@NotNull JsExpression value,
|
||||
@NotNull TranslationContext context) {
|
||||
JsObjectLiteral jsPropertyDescriptor = new JsObjectLiteral();
|
||||
List<JsPropertyInitializer> meta = jsPropertyDescriptor.getPropertyInitializers();
|
||||
meta.add(new JsPropertyInitializer(context.program().getStringLiteral("value"), value));
|
||||
if (writable) {
|
||||
meta.add(context.namer().writablePropertyDescriptorField());
|
||||
}
|
||||
JsObjectLiteral dataDescriptor = createDataDescriptor(value, writable, context);
|
||||
if (AnnotationsUtils.isEnumerable(descriptor)) {
|
||||
meta.add(context.namer().enumerablePropertyDescriptorField());
|
||||
dataDescriptor.getPropertyInitializers().add(context.namer().enumerablePropertyDescriptorField());
|
||||
}
|
||||
return jsPropertyDescriptor;
|
||||
return dataDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -30,7 +30,6 @@ 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;
|
||||
import java.util.Collection;
|
||||
@@ -145,16 +144,6 @@ public final class JsDescriptorUtils {
|
||||
return (functionDescriptor.getReceiverParameter().exists());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getNameForNamespace(@NotNull NamespaceDescriptor descriptor) {
|
||||
if (descriptor.getContainingDeclaration() instanceof ModuleDescriptor) {
|
||||
return Namer.getRootNamespaceName();
|
||||
}
|
||||
else {
|
||||
return descriptor.getName().getName();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: why callable descriptor
|
||||
@Nullable
|
||||
public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) {
|
||||
@@ -239,13 +228,18 @@ public final class JsDescriptorUtils {
|
||||
List<DeclarationDescriptor> result = Lists.newArrayList();
|
||||
for (DeclarationDescriptor descriptor : namespace.getMemberScope().getAllDescriptors()) {
|
||||
if (!AnnotationsUtils.isPredefinedObject(descriptor)) {
|
||||
PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(context, descriptor);
|
||||
if (psiElement != null) {
|
||||
PsiFile file = psiElement.getContainingFile();
|
||||
if (file.getUserData(LibrarySourcesConfig.EXTERNAL_LIB) == null) {
|
||||
result.add(descriptor);
|
||||
// namespace may be defined in multiple files
|
||||
if (!(descriptor instanceof NamespaceDescriptor)) {
|
||||
PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(context, descriptor);
|
||||
if (psiElement != null) {
|
||||
PsiFile file = psiElement.getContainingFile();
|
||||
if (file.getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME) != null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.add(descriptor);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetToken;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.k2js.translate.context.Namer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -143,17 +142,6 @@ public final class PsiUtils {
|
||||
return nameAsDeclaration;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getNamespaceName(@NotNull JetFile psiFile) {
|
||||
JetNamespaceHeader namespaceHeader = psiFile.getNamespaceHeader();
|
||||
String name = namespaceHeader.getName();
|
||||
assert name != null : "NamespaceHeader must have a name";
|
||||
if (name.isEmpty()) {
|
||||
return Namer.getRootNamespaceName();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetExpression getLoopRange(@NotNull JetForExpression expression) {
|
||||
JetExpression rangeExpression = expression.getLoopRange();
|
||||
|
||||
@@ -43,7 +43,7 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedRe
|
||||
*/
|
||||
public final class TranslationUtils {
|
||||
|
||||
private static JsNameRef UNDEFINED_LITERAL = AstUtil.newQualifiedNameRef("undefined");
|
||||
private static final JsNameRef UNDEFINED_LITERAL = AstUtil.newQualifiedNameRef("undefined");
|
||||
|
||||
private TranslationUtils() {
|
||||
}
|
||||
@@ -64,11 +64,7 @@ public final class TranslationUtils {
|
||||
@NotNull
|
||||
private static JsPropertyInitializer translateExtensionFunctionAsEcma5PropertyDescriptor(@NotNull JsFunction function,
|
||||
@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
|
||||
JsObjectLiteral meta = new JsObjectLiteral();
|
||||
meta.getPropertyInitializers().add(new JsPropertyInitializer(context.program().getStringLiteral("value"), function));
|
||||
if (descriptor.getModality().isOverridable()) {
|
||||
meta.getPropertyInitializers().add(context.namer().writablePropertyDescriptorField());
|
||||
}
|
||||
JsObjectLiteral meta = JsAstUtils.createDataDescriptor(function, descriptor.getModality().isOverridable(), context);
|
||||
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
foo = Kotlin.createNamespace({initialize:function(){
|
||||
}
|
||||
, box:function(){
|
||||
foo = Kotlin.definePackage({box:function(){
|
||||
return !false;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -46,9 +46,7 @@
|
||||
return {A:A, B:B, C:C};
|
||||
}
|
||||
();
|
||||
foo = Kotlin.createNamespace(classes, {initialize:function(){
|
||||
}
|
||||
, box:function(){
|
||||
foo = Kotlin.definePackage(classes, {box:function(){
|
||||
return (new foo.C).get_order() === 'ABC' && (new foo.B).get_order() === 'AB' && (new foo.A).get_order() === 'A';
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ var kotlin = {set:function (receiver, key, value) {
|
||||
return (obj1 === obj2);
|
||||
};
|
||||
|
||||
Kotlin.defs = {};
|
||||
Kotlin.modules = {};
|
||||
Kotlin.Exceptions = {};
|
||||
Kotlin.Exception = Kotlin.$createClass();
|
||||
Kotlin.RuntimeException = Kotlin.$createClass(Kotlin.Exception);
|
||||
@@ -44,7 +44,7 @@ var kotlin = {set:function (receiver, key, value) {
|
||||
Kotlin.Exceptions.UnsupportedOperationException = Kotlin.$createClass(Kotlin.Exception);
|
||||
Kotlin.Exceptions.IOException = Kotlin.$createClass(Kotlin.Exception);
|
||||
|
||||
Kotlin.throwNPE = function() {
|
||||
Kotlin.throwNPE = function () {
|
||||
throw Kotlin.$new(Kotlin.Exceptions.NullPointerException)();
|
||||
};
|
||||
|
||||
|
||||
@@ -141,9 +141,7 @@ var Kotlin = {};
|
||||
}
|
||||
})();
|
||||
|
||||
Kotlin.createNamespace = function () {
|
||||
return Kotlin.createTrait.apply(null, arguments);
|
||||
};
|
||||
Kotlin.definePackage = Kotlin.createTrait;
|
||||
|
||||
Kotlin.createClass = (function () {
|
||||
var METHODS = {addMethods: addMethods};
|
||||
@@ -243,4 +241,12 @@ var Kotlin = {};
|
||||
var singletonClass = Kotlin.createClass.apply(null, arguments);
|
||||
return new singletonClass();
|
||||
};
|
||||
|
||||
Kotlin.defineModule = function (id, module) {
|
||||
if (id in Kotlin.modules) {
|
||||
throw Kotlin.$new(Kotlin.Exceptions.IllegalArgumentException)();
|
||||
}
|
||||
|
||||
Kotlin.modules[id] = module;
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -110,18 +110,27 @@ var Kotlin = {};
|
||||
return o;
|
||||
};
|
||||
|
||||
function emptyFunction() {
|
||||
}
|
||||
|
||||
Kotlin.createNamespace = function (initializer, properties, classesAndNestedNamespaces) {
|
||||
var o = Object.create(null, properties || undefined);
|
||||
Object.defineProperty(o, "initialize", {value: initializer || emptyFunction});
|
||||
var keys = Object.keys(classesAndNestedNamespaces);
|
||||
for (var i = 0, n = keys.length; i < n; i++) {
|
||||
var name = keys[i];
|
||||
Object.defineProperty(o, name, {value: classesAndNestedNamespaces[name]});
|
||||
Kotlin.definePackage = function (functionsAndClasses, nestedNamespaces) {
|
||||
//var p = parent[localName];
|
||||
//if (!p) {
|
||||
// p = Object.create(null, functionsAndClasses || undefined);
|
||||
// Object.defineProperty(parent, localName, {value: p});
|
||||
//}
|
||||
//else if (functionsAndClasses) {
|
||||
// Object.defineProperties(p, functionsAndClasses);
|
||||
//}
|
||||
var p = Object.create(null, functionsAndClasses || undefined);
|
||||
|
||||
if (nestedNamespaces) {
|
||||
var keys = Object.keys(nestedNamespaces);
|
||||
for (var i = 0, n = keys.length; i < n; i++) {
|
||||
var name = keys[i];
|
||||
Object.defineProperty(p, name, {value:nestedNamespaces[name]});
|
||||
}
|
||||
}
|
||||
return o;
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
Kotlin.$new = function (f) {
|
||||
@@ -170,4 +179,13 @@ var Kotlin = {};
|
||||
|
||||
return Kotlin.createClass(parent || null, initializer, descriptors);
|
||||
};
|
||||
|
||||
Kotlin.defineModule = function (id, module) {
|
||||
if (id in Kotlin.modules) {
|
||||
throw Kotlin.$new(Kotlin.Exceptions.IllegalArgumentException)();
|
||||
}
|
||||
|
||||
Object.freeze(module);
|
||||
Object.defineProperty(Kotlin.modules, id, {value: module});
|
||||
};
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user