Better test generator step1, isolate testing functionality
Also move defineModule to TranslationUtils
This commit is contained in:
+14
-4
@@ -18,7 +18,6 @@ package org.jetbrains.k2js.translate.general;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
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.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetClass;
|
import org.jetbrains.jet.lang.psi.JetClass;
|
||||||
@@ -28,8 +27,10 @@ import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
|||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
|
||||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getNullableDescriptorForFunction;
|
import static org.jetbrains.k2js.translate.utils.BindingUtils.getNullableDescriptorForFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,8 +66,8 @@ public class JetTestFunctionDetector {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
public static List<JetNamedFunction> findTestFunctions(@NotNull BindingContext bindingContext, @NotNull List<JetFile> files) {
|
private static List<JetNamedFunction> findTestFunctions(@NotNull BindingContext bindingContext, @NotNull Collection<JetFile> files) {
|
||||||
List<JetNamedFunction> answer = Lists.newArrayList();
|
List<JetNamedFunction> answer = Lists.newArrayList();
|
||||||
for (JetFile file : files) {
|
for (JetFile file : files) {
|
||||||
answer.addAll(getTestFunctions(bindingContext, file.getDeclarations()));
|
answer.addAll(getTestFunctions(bindingContext, file.getDeclarations()));
|
||||||
@@ -74,7 +75,16 @@ public class JetTestFunctionDetector {
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
|
public static List<FunctionDescriptor> getTestFunctionDescriptors(@NotNull BindingContext bindingContext, @NotNull Collection<JetFile> files) {
|
||||||
|
List<FunctionDescriptor> answer = Lists.newArrayList();
|
||||||
|
for (JetNamedFunction function : findTestFunctions(bindingContext, files)) {
|
||||||
|
answer.add(getFunctionDescriptor(bindingContext, function));
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private static List<JetNamedFunction> getTestFunctions(@NotNull BindingContext bindingContext,
|
private static List<JetNamedFunction> getTestFunctions(@NotNull BindingContext bindingContext,
|
||||||
@NotNull List<JetDeclaration> declarations) {
|
@NotNull List<JetDeclaration> declarations) {
|
||||||
List<JetNamedFunction> answer = Lists.newArrayList();
|
List<JetNamedFunction> answer = Lists.newArrayList();
|
||||||
|
|||||||
@@ -19,12 +19,8 @@ package org.jetbrains.k2js.translate.general;
|
|||||||
import com.google.dart.compiler.backend.js.JsNamer;
|
import com.google.dart.compiler.backend.js.JsNamer;
|
||||||
import com.google.dart.compiler.backend.js.JsPrettyNamer;
|
import com.google.dart.compiler.backend.js.JsPrettyNamer;
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
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.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -48,11 +44,13 @@ import org.jetbrains.k2js.translate.expression.WhenTranslator;
|
|||||||
import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator;
|
import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator;
|
||||||
import org.jetbrains.k2js.translate.initializer.NamespaceInitializerTranslator;
|
import org.jetbrains.k2js.translate.initializer.NamespaceInitializerTranslator;
|
||||||
import org.jetbrains.k2js.translate.reference.CallBuilder;
|
import org.jetbrains.k2js.translate.reference.CallBuilder;
|
||||||
|
import org.jetbrains.k2js.translate.test.TestGenerator;
|
||||||
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
import org.jetbrains.k2js.translate.utils.JsAstUtils;
|
||||||
|
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
||||||
import org.jetbrains.k2js.translate.utils.dangerous.DangerousData;
|
import org.jetbrains.k2js.translate.utils.dangerous.DangerousData;
|
||||||
import org.jetbrains.k2js.translate.utils.dangerous.DangerousTranslator;
|
import org.jetbrains.k2js.translate.utils.dangerous.DangerousTranslator;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -79,7 +77,7 @@ public final class Translation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static List<JsStatement> translateFiles(@NotNull List<JetFile> files, @NotNull TranslationContext context) {
|
public static List<JsStatement> translateFiles(@NotNull Collection<JetFile> files, @NotNull TranslationContext context) {
|
||||||
return NamespaceDeclarationTranslator.translateFiles(files, context);
|
return NamespaceDeclarationTranslator.translateFiles(files, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,11 +147,11 @@ public final class Translation {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsProgram generateAst(@NotNull BindingContext bindingContext,
|
public static JsProgram generateAst(@NotNull BindingContext bindingContext,
|
||||||
@NotNull List<JetFile> files, @NotNull MainCallParameters mainCallParameters,
|
@NotNull Collection<JetFile> files, @NotNull MainCallParameters mainCallParameters,
|
||||||
@NotNull Config config, List<String> rawStatements)
|
@NotNull Config config)
|
||||||
throws TranslationException {
|
throws TranslationException {
|
||||||
try {
|
try {
|
||||||
return doGenerateAst(bindingContext, files, mainCallParameters, config, rawStatements);
|
return doGenerateAst(bindingContext, files, mainCallParameters, config);
|
||||||
}
|
}
|
||||||
catch (UnsupportedOperationException e) {
|
catch (UnsupportedOperationException e) {
|
||||||
throw new UnsupportedFeatureException("Unsupported feature used.", e);
|
throw new UnsupportedFeatureException("Unsupported feature used.", e);
|
||||||
@@ -164,9 +162,9 @@ public final class Translation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JsProgram doGenerateAst(@NotNull BindingContext bindingContext, @NotNull List<JetFile> files,
|
private static JsProgram doGenerateAst(@NotNull BindingContext bindingContext, @NotNull Collection<JetFile> files,
|
||||||
@NotNull MainCallParameters mainCallParameters,
|
@NotNull MainCallParameters mainCallParameters,
|
||||||
@NotNull Config config, List<String> rawStatements) throws MainFunctionNotFoundException {
|
@NotNull Config config) throws MainFunctionNotFoundException {
|
||||||
//TODO: move some of the code somewhere
|
//TODO: move some of the code somewhere
|
||||||
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
|
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
|
||||||
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, config.getTarget());
|
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, config.getTarget());
|
||||||
@@ -174,12 +172,13 @@ public final class Translation {
|
|||||||
JsBlock block = program.getGlobalBlock();
|
JsBlock block = program.getGlobalBlock();
|
||||||
|
|
||||||
JsFunction rootFunction = JsAstUtils.createPackage(block.getStatements(), program.getScope());
|
JsFunction rootFunction = JsAstUtils.createPackage(block.getStatements(), program.getScope());
|
||||||
List<JsStatement> statements = rootFunction.getBody().getStatements();
|
JsBlock rootBlock = rootFunction.getBody();
|
||||||
|
List<JsStatement> statements = rootBlock.getStatements();
|
||||||
statements.add(program.getStringLiteral("use strict").makeStmt());
|
statements.add(program.getStringLiteral("use strict").makeStmt());
|
||||||
|
|
||||||
TranslationContext context = TranslationContext.rootContext(staticContext);
|
TranslationContext context = TranslationContext.rootContext(staticContext);
|
||||||
statements.addAll(translateFiles(files, context));
|
statements.addAll(translateFiles(files, context));
|
||||||
defineModule(statements, context, config);
|
TranslationUtils.defineModule(context, statements, config.getModuleId());
|
||||||
|
|
||||||
if (mainCallParameters.shouldBeGenerated()) {
|
if (mainCallParameters.shouldBeGenerated()) {
|
||||||
JsStatement statement = generateCallToMain(context, files, mainCallParameters.arguments());
|
JsStatement statement = generateCallToMain(context, files, mainCallParameters.arguments());
|
||||||
@@ -187,22 +186,18 @@ public final class Translation {
|
|||||||
statements.add(statement);
|
statements.add(statement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
generateTestCalls(context, files, block, rawStatements);
|
TestGenerator.generateTestCalls(context, files, rootBlock);
|
||||||
JsNamer namer = new JsPrettyNamer();
|
performSimpleNameMangling(context.program());
|
||||||
namer.exec(context.program());
|
|
||||||
return context.program();
|
return context.program();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void defineModule(@NotNull List<JsStatement> statements,
|
private static void performSimpleNameMangling(@NotNull JsProgram program) {
|
||||||
@NotNull TranslationContext context,
|
JsNamer namer = new JsPrettyNamer();
|
||||||
@NotNull Config config) {
|
namer.exec(program);
|
||||||
statements.add(AstUtil.newInvocation(context.namer().kotlin("defineModule"),
|
|
||||||
context.program().getStringLiteral(config.getModuleId()),
|
|
||||||
context.jsScope().declareName("_").makeRef()).makeStmt());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static JsStatement generateCallToMain(@NotNull TranslationContext context, @NotNull List<JetFile> files,
|
private static JsStatement generateCallToMain(@NotNull TranslationContext context, @NotNull Collection<JetFile> files,
|
||||||
@NotNull List<String> arguments) throws MainFunctionNotFoundException {
|
@NotNull List<String> arguments) throws MainFunctionNotFoundException {
|
||||||
JetNamedFunction mainFunction = getMainFunction(files);
|
JetNamedFunction mainFunction = getMainFunction(files);
|
||||||
if (mainFunction == null) {
|
if (mainFunction == null) {
|
||||||
@@ -228,53 +223,4 @@ public final class Translation {
|
|||||||
arrayLiteral.getExpressions().addAll(toStringLiteralList(arguments, context.program()));
|
arrayLiteral.getExpressions().addAll(toStringLiteralList(arguments, context.program()));
|
||||||
JsAstUtils.setArguments(translatedCall, Collections.<JsExpression>singletonList(arrayLiteral));
|
JsAstUtils.setArguments(translatedCall, Collections.<JsExpression>singletonList(arrayLiteral));
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
String funName = functionDescriptor.getName().getName();
|
|
||||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
|
||||||
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() {");
|
|
||||||
//rawStatements.add(" expect(0);");
|
|
||||||
rawStatements.add(" _testCase." + funName + "();");
|
|
||||||
} else {
|
|
||||||
rawStatements.add("QUnit.test( \"" + funName + "()\", function() {");
|
|
||||||
//rawStatements.add(" expect(0);");
|
|
||||||
rawStatements.add(" " + funName + "();");
|
|
||||||
}
|
|
||||||
rawStatements.add("});");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getQualifiedName(ClassDescriptor classDescriptor) {
|
|
||||||
List<String> parts = new ArrayList<String>();
|
|
||||||
DeclarationDescriptor current = classDescriptor;
|
|
||||||
while (current != null) {
|
|
||||||
String name = current.getName().getName();
|
|
||||||
if (name.startsWith("<")) break;
|
|
||||||
parts.add(name);
|
|
||||||
current = current.getContainingDeclaration();
|
|
||||||
}
|
|
||||||
Collections.reverse(parts);
|
|
||||||
return StringUtil.join(parts, ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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.test;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.*;
|
||||||
|
import com.google.dart.compiler.util.AstUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
|
import org.jetbrains.k2js.translate.general.JetTestFunctionDetector;
|
||||||
|
import org.jetbrains.k2js.translate.reference.CallBuilder;
|
||||||
|
import org.jetbrains.k2js.translate.reference.ReferenceTranslator;
|
||||||
|
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.google.dart.compiler.util.AstUtil.newBlock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Pavel Talanov
|
||||||
|
*/
|
||||||
|
public final class TestGenerator {
|
||||||
|
private TestGenerator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void generateTestCalls(@NotNull TranslationContext context,
|
||||||
|
@NotNull Collection<JetFile> files,
|
||||||
|
@NotNull JsBlock block) {
|
||||||
|
List<FunctionDescriptor> functionDescriptors = JetTestFunctionDetector.getTestFunctionDescriptors(context.bindingContext(), files);
|
||||||
|
doGenerateTestCalls(functionDescriptors, block, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doGenerateTestCalls(@NotNull List<FunctionDescriptor> functionDescriptors,
|
||||||
|
@NotNull JsBlock block,
|
||||||
|
@NotNull TranslationContext context) {
|
||||||
|
for (FunctionDescriptor functionDescriptor : functionDescriptors) {
|
||||||
|
ClassDescriptor classDescriptor = JsDescriptorUtils.getContainingClass(functionDescriptor);
|
||||||
|
if (classDescriptor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JsExpression expression = ReferenceTranslator.translateAsFQReference(classDescriptor, context);
|
||||||
|
JsNew constructClassExpr = new JsNew(expression);
|
||||||
|
JsExpression functionToTestCall =
|
||||||
|
CallBuilder.build(context).descriptor(functionDescriptor).receiver(constructClassExpr).translate();
|
||||||
|
JsNameRef qUnitTestFunRef = AstUtil.newQualifiedNameRef("QUnit.test");
|
||||||
|
JsFunction functionToTest = new JsFunction(context.jsScope());
|
||||||
|
functionToTest.setBody(newBlock(functionToTestCall.makeStmt()));
|
||||||
|
String testName = classDescriptor.getName() + "." + functionDescriptor.getName();
|
||||||
|
block.getStatements()
|
||||||
|
.add(AstUtil.newInvocation(qUnitTestFunRef, context.program().getStringLiteral(testName), functionToTest)
|
||||||
|
.makeStmt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -255,4 +255,11 @@ public final class TranslationUtils {
|
|||||||
public static boolean isNullLiteral(@NotNull TranslationContext context, @NotNull JsExpression expression) {
|
public static boolean isNullLiteral(@NotNull TranslationContext context, @NotNull JsExpression expression) {
|
||||||
return expression.equals(context.program().getNullLiteral());
|
return expression.equals(context.program().getNullLiteral());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void defineModule(@NotNull TranslationContext context, @NotNull List<JsStatement> statements,
|
||||||
|
String moduleId) {
|
||||||
|
statements.add(AstUtil.newInvocation(context.namer().kotlin("defineModule"),
|
||||||
|
context.program().getStringLiteral(moduleId),
|
||||||
|
context.jsScope().declareName("_").makeRef()).makeStmt());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user