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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
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.types.JetType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getNullableDescriptorForFunction;
|
||||
|
||||
/**
|
||||
@@ -65,8 +66,8 @@ public class JetTestFunctionDetector {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static List<JetNamedFunction> findTestFunctions(@NotNull BindingContext bindingContext, @NotNull List<JetFile> files) {
|
||||
@NotNull
|
||||
private static List<JetNamedFunction> findTestFunctions(@NotNull BindingContext bindingContext, @NotNull Collection<JetFile> files) {
|
||||
List<JetNamedFunction> answer = Lists.newArrayList();
|
||||
for (JetFile file : files) {
|
||||
answer.addAll(getTestFunctions(bindingContext, file.getDeclarations()));
|
||||
@@ -74,7 +75,16 @@ public class JetTestFunctionDetector {
|
||||
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,
|
||||
@NotNull List<JetDeclaration> declarations) {
|
||||
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.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.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.NamespaceDescriptor;
|
||||
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.NamespaceInitializerTranslator;
|
||||
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.TranslationUtils;
|
||||
import org.jetbrains.k2js.translate.utils.dangerous.DangerousData;
|
||||
import org.jetbrains.k2js.translate.utils.dangerous.DangerousTranslator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -79,7 +77,7 @@ public final class Translation {
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@@ -149,11 +147,11 @@ public final class Translation {
|
||||
|
||||
@NotNull
|
||||
public static JsProgram generateAst(@NotNull BindingContext bindingContext,
|
||||
@NotNull List<JetFile> files, @NotNull MainCallParameters mainCallParameters,
|
||||
@NotNull Config config, List<String> rawStatements)
|
||||
@NotNull Collection<JetFile> files, @NotNull MainCallParameters mainCallParameters,
|
||||
@NotNull Config config)
|
||||
throws TranslationException {
|
||||
try {
|
||||
return doGenerateAst(bindingContext, files, mainCallParameters, config, rawStatements);
|
||||
return doGenerateAst(bindingContext, files, mainCallParameters, config);
|
||||
}
|
||||
catch (UnsupportedOperationException e) {
|
||||
throw new UnsupportedFeatureException("Unsupported feature used.", e);
|
||||
@@ -164,9 +162,9 @@ public final class Translation {
|
||||
}
|
||||
|
||||
@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 Config config, List<String> rawStatements) throws MainFunctionNotFoundException {
|
||||
@NotNull Config config) throws MainFunctionNotFoundException {
|
||||
//TODO: move some of the code somewhere
|
||||
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
|
||||
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, config.getTarget());
|
||||
@@ -174,12 +172,13 @@ public final class Translation {
|
||||
JsBlock block = program.getGlobalBlock();
|
||||
|
||||
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());
|
||||
|
||||
TranslationContext context = TranslationContext.rootContext(staticContext);
|
||||
statements.addAll(translateFiles(files, context));
|
||||
defineModule(statements, context, config);
|
||||
TranslationUtils.defineModule(context, statements, config.getModuleId());
|
||||
|
||||
if (mainCallParameters.shouldBeGenerated()) {
|
||||
JsStatement statement = generateCallToMain(context, files, mainCallParameters.arguments());
|
||||
@@ -187,22 +186,18 @@ public final class Translation {
|
||||
statements.add(statement);
|
||||
}
|
||||
}
|
||||
generateTestCalls(context, files, block, rawStatements);
|
||||
JsNamer namer = new JsPrettyNamer();
|
||||
namer.exec(context.program());
|
||||
TestGenerator.generateTestCalls(context, files, rootBlock);
|
||||
performSimpleNameMangling(context.program());
|
||||
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());
|
||||
private static void performSimpleNameMangling(@NotNull JsProgram program) {
|
||||
JsNamer namer = new JsPrettyNamer();
|
||||
namer.exec(program);
|
||||
}
|
||||
|
||||
@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 {
|
||||
JetNamedFunction mainFunction = getMainFunction(files);
|
||||
if (mainFunction == null) {
|
||||
@@ -228,53 +223,4 @@ public final class Translation {
|
||||
arrayLiteral.getExpressions().addAll(toStringLiteralList(arguments, context.program()));
|
||||
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) {
|
||||
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