JS backend: add support for reflection types

This commit is contained in:
Michael Nedzelsky
2014-07-22 14:55:33 +04:00
parent b3ad725e8d
commit c42a9840de
12 changed files with 86 additions and 50 deletions
+3
View File
@@ -219,6 +219,9 @@
<include name="html5/**"/> <include name="html5/**"/>
<include name="stdlib/TuplesCode.kt"/> <include name="stdlib/TuplesCode.kt"/>
</fileset> </fileset>
<fileset dir="${basedir}/core/reflection/src">
<include name="kotlin/**"/>
</fileset>
<zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/> <zipfileset file="${kotlin-home}/build.txt" prefix="META-INF"/>
<manifest> <manifest>
@@ -19,8 +19,6 @@ package org.jetbrains.k2js.test;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
@@ -31,10 +29,10 @@ import org.jetbrains.k2js.facade.MainCallParameters;
import org.jetbrains.k2js.test.config.TestConfig; import org.jetbrains.k2js.test.config.TestConfig;
import org.jetbrains.k2js.test.config.TestConfigFactory; import org.jetbrains.k2js.test.config.TestConfigFactory;
import org.jetbrains.k2js.test.rhino.RhinoResultChecker; import org.jetbrains.k2js.test.rhino.RhinoResultChecker;
import org.jetbrains.k2js.test.utils.JsTestUtils;
import org.jetbrains.k2js.test.utils.TranslationUtils; import org.jetbrains.k2js.test.utils.TranslationUtils;
import java.io.File; import java.io.File;
import java.io.FilenameFilter;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -174,8 +172,8 @@ public abstract class BasicTest extends KotlinTestWithEnvironment {
@NotNull @NotNull
protected List<String> additionalKotlinFiles() { protected List<String> additionalKotlinFiles() {
List<String> additionalFiles = Lists.newArrayList(); List<String> additionalFiles = Lists.newArrayList();
additionalFiles.addAll(kotlinFilesInDirectory(pathToTestFilesRoot() + COMMON_FILES_DIR)); additionalFiles.addAll(JsTestUtils.kotlinFilesInDirectory(pathToTestFilesRoot() + COMMON_FILES_DIR));
additionalFiles.addAll(kotlinFilesInDirectory(pathToTestFiles() + COMMON_FILES_DIR)); additionalFiles.addAll(JsTestUtils.kotlinFilesInDirectory(pathToTestFiles() + COMMON_FILES_DIR));
return additionalFiles; return additionalFiles;
} }
@@ -238,30 +236,4 @@ public abstract class BasicTest extends KotlinTestWithEnvironment {
return getExpectedPath() + testName + ".out"; return getExpectedPath() + testName + ".out";
} }
@NotNull
private static List<String> kotlinFilesInDirectory(@NotNull String directory) {
File dir = new File(directory);
if (!dir.isDirectory()) {
return ContainerUtil.emptyList();
}
File[] kotlinFiles = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(@NotNull File dir, @NotNull String name) {
return name.endsWith(".kt");
}
});
if (kotlinFiles == null) {
return ContainerUtil.emptyList();
}
return ContainerUtil.map2List(kotlinFiles, new Function<File, String>() {
@Override
public String fun(File kotlinFile) {
return kotlinFile.getAbsolutePath();
}
});
}
} }
@@ -17,10 +17,13 @@
package org.jetbrains.k2js.test.utils; package org.jetbrains.k2js.test.utils;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.EcmaVersion;
import java.io.File; import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
@@ -61,4 +64,31 @@ public final class JsTestUtils {
} }
return fullFilePaths; return fullFilePaths;
} }
@NotNull
public static List<String> kotlinFilesInDirectory(@NotNull String directory) {
File dir = new File(directory);
if (!dir.isDirectory()) {
return ContainerUtil.emptyList();
}
File[] kotlinFiles = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(@NotNull File dir, @NotNull String name) {
return name.endsWith(".kt");
}
});
if (kotlinFiles == null) {
return ContainerUtil.emptyList();
}
return ContainerUtil.map2List(kotlinFiles, new Function<File, String>() {
@Override
public String fun(File kotlinFile) {
return kotlinFile.getAbsolutePath();
}
});
}
} }
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.config.Config; import org.jetbrains.k2js.config.Config;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public final class LibraryFilePathsUtil { public final class LibraryFilePathsUtil {
@@ -30,12 +31,15 @@ public final class LibraryFilePathsUtil {
@NotNull @NotNull
public static List<String> getBasicLibraryFiles() { public static List<String> getBasicLibraryFiles() {
return Lists.transform(Config.LIB_FILE_NAMES, new Function<String, String>() { List<String> files = new ArrayList<String>();
files.addAll(Lists.transform(Config.LIB_FILE_NAMES, new Function<String, String>() {
@Override @Override
public String apply(@Nullable String s) { public String apply(@Nullable String s) {
return Config.LIBRARIES_LOCATION + s; return Config.LIBRARIES_LOCATION + s;
} }
}); }));
files.addAll(getReflectionLibraryFiles());
return files;
} }
@NotNull @NotNull
@@ -55,4 +59,9 @@ public final class LibraryFilePathsUtil {
} }
return additionalKotlinFiles; return additionalKotlinFiles;
} }
@NotNull
public static List<String> getReflectionLibraryFiles() {
return JsTestUtils.kotlinFilesInDirectory(Config.REFLECTION_LIB_LOCATION);
}
} }
@@ -127,7 +127,7 @@ public final class TranslationUtils {
@NotNull @NotNull
private static List<JetFile> initLibFiles(@NotNull Project project) { private static List<JetFile> initLibFiles(@NotNull Project project) {
return createJetFileList(project, Config.LIB_FILE_NAMES, Config.LIBRARIES_LOCATION); return createJetFileList(project, LibraryFilePathsUtil.getBasicLibraryFiles(), null);
} }
@NotNull @NotNull
@@ -55,15 +55,6 @@ public final class AnalyzerFacadeForJS {
private AnalyzerFacadeForJS() { private AnalyzerFacadeForJS() {
} }
@NotNull
public static BindingContext analyzeFilesAndCheckErrors(@NotNull List<JetFile> files,
@NotNull Config config) {
BindingContext bindingContext = analyzeFiles(files, Predicates.<PsiFile>alwaysTrue(), config).getBindingContext();
checkForErrors(Config.withJsLibAdded(files, config), bindingContext);
return bindingContext;
}
//NOTE: web demo related method //NOTE: web demo related method
@SuppressWarnings("UnusedDeclaration") @SuppressWarnings("UnusedDeclaration")
@NotNull @NotNull
@@ -107,6 +107,7 @@ public abstract class Config {
); );
public static final String LIBRARIES_LOCATION = "js/js.libraries/src"; public static final String LIBRARIES_LOCATION = "js/js.libraries/src";
public static final String REFLECTION_LIB_LOCATION = "core/reflection/src/kotlin/reflect";
/** /**
* The file names in the standard library to compile * The file names in the standard library to compile
@@ -16,12 +16,14 @@
package org.jetbrains.k2js.facade; package org.jetbrains.k2js.facade;
import com.google.common.base.Predicates;
import com.google.dart.compiler.backend.js.ast.JsProgram; import com.google.dart.compiler.backend.js.ast.JsProgram;
import com.google.dart.compiler.util.TextOutputImpl; import com.google.dart.compiler.util.TextOutputImpl;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.util.Function; import com.intellij.util.Function;
import com.intellij.util.SmartList; import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
@@ -30,6 +32,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.OutputFileCollection; import org.jetbrains.jet.OutputFileCollection;
import org.jetbrains.jet.SimpleOutputFile; import org.jetbrains.jet.SimpleOutputFile;
import org.jetbrains.jet.SimpleOutputFileCollection; import org.jetbrains.jet.SimpleOutputFileCollection;
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
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.utils.fileUtils.FileUtilsPackage; import org.jetbrains.jet.utils.fileUtils.FileUtilsPackage;
@@ -141,8 +145,11 @@ public final class K2JSTranslator {
public JsProgram generateProgram(@NotNull List<JetFile> filesToTranslate, public JsProgram generateProgram(@NotNull List<JetFile> filesToTranslate,
@NotNull MainCallParameters mainCallParameters) @NotNull MainCallParameters mainCallParameters)
throws TranslationException { throws TranslationException {
BindingContext bindingContext = AnalyzerFacadeForJS.analyzeFilesAndCheckErrors(filesToTranslate, config); AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJS.analyzeFiles(filesToTranslate, Predicates.<PsiFile>alwaysTrue(), config);
return Translation.generateAst(bindingContext, filesToTranslate, mainCallParameters, config); BindingContext bindingContext = analyzeExhaust.getBindingContext();
AnalyzerFacadeForJS.checkForErrors(Config.withJsLibAdded(filesToTranslate, config), bindingContext);
ModuleDescriptor moduleDescriptor = analyzeExhaust.getModuleDescriptor();
return Translation.generateAst(bindingContext, filesToTranslate, mainCallParameters, moduleDescriptor, config);
} }
@NotNull @NotNull
@@ -24,6 +24,7 @@ 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.reflect.ReflectionTypes;
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.jet.lang.resolve.name.FqName;
import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.EcmaVersion;
@@ -48,12 +49,12 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.getSuggestedNa
*/ */
public final class StaticContext { public final class StaticContext {
public static StaticContext generateStaticContext(@NotNull BindingContext bindingContext, @NotNull EcmaVersion ecmaVersion) { public static StaticContext generateStaticContext(@NotNull BindingContext bindingContext, @NotNull EcmaVersion ecmaVersion, @NotNull ModuleDescriptor moduleDescriptor) {
JsProgram program = new JsProgram("main"); JsProgram program = new JsProgram("main");
Namer namer = Namer.newInstance(program.getRootScope()); Namer namer = Namer.newInstance(program.getRootScope());
Intrinsics intrinsics = new Intrinsics(); Intrinsics intrinsics = new Intrinsics();
StandardClasses standardClasses = StandardClasses.bindImplementations(namer.getKotlinScope()); StandardClasses standardClasses = StandardClasses.bindImplementations(namer.getKotlinScope());
return new StaticContext(program, bindingContext, namer, intrinsics, standardClasses, program.getRootScope(), ecmaVersion); return new StaticContext(program, bindingContext, namer, intrinsics, standardClasses, program.getRootScope(), ecmaVersion, moduleDescriptor);
} }
@NotNull @NotNull
@@ -70,6 +71,9 @@ public final class StaticContext {
@NotNull @NotNull
private final StandardClasses standardClasses; private final StandardClasses standardClasses;
@NotNull
private final ReflectionTypes reflectionTypes;
@NotNull @NotNull
private final JsScope rootScope; private final JsScope rootScope;
@@ -93,7 +97,7 @@ public final class StaticContext {
//TODO: too many parameters in constructor //TODO: too many parameters in constructor
private StaticContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext, private StaticContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext,
@NotNull Namer namer, @NotNull Intrinsics intrinsics, @NotNull Namer namer, @NotNull Intrinsics intrinsics,
@NotNull StandardClasses standardClasses, @NotNull JsScope rootScope, @NotNull EcmaVersion ecmaVersion) { @NotNull StandardClasses standardClasses, @NotNull JsScope rootScope, @NotNull EcmaVersion ecmaVersion, @NotNull ModuleDescriptor moduleDescriptor) {
this.program = program; this.program = program;
this.bindingContext = bindingContext; this.bindingContext = bindingContext;
this.namer = namer; this.namer = namer;
@@ -101,6 +105,7 @@ public final class StaticContext {
this.rootScope = rootScope; this.rootScope = rootScope;
this.standardClasses = standardClasses; this.standardClasses = standardClasses;
this.ecmaVersion = ecmaVersion; this.ecmaVersion = ecmaVersion;
this.reflectionTypes = new ReflectionTypes(moduleDescriptor);
} }
public boolean isEcma5() { public boolean isEcma5() {
@@ -127,6 +132,11 @@ public final class StaticContext {
return namer; return namer;
} }
@NotNull
public ReflectionTypes getReflectionTypes() {
return reflectionTypes;
}
@NotNull @NotNull
public JsScope getRootScope() { public JsScope getRootScope() {
return rootScope; return rootScope;
@@ -22,6 +22,7 @@ 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.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.reflect.ReflectionTypes;
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.jet.lang.resolve.name.FqName;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
@@ -229,6 +230,11 @@ public class TranslationContext {
return staticContext.getIntrinsics(); return staticContext.getIntrinsics();
} }
@NotNull
public ReflectionTypes getReflectionTypes() {
return staticContext.getReflectionTypes();
}
@NotNull @NotNull
public JsProgram program() { public JsProgram program() {
return staticContext.getProgram(); return staticContext.getProgram();
@@ -20,10 +20,12 @@ 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.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.lang.reflect.ReflectionTypes;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.plugin.MainFunctionDetector; import org.jetbrains.jet.plugin.MainFunctionDetector;
import org.jetbrains.k2js.config.Config; import org.jetbrains.k2js.config.Config;
@@ -108,10 +110,11 @@ public final class Translation {
@NotNull @NotNull
public static JsProgram generateAst(@NotNull BindingContext bindingContext, public static JsProgram generateAst(@NotNull BindingContext bindingContext,
@NotNull Collection<JetFile> files, @NotNull MainCallParameters mainCallParameters, @NotNull Collection<JetFile> files, @NotNull MainCallParameters mainCallParameters,
@NotNull ModuleDescriptor moduleDescriptor,
@NotNull Config config) @NotNull Config config)
throws TranslationException { throws TranslationException {
try { try {
return doGenerateAst(bindingContext, files, mainCallParameters, config); return doGenerateAst(bindingContext, files, mainCallParameters, moduleDescriptor, config);
} }
catch (UnsupportedOperationException e) { catch (UnsupportedOperationException e) {
throw new UnsupportedFeatureException("Unsupported feature used.", e); throw new UnsupportedFeatureException("Unsupported feature used.", e);
@@ -124,8 +127,9 @@ public final class Translation {
@NotNull @NotNull
private static JsProgram doGenerateAst(@NotNull BindingContext bindingContext, @NotNull Collection<JetFile> files, private static JsProgram doGenerateAst(@NotNull BindingContext bindingContext, @NotNull Collection<JetFile> files,
@NotNull MainCallParameters mainCallParameters, @NotNull MainCallParameters mainCallParameters,
@NotNull ModuleDescriptor moduleDescriptor,
@NotNull Config config) throws MainFunctionNotFoundException { @NotNull Config config) throws MainFunctionNotFoundException {
StaticContext staticContext = StaticContext.generateStaticContext(bindingContext, config.getTarget()); StaticContext staticContext = StaticContext.generateStaticContext(bindingContext, config.getTarget(), moduleDescriptor);
JsProgram program = staticContext.getProgram(); JsProgram program = staticContext.getProgram();
JsBlock block = program.getGlobalBlock(); JsBlock block = program.getGlobalBlock();
@@ -38,6 +38,9 @@
<exclude name="**/*Code.kt"/> <exclude name="**/*Code.kt"/>
<exclude name="core/dom/core.kt"/> <exclude name="core/dom/core.kt"/>
</fileset> </fileset>
<fileset dir="${basedir}/../../../core/reflection/src">
<include name="kotlin/**"/>
</fileset>
</copy> </copy>
<copy todir="${basedir}/target/generated-js-library"> <copy todir="${basedir}/target/generated-js-library">
<fileset dir="${kotlin-js-lib-srcdir}"> <fileset dir="${kotlin-js-lib-srcdir}">