develar
2012-05-13 19:44:48 +04:00
committed by pTalanov
parent c6223fc0c2
commit e0be72d5b5
25 changed files with 307 additions and 130 deletions
@@ -22,5 +22,5 @@ package org.jetbrains.jet.cli.common;
public class CompilerVersion {
// The value of this constant is generated by the build script
// DON'T MODIFY IT
public static final String VERSION = "@snapshot@";
public static final String VERSION = "snapshot";
}
@@ -121,8 +121,8 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments, K2JSCompile
@NotNull
private static Config getConfig(@NotNull K2JSCompilerArguments arguments, @NotNull Project project) {
if (arguments.libzip == null) {
return Config.getEmptyConfig(project);
return Config.getEmptyConfig(project, arguments.target);
}
return new ZippedLibrarySourcesConfig(project, arguments.libzip);
return new ZippedLibrarySourcesConfig(project, arguments.libzip, arguments.target);
}
}
@@ -38,6 +38,9 @@ public class K2JSCompilerArguments extends CompilerArguments {
@Argument(value = "srcdir", description = "Sources directory")
public String srcdir;
@Argument(value = "target", description = "Generate js files for specific ECMA version (3 or 5, default ECMA 3)")
public String target;
@Argument(value = "tags", description = "Demarcate each compilation message (error, warning, etc) with an open and close tag")
public boolean tags;
@@ -24,6 +24,7 @@ import com.intellij.openapi.compiler.TranslatingCompiler;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Chunk;
@@ -118,17 +119,33 @@ public final class K2JSCompiler implements TranslatingCompiler {
context.addMessage(CompilerMessageCategory.ERROR, "K2JSCompiler does not support multiple module source roots.", null, -1, -1);
return -1;
}
String[] commandLineArgs = constructArguments(context.getProject(), context.getModuleOutputDirectory(module), roots[0]);
VirtualFile outDir = context.getModuleOutputDirectory(module);
String outFile = outDir == null ? null : K2JSRunnerUtils.constructPathToGeneratedFile(context.getProject(), outDir.getPath());
String[] commandLineArgs = constructArguments(context.getProject(), outFile, roots[0]);
Object rc = invokeExecMethod(environment, out, context, commandLineArgs, "org.jetbrains.jet.cli.js.K2JSCompiler");
if (outDir != null) {
outDir.refresh(false, true);
}
return CompilerUtils.getReturnCodeFromObject(rc);
}
@NotNull
private static String[] constructArguments(@NotNull Project project, @Nullable VirtualFile outDir, @NotNull VirtualFile srcDir) {
private static String[] constructArguments(@NotNull Project project, @Nullable String outFile, @NotNull VirtualFile srcDir) {
ArrayList<String> args = Lists.newArrayList("-tags", "-verbose", "-version");
addPathToSourcesDir(args, srcDir);
addOutputPath(project, outDir, args);
addPathToZippedLib(project, args);
addOutputPath(outFile, args);
Pair<String, String> data = JsModuleDetector.getLibLocationAndTargetForProject(project);
if (data.first != null) {
args.add("-libzip");
args.add(data.first);
}
if (data.second != null) {
args.add("-target");
args.add(data.second);
}
return ArrayUtil.toStringArray(args);
}
@@ -138,23 +155,13 @@ public final class K2JSCompiler implements TranslatingCompiler {
args.add(srcPath);
}
private static void addOutputPath(@NotNull Project project, @Nullable VirtualFile outDir, @NotNull ArrayList<String> args) {
if (outDir != null) {
String outPath = outDir.getPath();
String outFile = K2JSRunnerUtils.constructPathToGeneratedFile(project, outPath);
private static void addOutputPath(@Nullable String outFile, @NotNull ArrayList<String> args) {
if (outFile != null) {
args.add("-output");
args.add(outFile);
}
}
private static void addPathToZippedLib(@NotNull Project project, @NotNull ArrayList<String> args) {
String libLocationForProject = JsModuleDetector.getLibLocationForProject(project);
if (libLocationForProject != null) {
args.add("-libzip");
args.add(libLocationForProject);
}
}
@NotNull
@Override
public String getDescription() {
@@ -20,7 +20,7 @@ import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.config.ZippedLibrarySourcesConfig;
import static org.jetbrains.jet.plugin.project.JsModuleDetector.getLibLocationForProject;
import static org.jetbrains.jet.plugin.project.JsModuleDetector.getLibLocationAndTargetForProject;
/**
* @author Pavel Talanov
@@ -28,6 +28,6 @@ import static org.jetbrains.jet.plugin.project.JsModuleDetector.getLibLocationFo
public final class IDEAConfig extends ZippedLibrarySourcesConfig {
public IDEAConfig(@NotNull Project project) {
super(project, getLibLocationForProject(project));
super(project, getLibLocationAndTargetForProject(project).first, null);
}
}
@@ -18,6 +18,7 @@ package org.jetbrains.jet.plugin.project;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -60,42 +61,35 @@ public final class JsModuleDetector {
}
//TODO: refactor
@Nullable
public static String getLibLocationForProject(@NotNull Project project) {
@NotNull
public static Pair<String, String> getLibLocationAndTargetForProject(@NotNull Project project) {
VirtualFile indicationFile = findIndicationFileInContentRoots(project);
if (indicationFile == null) {
return null;
return Pair.empty();
}
try {
InputStream stream = indicationFile.getInputStream();
String path = FileUtil.loadTextAndClose(stream);
String pathToLibFile = getFirstLine(path);
if (pathToLibFile == null) {
return null;
}
BufferedReader reader = new BufferedReader(new StringReader(FileUtil.loadTextAndClose(stream)));
try {
String pathToLibFile = reader.readLine();
if (pathToLibFile == null) {
return Pair.empty();
}
URI pathToLibFileUri = new URI(pathToLibFile);
URI pathToIndicationFileUri = new URI(indicationFile.getPath());
return pathToIndicationFileUri.resolve(pathToLibFileUri).toString();
return new Pair<String, String>(pathToIndicationFileUri.resolve(pathToLibFileUri).toString(), reader.readLine());
}
catch (URISyntaxException e) {
return null;
return Pair.empty();
}
finally {
reader.close();
}
}
catch (IOException e) {
return null;
}
}
@Nullable
private static String getFirstLine(@NotNull String path) throws IOException {
BufferedReader reader = new BufferedReader(new StringReader(path));
try {
return reader.readLine();
}
finally {
reader.close();
return Pair.empty();
}
}
}
@@ -41,7 +41,7 @@ public final class TestConfig extends Config {
private /*var*/ List<JetFile> jsLibFiles = null;
public TestConfig(@NotNull Project project) {
super(project);
super(project, null);
}
@NotNull
@@ -17,6 +17,7 @@
package org.jetbrains.k2js.config;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetFile;
@@ -25,6 +26,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.k2js.translate.general.Translation.EcmaVersion;
/**
* @author Pavel Talanov
* <p/>
@@ -33,8 +36,8 @@ import java.util.List;
public abstract class Config {
@NotNull
public static Config getEmptyConfig(@NotNull Project project) {
return new Config(project) {
public static Config getEmptyConfig(@NotNull Project project, @Nullable String target) {
return new Config(project, target) {
@NotNull
@Override
protected List<JetFile> generateLibFiles() {
@@ -67,9 +70,12 @@ public abstract class Config {
private final Project project;
@Nullable
private List<JetFile> libFiles = null;
@NotNull
private final EcmaVersion target;
public Config(@NotNull Project project) {
public Config(@NotNull Project project, @Nullable String target) {
this.project = project;
this.target = StringUtil.compareVersionNumbers(target, "5") >= 0 ? EcmaVersion.v5 : EcmaVersion.v3;
}
@NotNull
@@ -77,6 +83,11 @@ public abstract class Config {
return project;
}
@NotNull
public EcmaVersion getTarget() {
return target;
}
@NotNull
protected abstract List<JetFile> generateLibFiles();
@@ -40,8 +40,8 @@ public class ZippedLibrarySourcesConfig extends Config {
@Nullable
protected final String pathToLibZip;
public ZippedLibrarySourcesConfig(@NotNull Project project, @Nullable String pathToZip) {
super(project);
public ZippedLibrarySourcesConfig(@NotNull Project project, @Nullable String pathToZip, @Nullable String target) {
super(project, target);
pathToLibZip = pathToZip;
}
@@ -103,7 +103,8 @@ public final class K2JSTranslator {
JetStandardLibrary.initialize(config.getProject());
BindingContext bindingContext = AnalyzerFacadeForJS.analyzeFilesAndCheckErrors(filesToTranslate, config);
Collection<JetFile> files = AnalyzerFacadeForJS.withJsLibAdded(filesToTranslate, config);
return Translation.generateAst(bindingContext, Lists.newArrayList(files), mainCallParameters);
return Translation.generateAst(bindingContext, Lists.newArrayList(files), mainCallParameters, config.getTarget());
}
//TODO: util
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.k2js.translate.context.generator.Generator;
import org.jetbrains.k2js.translate.context.generator.Rule;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
@@ -44,7 +45,7 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.*;
public final class StaticContext {
public static StaticContext generateStaticContext(@NotNull JetStandardLibrary library,
@NotNull BindingContext bindingContext) {
@NotNull BindingContext bindingContext, Translation.EcmaVersion ecmaVersion) {
JsProgram program = new JsProgram("main");
JsRootScope jsRootScope = program.getRootScope();
Namer namer = Namer.newInstance(jsRootScope);
@@ -52,7 +53,7 @@ public final class StaticContext {
Intrinsics intrinsics = Intrinsics.standardLibraryIntrinsics(library);
StandardClasses standardClasses =
StandardClasses.bindImplementations(namer.getKotlinScope());
return new StaticContext(program, bindingContext, namer, intrinsics, standardClasses, scope);
return new StaticContext(program, bindingContext, namer, intrinsics, standardClasses, scope, ecmaVersion);
}
@NotNull
@@ -83,17 +84,24 @@ public final class StaticContext {
@NotNull
private final Map<NamingScope, JsFunction> scopeToFunction = Maps.newHashMap();
@NotNull
private final Translation.EcmaVersion ecmaVersion;
//TODO: too many parameters in constructor
private StaticContext(@NotNull JsProgram program, @NotNull BindingContext bindingContext,
@NotNull Namer namer, @NotNull Intrinsics intrinsics,
@NotNull StandardClasses standardClasses, @NotNull NamingScope rootScope) {
@NotNull Namer namer, @NotNull Intrinsics intrinsics,
@NotNull StandardClasses standardClasses, @NotNull NamingScope rootScope, @NotNull Translation.EcmaVersion ecmaVersion) {
this.program = program;
this.bindingContext = bindingContext;
this.namer = namer;
this.intrinsics = intrinsics;
this.rootScope = rootScope;
this.standardClasses = standardClasses;
this.ecmaVersion = ecmaVersion;
}
public boolean isEcma5() {
return ecmaVersion == Translation.EcmaVersion.v5;
}
@NotNull
@@ -219,8 +227,25 @@ public final class StaticContext {
if (!(descriptor instanceof PropertyDescriptor)) {
return null;
}
NamingScope enclosingScope = getEnclosingScope(descriptor);
return enclosingScope.declareObfuscatableName(Namer.getKotlinBackingFieldName(descriptor.getName()));
if (isEcma5()) {
String name = descriptor.getName();
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
if (!isDefaultAccessor(propertyDescriptor.getGetter()) || !isDefaultAccessor(propertyDescriptor.getSetter())) {
// _ is more preferable than $ — should be discussed later
name = '_' + name;
}
return enclosingScope.declareUnobfuscatableName(name);
}
else {
return enclosingScope.declareObfuscatableName(Namer.getKotlinBackingFieldName(descriptor.getName()));
}
}
private boolean isDefaultAccessor(PropertyAccessorDescriptor accessorDescriptor) {
return accessorDescriptor == null || accessorDescriptor.isDefault();
}
};
//TODO: hack!
@@ -54,6 +54,10 @@ public final class TranslationContext {
rootDynamicContext, rootAliasingContext);
}
public boolean isEcma5() {
return staticContext.isEcma5();
}
private TranslationContext(@NotNull StaticContext staticContext,
@NotNull DynamicContext dynamicContext,
@NotNull AliasingContext context) {
@@ -36,8 +36,8 @@ import org.jetbrains.k2js.translate.utils.ClassSortingUtils;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getAllClassesDefinedInNamespace;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getAllClassesDefinedInNamespace;
/**
* @author Pavel Talanov
@@ -213,7 +213,10 @@ public final class ClassTranslator extends AbstractTranslator {
if (!isTrait()) {
propertyList.add(Translation.generateClassInitializerMethod(classDeclaration, classDeclarationContext));
}
propertyList.addAll(translatePropertiesAsConstructorParameters(classDeclarationContext));
// skip for ecma5, because accessors defined via Object.defineProperties
if (!context().isEcma5()) {
propertyList.addAll(translatePropertiesAsConstructorParameters(classDeclarationContext));
}
propertyList.addAll(declarationBodyVisitor.traverseClass(classDeclaration, classDeclarationContext));
return JsAstUtils.newObjectLiteral(propertyList);
}
@@ -29,6 +29,7 @@ import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyForDescriptor;
@@ -53,6 +54,10 @@ public final class PropertyTranslator extends AbstractTranslator {
static public List<JsPropertyInitializer> translateAccessors(@NotNull PropertyDescriptor descriptor,
@NotNull TranslationContext context) {
if (context.isEcma5()) {
return Collections.emptyList();
}
PropertyTranslator propertyTranslator = new PropertyTranslator(descriptor, context);
return propertyTranslator.translate();
}
@@ -61,6 +61,9 @@ import static org.jetbrains.k2js.translate.utils.dangerous.DangerousData.collect
* Goal is to simlify interaction between translators.
*/
public final class Translation {
public enum EcmaVersion {
v3, v5
}
private Translation() {
}
@@ -142,9 +145,9 @@ public final class Translation {
@NotNull
public static JsProgram generateAst(@NotNull BindingContext bindingContext,
@NotNull List<JetFile> files, @NotNull MainCallParameters mainCallParameters) throws TranslationException {
@NotNull List<JetFile> files, @NotNull MainCallParameters mainCallParameters, EcmaVersion ecmaVersion) throws TranslationException {
try {
return doGenerateAst(bindingContext, files, mainCallParameters);
return doGenerateAst(bindingContext, files, mainCallParameters, ecmaVersion);
}
catch (UnsupportedOperationException e) {
throw new UnsupportedFeatureException("Unsupported feature used.", e);
@@ -156,10 +159,10 @@ public final class Translation {
@NotNull
private static JsProgram doGenerateAst(@NotNull BindingContext bindingContext, @NotNull List<JetFile> files,
@NotNull MainCallParameters mainCallParameters) throws MainFunctionNotFoundException {
@NotNull MainCallParameters mainCallParameters, EcmaVersion ecmaVersion) throws MainFunctionNotFoundException {
//TODO: move some of the code somewhere
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext);
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, ecmaVersion);
JsBlock block = staticContext.getProgram().getFragmentBlock(0);
TranslationContext context = TranslationContext.rootContext(staticContext);
block.getStatements().addAll(translateFiles(files, context));
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.psi.JetParameter;
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 java.util.ArrayList;
import java.util.List;
@@ -43,12 +44,13 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateArgum
* @author Pavel Talanov
*/
public final class ClassInitializerTranslator extends AbstractTranslator {
@NotNull
private final JetClassOrObject classDeclaration;
@NotNull
private final List<JsStatement> initializerStatements = new ArrayList<JsStatement>();
private final JsObjectLiteral propertiesDefinition = new JsObjectLiteral();
public ClassInitializerTranslator(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) {
// Note: it's important we use scope for class descriptor because anonymous function used in property initializers
// belong to the properties themselves
@@ -65,8 +67,12 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
// for properties declared as constructor parameters
setParameters(result, translatePrimaryConstructorParameters());
mayBeAddCallToSuperMethod();
initializerStatements.addAll((new InitializerVisitor()).traverseClass(classDeclaration, context()));
initializerStatements.addAll((InitializerVisitor.create(context())).traverseClass(classDeclaration, context()));
result.getBody().getStatements().addAll(initializerStatements);
if (!propertiesDefinition.getPropertyInitializers().isEmpty()) {
result.getBody().getStatements().add(JsAstUtils.defineProperties(propertiesDefinition));
}
return InitializerUtils.generateInitializeMethod(result);
}
@@ -123,15 +129,20 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
}
private void mayBeAddInitializerStatementForProperty(@NotNull JsParameter jsParameter,
@NotNull JetParameter jetParameter) {
@NotNull JetParameter jetParameter) {
PropertyDescriptor propertyDescriptor =
getPropertyDescriptorForConstructorParameter(bindingContext(), jetParameter);
if (propertyDescriptor != null) {
JsStatement assignmentToBackingFieldExpression = assignmentToBackingField
(context(), propertyDescriptor, jsParameter.getName().makeRef()).makeStmt();
if (propertyDescriptor == null) {
return;
}
final JsNameRef nameRef = jsParameter.getName().makeRef();
if (context().isEcma5()) {
propertiesDefinition.getPropertyInitializers().add(JsAstUtils.propertyDescriptor(propertyDescriptor, context(), nameRef));
}
else {
JsStatement assignmentToBackingFieldExpression = assignmentToBackingField(context(), propertyDescriptor, nameRef).makeStmt();
initializerStatements.add(assignmentToBackingFieldExpression);
}
}
}
@@ -0,0 +1,54 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.initializer;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsObjectLiteral;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.List;
final class InitializerEcma5Visitor extends InitializerVisitor {
private final JsObjectLiteral propertiesDefinition = new JsObjectLiteral();
@Nullable
@Override
protected JsExpression defineMember(TranslationContext context, PropertyDescriptor propertyDescriptor, JsExpression value) {
propertiesDefinition.getPropertyInitializers().add(JsAstUtils.propertyDescriptor(propertyDescriptor, context, value));
return null;
}
@Override
protected List<JsStatement> createStatements(List<JetDeclaration> declarations, TranslationContext context) {
List<JsStatement> statements = super.createStatements(declarations, context);
if (!propertiesDefinition.getPropertyInitializers().isEmpty()) {
JsStatement statement = JsAstUtils.defineProperties(propertiesDefinition);
if (statements.isEmpty()) {
statements.add(statement);
}
else {
statements.add(0, statement);
}
}
return statements;
}
}
@@ -16,11 +16,9 @@
package org.jetbrains.k2js.translate.initializer;
import com.google.dart.compiler.backend.js.ast.JsExprStmt;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsInvocation;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*;
@@ -36,6 +34,7 @@ import java.util.List;
import static org.jetbrains.k2js.translate.general.Translation.translateAsStatement;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDeclarationsForNamespace;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptor;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptorForObjectDeclaration;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getObjectDeclarationForName;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.assignmentToBackingField;
@@ -43,26 +42,25 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.assignmentToBa
/**
* @author Pavel Talanov
*/
public final class InitializerVisitor extends TranslatorVisitor<List<JsStatement>> {
/*package*/ InitializerVisitor() {
class InitializerVisitor extends TranslatorVisitor<List<JsStatement>> {
static InitializerVisitor create(TranslationContext context) {
return context.isEcma5() ? new InitializerEcma5Visitor() : new InitializerVisitor();
}
@Override
@NotNull
public List<JsStatement> visitProperty(@NotNull JetProperty expression, @NotNull TranslationContext context) {
JetExpression initializer = expression.getInitializer();
public final List<JsStatement> visitProperty(@NotNull JetProperty property, @NotNull TranslationContext context) {
JetExpression initializer = property.getInitializer();
if (initializer == null) {
return new ArrayList<JsStatement>();
return Collections.emptyList();
}
return Arrays.asList(translateInitializer(expression, context, initializer));
return toStatements(defineMember(context, getPropertyDescriptor(context.bindingContext(), property),
Translation.translateAsExpression(initializer, context)));
}
@NotNull
private static JsStatement translateInitializer(@NotNull JetProperty property, @NotNull TranslationContext context,
@NotNull JetExpression initializer) {
JsExpression initExpression = Translation.translateAsExpression(initializer, context);
return assignmentToBackingField(context, property, initExpression).makeStmt();
@Nullable
protected JsExpression defineMember(TranslationContext context, PropertyDescriptor propertyDescriptor, JsExpression value) {
return assignmentToBackingField(context, propertyDescriptor, value);
}
@Override
@@ -81,32 +79,37 @@ public final class InitializerVisitor extends TranslatorVisitor<List<JsStatement
@Override
@NotNull
public List<JsStatement> visitObjectDeclarationName(@NotNull JetObjectDeclarationName objectName,
@NotNull TranslationContext context) {
PropertyDescriptor propertyDescriptorForObjectDeclaration
= getPropertyDescriptorForObjectDeclaration(context.bindingContext(), objectName);
public final List<JsStatement> visitObjectDeclarationName(@NotNull JetObjectDeclarationName objectName,
@NotNull TranslationContext context) {
PropertyDescriptor propertyDescriptor = getPropertyDescriptorForObjectDeclaration(context.bindingContext(), objectName);
JetObjectDeclaration objectDeclaration = getObjectDeclarationForName(objectName);
JsInvocation objectValue = ClassTranslator.generateClassCreationExpression(objectDeclaration, context);
JsExprStmt assignment = assignmentToBackingField(context, propertyDescriptorForObjectDeclaration, objectValue)
.makeStmt();
return Collections.<JsStatement>singletonList(assignment);
return toStatements(defineMember(context, propertyDescriptor, objectValue));
}
private static List<JsStatement> toStatements(@Nullable JsExpression expression) {
return expression == null ? Collections.<JsStatement>emptyList() : Collections.<JsStatement>singletonList(expression.makeStmt());
}
protected List<JsStatement> createStatements(List<JetDeclaration> declarations, TranslationContext context) {
if (declarations.isEmpty()) {
return Collections.emptyList();
}
List<JsStatement> statements = new ArrayList<JsStatement>(declarations.size());
for (JetDeclaration declaration : declarations) {
statements.addAll(declaration.accept(this, context));
}
return statements;
}
@NotNull
public List<JsStatement> traverseClass(@NotNull JetClassOrObject expression, @NotNull TranslationContext context) {
List<JsStatement> initializerStatements = new ArrayList<JsStatement>();
for (JetDeclaration declaration : expression.getDeclarations()) {
initializerStatements.addAll(declaration.accept(this, context));
}
return initializerStatements;
public final List<JsStatement> traverseClass(@NotNull JetClassOrObject expression, @NotNull TranslationContext context) {
return createStatements(expression.getDeclarations(), context);
}
@NotNull
public List<JsStatement> traverseNamespace(@NotNull NamespaceDescriptor namespace, @NotNull TranslationContext context) {
List<JsStatement> initializerStatements = new ArrayList<JsStatement>();
for (JetDeclaration declaration : getDeclarationsForNamespace(context.bindingContext(), namespace)) {
initializerStatements.addAll(declaration.accept(this, context));
}
return initializerStatements;
public final List<JsStatement> traverseNamespace(@NotNull NamespaceDescriptor namespace, @NotNull TranslationContext context) {
return createStatements(getDeclarationsForNamespace(context.bindingContext(), namespace), context);
}
}
@@ -46,11 +46,10 @@ public final class NamespaceInitializerTranslator {
JsFunction result = JsAstUtils.createFunctionWithEmptyBody(namespaceContext.jsScope());
TranslationContext namespaceInitializerContext
= namespaceContext.innerContextWithGivenScopeAndBlock(result.getScope(), result.getBody());
List<JsStatement> initializerStatements =
(new InitializerVisitor()).traverseNamespace(namespace, namespaceInitializerContext);
List<JsStatement> initializerStatements = (InitializerVisitor.create(namespaceContext)).traverseNamespace(namespace,
namespaceInitializerContext);
result.getBody().getStatements().addAll(initializerStatements);
return InitializerUtils.generateInitializeMethod(result);
}
}
}
@@ -24,9 +24,7 @@ import com.google.dart.compiler.backend.js.ast.JsNew;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.calls.ExpressionAsFunctionDescriptor;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.VariableAsFunctionResolvedCall;
@@ -238,6 +236,17 @@ public final class CallTranslator extends AbstractTranslator {
if (receiver != null) {
setQualifier(callee, receiver);
}
if (context().isEcma5()) {
if (descriptor instanceof PropertyGetterDescriptor) {
return callee;
}
else if (descriptor instanceof PropertySetterDescriptor) {
assert arguments.size() == 1;
return assignment(callee, arguments.get(0));
}
}
return newInvocation(callee, arguments);
}
}, context());
@@ -20,14 +20,13 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsName;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedThisDescriptor;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.assignment;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.qualified;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedThisDescriptor;
/**
* @author Pavel Talanov
@@ -73,7 +72,7 @@ public final class NativePropertyAccessTranslator extends PropertyAccessTranslat
@NotNull
protected JsExpression translateAsSet(@Nullable JsExpression receiver, @NotNull JsExpression setTo) {
assert receiver != null;
return assignment(translateAsGet(getReceiver()), setTo);
return assignment(translateAsGet(receiver), setTo);
}
@NotNull
@@ -83,7 +82,7 @@ public final class NativePropertyAccessTranslator extends PropertyAccessTranslat
}
@Nullable
public JsExpression getReceiver() {
private JsExpression getReceiver() {
if (receiver != null) {
return receiver;
}
@@ -21,6 +21,7 @@ import com.google.dart.compiler.backend.js.ast.JsName;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.k2js.translate.context.TranslationContext;
@@ -55,8 +56,14 @@ public final class ReferenceTranslator {
@NotNull
public static JsExpression translateAsLocalNameReference(@NotNull DeclarationDescriptor referencedDescriptor,
@NotNull TranslationContext context) {
JsName referencedName = context.getNameForDescriptor(referencedDescriptor);
return referencedName.makeRef();
DeclarationDescriptor effectiveDescriptor;
if (context.isEcma5() && referencedDescriptor instanceof PropertyAccessorDescriptor) {
effectiveDescriptor = ((PropertyAccessorDescriptor) referencedDescriptor).getCorrespondingProperty();
}
else {
effectiveDescriptor = referencedDescriptor;
}
return context.getNameForDescriptor(effectiveDescriptor).makeRef();
}
@NotNull
@@ -20,6 +20,9 @@ import com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.k2js.translate.context.TranslationContext;
import java.util.*;
@@ -27,6 +30,16 @@ import java.util.*;
* @author Pavel Talanov
*/
public final class JsAstUtils {
private static final JsNameRef VALUE = new JsNameRef("value");
private static final JsPropertyInitializer WRITABLE = new JsPropertyInitializer(new JsNameRef("writable"), null) ;
private static final JsNameRef DEFINE_PROPERTIES = new JsNameRef("defineProperties");
private static final JsNameRef CREATE = new JsNameRef("create");
static {
JsNameRef nameRef = new JsNameRef("Object");
DEFINE_PROPERTIES.setQualifier(nameRef);
CREATE.setQualifier(nameRef);
}
private JsAstUtils() {
}
@@ -272,4 +285,38 @@ public final class JsAstUtils {
}
return result;
}
@NotNull
public static JsStatement defineProperties(JsObjectLiteral propertiesDefinition) {
JsInvocation invoke = new JsInvocation();
invoke.setQualifier(DEFINE_PROPERTIES);
invoke.getArguments().add(new JsThisRef());
invoke.getArguments().add(propertiesDefinition);
return invoke.makeStmt();
}
@NotNull
public static JsPropertyInitializer propertyDescriptor(PropertyDescriptor ktDescriptor,
TranslationContext context,
JsExpression value) {
return propertyDescriptor(ktDescriptor, context, value, ktDescriptor.isVar());
}
@NotNull
public static JsPropertyInitializer propertyDescriptor(DeclarationDescriptor ktDescriptor,
TranslationContext context,
JsExpression value,
boolean writable) {
JsObjectLiteral descriptor = new JsObjectLiteral();
List<JsPropertyInitializer> meta = descriptor.getPropertyInitializers();
meta.add(new JsPropertyInitializer(VALUE, value));
if (writable) {
if (WRITABLE.getValueExpr() == null) {
WRITABLE.setValueExpr(context.program().getTrueLiteral());
}
meta.add(WRITABLE);
}
// todo accessors
return new JsPropertyInitializer(context.getNameForDescriptor(ktDescriptor).makeRef(), descriptor);
}
}
@@ -33,10 +33,9 @@ import java.util.List;
import static com.google.dart.compiler.util.AstUtil.newAssignment;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptor;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getDeclarationDescriptorForReceiver;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedReceiverDescriptor;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
/**
* @author Pavel Talanov
@@ -204,13 +203,6 @@ public final class TranslationUtils {
return intrinsic.apply(left, Arrays.asList(right), context);
}
@NotNull
public static JsExpression assignmentToBackingField(@NotNull TranslationContext context, @NotNull JetProperty property,
@NotNull JsExpression initExpression) {
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(context.bindingContext(), property);
return assignmentToBackingField(context, propertyDescriptor, initExpression);
}
@Nullable
public static JsExpression resolveThisObjectForResolvedCall(@NotNull ResolvedCall<?> call,
@NotNull TranslationContext context) {
@@ -219,6 +211,6 @@ public final class TranslationUtils {
return null;
}
DeclarationDescriptor expectedThisDescriptor = getDeclarationDescriptorForReceiver(thisObject);
return TranslationUtils.getThisObject(context, expectedThisDescriptor);
return getThisObject(context, expectedThisDescriptor);
}
}