Inline test: check that no any inline method is called directly

This commit is contained in:
Mikhael Bogdanov
2014-03-28 13:22:38 +04:00
parent 0d239a3e0e
commit 5b5ecca12a
8 changed files with 314 additions and 107 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.jet.OutputFile;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.List;
public class GeneratedClassLoader extends URLClassLoader { public class GeneratedClassLoader extends URLClassLoader {
private ClassFileFactory state; private ClassFileFactory state;
@@ -47,4 +48,9 @@ public class GeneratedClassLoader extends URLClassLoader {
public void dispose() { public void dispose() {
state = null; state = null;
} }
@NotNull
public List<OutputFile> getAllGeneratedFiles() {
return state.asList();
}
} }
@@ -3,7 +3,8 @@ package test
enum class MyEnum { enum class MyEnum {
K; K;
inline fun <T> doSmth(a: T) : String { //TODO: KT-4693
[inline] fun <T> doSmth(a: T) : String {
return a.toString() + K.name() return a.toString() + K.name()
} }
} }
@@ -0,0 +1,189 @@
/*
* Copyright 2010-2014 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.jet.codegen;
import com.intellij.openapi.util.text.StringUtil;
import groovyjarjarasm.asm.Opcodes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.*;
import org.jetbrains.asm4.tree.MethodNode;
import org.jetbrains.jet.OutputFile;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class InlineTestUtil {
public static final String INLINE_ANNOTATION_CLASS = "kotlin/inline";
public static void checkNoCallsToInline(List<OutputFile> files) {
//final HashMap<Type> inlineMethods = new HashMap();
Set<MethodInfo> inlinedMethods = collectInlineMethods(files);
assert !inlinedMethods.isEmpty() : "There is no any inline method";
List<NotInlinedCall> notInlinedCalls = checkInlineNotInvoked(files, inlinedMethods);
assert notInlinedCalls.isEmpty() : "All inline methods should be inlined but " + StringUtil.join(notInlinedCalls, "\n");
}
private static Set<MethodInfo> collectInlineMethods(List<OutputFile> files) {
final Set<MethodInfo> inlineMethods = new HashSet<MethodInfo>();
for (OutputFile file : files) {
ClassReader cr = new ClassReader(file.asByteArray());
final String[] className = {null};
cr.accept(new ClassVisitor(Opcodes.ASM4) {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
className[0] = name;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(
int access, String name, String desc, String signature, String[] exceptions
) {
return new MethodNode(Opcodes.ASM4, access, name, desc, signature, exceptions) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
Type type = Type.getType(desc);
String annotationClass = type.getInternalName();
if (INLINE_ANNOTATION_CLASS.equals(annotationClass)) {
inlineMethods.add(new MethodInfo(className[0], name, this.desc));
}
return super.visitAnnotation(desc, visible);
}
};
}
}, 0);
}
return inlineMethods;
}
private static List<NotInlinedCall> checkInlineNotInvoked(List<OutputFile> files, final Set<MethodInfo> inlinedMethods) {
final List<NotInlinedCall> notInlined = new ArrayList<NotInlinedCall>();
for (OutputFile file : files) {
ClassReader cr = new ClassReader(file.asByteArray());
final String[] className = {null};
cr.accept(new ClassVisitor(Opcodes.ASM4) {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
className[0] = name;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(
int access, String name, String desc, String signature, String[] exceptions
) {
return new MethodNode(Opcodes.ASM4, access, name, desc, signature, exceptions) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
MethodInfo methodCall = new MethodInfo(owner, name, desc);
if (inlinedMethods.contains(methodCall)) {
MethodInfo fromCall = new MethodInfo(className[0], this.name, this.desc);
//skip facades
if (methodCall.owner.startsWith(fromCall.owner + "-")) {
return;
}
//skip delegation to trait impl from child class
if (methodCall.owner.endsWith(JvmAbi.TRAIT_IMPL_SUFFIX) && !fromCall.owner.equals(methodCall.owner)) {
return;
}
notInlined.add(new NotInlinedCall(fromCall, methodCall));
}
}
};
}
}, 0);
}
return notInlined;
}
public static class NotInlinedCall {
public final MethodInfo fromCall;
public final MethodInfo inlineMethod;
public NotInlinedCall(MethodInfo call, MethodInfo method) {
fromCall = call;
inlineMethod = method;
}
@Override
public String toString() {
return "NotInlinedCall{" +
"fromCall=" + fromCall +
", inlineMethod=" + inlineMethod +
'}';
}
}
public static class MethodInfo {
private final String owner;
private final String name;
private final String desc;
public MethodInfo(@NotNull String owner, @NotNull String name, @NotNull String desc) {
this.owner = owner;
this.name = name;
this.desc = desc;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MethodInfo method = (MethodInfo) o;
if (!desc.equals(method.desc)) return false;
if (!name.equals(method.name)) return false;
if (!owner.equals(method.owner)) return false;
return true;
}
@Override
public int hashCode() {
int result = owner.hashCode();
result = 31 * result + name.hashCode();
result = 31 * result + desc.hashCode();
return result;
}
@Override
public String toString() {
return "MethodInfo{" +
"owner='" + owner + '\'' +
", name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
}
@@ -19,11 +19,10 @@ package org.jetbrains.jet.codegen.generated;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.Processor; import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.*;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.TestJdkKind;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.codegen.CodegenTestCase; import org.jetbrains.jet.codegen.CodegenTestCase;
import org.jetbrains.jet.codegen.InlineTestUtil;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.utils.UtilsPackage; import org.jetbrains.jet.utils.UtilsPackage;
@@ -71,6 +70,10 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {
blackBox(); blackBox();
} }
public void doTestMultiFileWithInlineCheck(@NotNull String folderName) {
doTestMultiFile(folderName);
InlineTestUtil.checkNoCallsToInline(initializedClassLoader.getAllGeneratedFiles());
}
private void blackBoxFileWithJavaByFullPath(@NotNull String ktFileFullPath) { private void blackBoxFileWithJavaByFullPath(@NotNull String ktFileFullPath) {
String ktFile = ktFileFullPath.substring("compiler/testData/codegen/".length()); String ktFile = ktFileFullPath.substring("compiler/testData/codegen/".length());
@@ -38,242 +38,242 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxCodegenT
@TestMetadata("builders") @TestMetadata("builders")
public void testBuilders() throws Exception { public void testBuilders() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/builders"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/builders");
} }
@TestMetadata("buildersAndLambdaCapturing") @TestMetadata("buildersAndLambdaCapturing")
public void testBuildersAndLambdaCapturing() throws Exception { public void testBuildersAndLambdaCapturing() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/buildersAndLambdaCapturing"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/buildersAndLambdaCapturing");
} }
@TestMetadata("captureInlinable") @TestMetadata("captureInlinable")
public void testCaptureInlinable() throws Exception { public void testCaptureInlinable() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/captureInlinable"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/captureInlinable");
} }
@TestMetadata("captureInlinableAndOther") @TestMetadata("captureInlinableAndOther")
public void testCaptureInlinableAndOther() throws Exception { public void testCaptureInlinableAndOther() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/captureInlinableAndOther"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/captureInlinableAndOther");
} }
@TestMetadata("captureThisAndReceiver") @TestMetadata("captureThisAndReceiver")
public void testCaptureThisAndReceiver() throws Exception { public void testCaptureThisAndReceiver() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/captureThisAndReceiver"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/captureThisAndReceiver");
} }
@TestMetadata("classObject") @TestMetadata("classObject")
public void testClassObject() throws Exception { public void testClassObject() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/classObject"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/classObject");
} }
@TestMetadata("closureChain") @TestMetadata("closureChain")
public void testClosureChain() throws Exception { public void testClosureChain() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/closureChain"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/closureChain");
} }
@TestMetadata("extension") @TestMetadata("extension")
public void testExtension() throws Exception { public void testExtension() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/extension"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/extension");
} }
@TestMetadata("forEachLine") @TestMetadata("forEachLine")
public void testForEachLine() throws Exception { public void testForEachLine() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/forEachLine"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/forEachLine");
} }
@TestMetadata("generics") @TestMetadata("generics")
public void testGenerics() throws Exception { public void testGenerics() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/generics"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/generics");
} }
@TestMetadata("identityCheck") @TestMetadata("identityCheck")
public void testIdentityCheck() throws Exception { public void testIdentityCheck() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/identityCheck"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/identityCheck");
} }
@TestMetadata("ifBranches") @TestMetadata("ifBranches")
public void testIfBranches() throws Exception { public void testIfBranches() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/ifBranches"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/ifBranches");
} }
@TestMetadata("iinc") @TestMetadata("iinc")
public void testIinc() throws Exception { public void testIinc() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/iinc"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/iinc");
} }
@TestMetadata("inlineChain") @TestMetadata("inlineChain")
public void testInlineChain() throws Exception { public void testInlineChain() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/inlineChain"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/inlineChain");
} }
@TestMetadata("lambdaClassClash") @TestMetadata("lambdaClassClash")
public void testLambdaClassClash() throws Exception { public void testLambdaClassClash() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/lambdaClassClash"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/lambdaClassClash");
} }
@TestMetadata("lambdaCloning") @TestMetadata("lambdaCloning")
public void testLambdaCloning() throws Exception { public void testLambdaCloning() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/lambdaCloning"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/lambdaCloning");
} }
@TestMetadata("lambdaInLambda") @TestMetadata("lambdaInLambda")
public void testLambdaInLambda() throws Exception { public void testLambdaInLambda() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/lambdaInLambda"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/lambdaInLambda");
} }
@TestMetadata("lambdaInLambda2") @TestMetadata("lambdaInLambda2")
public void testLambdaInLambda2() throws Exception { public void testLambdaInLambda2() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/lambdaInLambda2"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/lambdaInLambda2");
} }
@TestMetadata("lambdaInLambdaNoInline") @TestMetadata("lambdaInLambdaNoInline")
public void testLambdaInLambdaNoInline() throws Exception { public void testLambdaInLambdaNoInline() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/lambdaInLambdaNoInline"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/lambdaInLambdaNoInline");
} }
@TestMetadata("localFunInLambda") @TestMetadata("localFunInLambda")
public void testLocalFunInLambda() throws Exception { public void testLocalFunInLambda() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/localFunInLambda"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/localFunInLambda");
} }
@TestMetadata("noInline") @TestMetadata("noInline")
public void testNoInline() throws Exception { public void testNoInline() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/noInline"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/noInline");
} }
@TestMetadata("noInlineLambdaChain") @TestMetadata("noInlineLambdaChain")
public void testNoInlineLambdaChain() throws Exception { public void testNoInlineLambdaChain() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/noInlineLambdaChain"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/noInlineLambdaChain");
} }
@TestMetadata("noInlineLambdaChainWithCapturedInline") @TestMetadata("noInlineLambdaChainWithCapturedInline")
public void testNoInlineLambdaChainWithCapturedInline() throws Exception { public void testNoInlineLambdaChainWithCapturedInline() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/noInlineLambdaChainWithCapturedInline"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/noInlineLambdaChainWithCapturedInline");
} }
@TestMetadata("noInlineLambdaX2") @TestMetadata("noInlineLambdaX2")
public void testNoInlineLambdaX2() throws Exception { public void testNoInlineLambdaX2() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/noInlineLambdaX2"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/noInlineLambdaX2");
} }
@TestMetadata("params") @TestMetadata("params")
public void testParams() throws Exception { public void testParams() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/params"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/params");
} }
@TestMetadata("plusAssign") @TestMetadata("plusAssign")
public void testPlusAssign() throws Exception { public void testPlusAssign() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/plusAssign"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/plusAssign");
} }
@TestMetadata("regeneratedLambdaName") @TestMetadata("regeneratedLambdaName")
public void testRegeneratedLambdaName() throws Exception { public void testRegeneratedLambdaName() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/regeneratedLambdaName"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/regeneratedLambdaName");
} }
@TestMetadata("rootConstructor") @TestMetadata("rootConstructor")
public void testRootConstructor() throws Exception { public void testRootConstructor() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/rootConstructor"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/rootConstructor");
} }
@TestMetadata("sameCaptured") @TestMetadata("sameCaptured")
public void testSameCaptured() throws Exception { public void testSameCaptured() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/sameCaptured"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/sameCaptured");
} }
@TestMetadata("severalClosures") @TestMetadata("severalClosures")
public void testSeveralClosures() throws Exception { public void testSeveralClosures() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/severalClosures"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/severalClosures");
} }
@TestMetadata("severalUsage") @TestMetadata("severalUsage")
public void testSeveralUsage() throws Exception { public void testSeveralUsage() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/severalUsage"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/severalUsage");
} }
@TestMetadata("simpleCapturingInClass") @TestMetadata("simpleCapturingInClass")
public void testSimpleCapturingInClass() throws Exception { public void testSimpleCapturingInClass() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/simpleCapturingInClass"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/simpleCapturingInClass");
} }
@TestMetadata("simpleCapturingInPackage") @TestMetadata("simpleCapturingInPackage")
public void testSimpleCapturingInPackage() throws Exception { public void testSimpleCapturingInPackage() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/simpleCapturingInPackage"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/simpleCapturingInPackage");
} }
@TestMetadata("simpleDouble") @TestMetadata("simpleDouble")
public void testSimpleDouble() throws Exception { public void testSimpleDouble() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/simpleDouble"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/simpleDouble");
} }
@TestMetadata("simpleEnum") @TestMetadata("simpleEnum")
public void testSimpleEnum() throws Exception { public void testSimpleEnum() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/simpleEnum"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/simpleEnum");
} }
@TestMetadata("simpleGenerics") @TestMetadata("simpleGenerics")
public void testSimpleGenerics() throws Exception { public void testSimpleGenerics() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/simpleGenerics"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/simpleGenerics");
} }
@TestMetadata("simpleInt") @TestMetadata("simpleInt")
public void testSimpleInt() throws Exception { public void testSimpleInt() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/simpleInt"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/simpleInt");
} }
@TestMetadata("simpleLambda") @TestMetadata("simpleLambda")
public void testSimpleLambda() throws Exception { public void testSimpleLambda() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/simpleLambda"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/simpleLambda");
} }
@TestMetadata("simpleObject") @TestMetadata("simpleObject")
public void testSimpleObject() throws Exception { public void testSimpleObject() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/simpleObject"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/simpleObject");
} }
@TestMetadata("stackHeightBug") @TestMetadata("stackHeightBug")
public void testStackHeightBug() throws Exception { public void testStackHeightBug() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/stackHeightBug"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/stackHeightBug");
} }
@TestMetadata("trait") @TestMetadata("trait")
public void testTrait() throws Exception { public void testTrait() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/trait"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/trait");
} }
@TestMetadata("tryCatch") @TestMetadata("tryCatch")
public void testTryCatch() throws Exception { public void testTryCatch() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/tryCatch"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/tryCatch");
} }
@TestMetadata("tryCatch2") @TestMetadata("tryCatch2")
public void testTryCatch2() throws Exception { public void testTryCatch2() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/tryCatch2"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/tryCatch2");
} }
@TestMetadata("tryCatchFinally") @TestMetadata("tryCatchFinally")
public void testTryCatchFinally() throws Exception { public void testTryCatchFinally() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/tryCatchFinally"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/tryCatchFinally");
} }
@TestMetadata("use") @TestMetadata("use")
public void testUse() throws Exception { public void testUse() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/use"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/use");
} }
@TestMetadata("vararg") @TestMetadata("vararg")
public void testVararg() throws Exception { public void testVararg() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/vararg"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/vararg");
} }
@TestMetadata("with") @TestMetadata("with")
public void testWith() throws Exception { public void testWith() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/with"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/with");
} }
@TestMetadata("withoutInline") @TestMetadata("withoutInline")
public void testWithoutInline() throws Exception { public void testWithoutInline() throws Exception {
doTestMultiFile("compiler/testData/codegen/boxInline/withoutInline"); doTestMultiFileWithInlineCheck("compiler/testData/codegen/boxInline/withoutInline");
} }
} }
@@ -22,14 +22,12 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor; import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.*;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.OutputFileCollection;
import org.jetbrains.jet.TestJdkKind;
import org.jetbrains.jet.cli.common.output.outputUtils.OutputUtilsPackage; import org.jetbrains.jet.cli.common.output.outputUtils.OutputUtilsPackage;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationUtils; import org.jetbrains.jet.codegen.GenerationUtils;
import org.jetbrains.jet.codegen.InlineTestUtil;
import org.jetbrains.jet.config.CompilerConfiguration; import org.jetbrains.jet.config.CompilerConfiguration;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
@@ -65,7 +63,13 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends TestCaseWit
invokeMain(); invokeMain();
} }
public void doBoxTest(@NotNull String folderName) throws Exception { public void doBoxTestWithInlineCheck(@NotNull String folderName) throws Exception {
ArrayList<OutputFile> files = doBoxTest(folderName);
InlineTestUtil.checkNoCallsToInline(files);
}
@NotNull
private ArrayList<OutputFile> doBoxTest(@NotNull String folderName) throws Exception {
final List<String> files = new ArrayList<String>(2); final List<String> files = new ArrayList<String>(2);
FileUtil.processFilesRecursively(new File(folderName), new Processor<File>() { FileUtil.processFilesRecursively(new File(folderName), new Processor<File>() {
@Override @Override
@@ -96,6 +100,10 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends TestCaseWit
System.out.println(result); System.out.println(result);
throw UtilsPackage.rethrow(e); throw UtilsPackage.rethrow(e);
} }
ArrayList<OutputFile> allGeneratedFiles = new ArrayList<OutputFile>(factory1.asList());
allGeneratedFiles.addAll(factory2.asList());
return allGeneratedFiles;
} }
private void invokeMain() throws Exception { private void invokeMain() throws Exception {
@@ -38,242 +38,242 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
@TestMetadata("builders") @TestMetadata("builders")
public void testBuilders() throws Exception { public void testBuilders() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/builders"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/builders");
} }
@TestMetadata("buildersAndLambdaCapturing") @TestMetadata("buildersAndLambdaCapturing")
public void testBuildersAndLambdaCapturing() throws Exception { public void testBuildersAndLambdaCapturing() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/buildersAndLambdaCapturing"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/buildersAndLambdaCapturing");
} }
@TestMetadata("captureInlinable") @TestMetadata("captureInlinable")
public void testCaptureInlinable() throws Exception { public void testCaptureInlinable() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/captureInlinable"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/captureInlinable");
} }
@TestMetadata("captureInlinableAndOther") @TestMetadata("captureInlinableAndOther")
public void testCaptureInlinableAndOther() throws Exception { public void testCaptureInlinableAndOther() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/captureInlinableAndOther"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/captureInlinableAndOther");
} }
@TestMetadata("captureThisAndReceiver") @TestMetadata("captureThisAndReceiver")
public void testCaptureThisAndReceiver() throws Exception { public void testCaptureThisAndReceiver() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/captureThisAndReceiver"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/captureThisAndReceiver");
} }
@TestMetadata("classObject") @TestMetadata("classObject")
public void testClassObject() throws Exception { public void testClassObject() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/classObject"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/classObject");
} }
@TestMetadata("closureChain") @TestMetadata("closureChain")
public void testClosureChain() throws Exception { public void testClosureChain() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/closureChain"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/closureChain");
} }
@TestMetadata("extension") @TestMetadata("extension")
public void testExtension() throws Exception { public void testExtension() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/extension"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/extension");
} }
@TestMetadata("forEachLine") @TestMetadata("forEachLine")
public void testForEachLine() throws Exception { public void testForEachLine() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/forEachLine"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/forEachLine");
} }
@TestMetadata("generics") @TestMetadata("generics")
public void testGenerics() throws Exception { public void testGenerics() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/generics"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/generics");
} }
@TestMetadata("identityCheck") @TestMetadata("identityCheck")
public void testIdentityCheck() throws Exception { public void testIdentityCheck() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/identityCheck"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/identityCheck");
} }
@TestMetadata("ifBranches") @TestMetadata("ifBranches")
public void testIfBranches() throws Exception { public void testIfBranches() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/ifBranches"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/ifBranches");
} }
@TestMetadata("iinc") @TestMetadata("iinc")
public void testIinc() throws Exception { public void testIinc() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/iinc"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/iinc");
} }
@TestMetadata("inlineChain") @TestMetadata("inlineChain")
public void testInlineChain() throws Exception { public void testInlineChain() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/inlineChain"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/inlineChain");
} }
@TestMetadata("lambdaClassClash") @TestMetadata("lambdaClassClash")
public void testLambdaClassClash() throws Exception { public void testLambdaClassClash() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/lambdaClassClash"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/lambdaClassClash");
} }
@TestMetadata("lambdaCloning") @TestMetadata("lambdaCloning")
public void testLambdaCloning() throws Exception { public void testLambdaCloning() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/lambdaCloning"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/lambdaCloning");
} }
@TestMetadata("lambdaInLambda") @TestMetadata("lambdaInLambda")
public void testLambdaInLambda() throws Exception { public void testLambdaInLambda() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/lambdaInLambda"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/lambdaInLambda");
} }
@TestMetadata("lambdaInLambda2") @TestMetadata("lambdaInLambda2")
public void testLambdaInLambda2() throws Exception { public void testLambdaInLambda2() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/lambdaInLambda2"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/lambdaInLambda2");
} }
@TestMetadata("lambdaInLambdaNoInline") @TestMetadata("lambdaInLambdaNoInline")
public void testLambdaInLambdaNoInline() throws Exception { public void testLambdaInLambdaNoInline() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/lambdaInLambdaNoInline"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/lambdaInLambdaNoInline");
} }
@TestMetadata("localFunInLambda") @TestMetadata("localFunInLambda")
public void testLocalFunInLambda() throws Exception { public void testLocalFunInLambda() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/localFunInLambda"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/localFunInLambda");
} }
@TestMetadata("noInline") @TestMetadata("noInline")
public void testNoInline() throws Exception { public void testNoInline() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/noInline"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/noInline");
} }
@TestMetadata("noInlineLambdaChain") @TestMetadata("noInlineLambdaChain")
public void testNoInlineLambdaChain() throws Exception { public void testNoInlineLambdaChain() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/noInlineLambdaChain"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/noInlineLambdaChain");
} }
@TestMetadata("noInlineLambdaChainWithCapturedInline") @TestMetadata("noInlineLambdaChainWithCapturedInline")
public void testNoInlineLambdaChainWithCapturedInline() throws Exception { public void testNoInlineLambdaChainWithCapturedInline() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/noInlineLambdaChainWithCapturedInline"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/noInlineLambdaChainWithCapturedInline");
} }
@TestMetadata("noInlineLambdaX2") @TestMetadata("noInlineLambdaX2")
public void testNoInlineLambdaX2() throws Exception { public void testNoInlineLambdaX2() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/noInlineLambdaX2"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/noInlineLambdaX2");
} }
@TestMetadata("params") @TestMetadata("params")
public void testParams() throws Exception { public void testParams() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/params"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/params");
} }
@TestMetadata("plusAssign") @TestMetadata("plusAssign")
public void testPlusAssign() throws Exception { public void testPlusAssign() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/plusAssign"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/plusAssign");
} }
@TestMetadata("regeneratedLambdaName") @TestMetadata("regeneratedLambdaName")
public void testRegeneratedLambdaName() throws Exception { public void testRegeneratedLambdaName() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/regeneratedLambdaName"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/regeneratedLambdaName");
} }
@TestMetadata("rootConstructor") @TestMetadata("rootConstructor")
public void testRootConstructor() throws Exception { public void testRootConstructor() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/rootConstructor"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/rootConstructor");
} }
@TestMetadata("sameCaptured") @TestMetadata("sameCaptured")
public void testSameCaptured() throws Exception { public void testSameCaptured() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/sameCaptured"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/sameCaptured");
} }
@TestMetadata("severalClosures") @TestMetadata("severalClosures")
public void testSeveralClosures() throws Exception { public void testSeveralClosures() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/severalClosures"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/severalClosures");
} }
@TestMetadata("severalUsage") @TestMetadata("severalUsage")
public void testSeveralUsage() throws Exception { public void testSeveralUsage() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/severalUsage"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/severalUsage");
} }
@TestMetadata("simpleCapturingInClass") @TestMetadata("simpleCapturingInClass")
public void testSimpleCapturingInClass() throws Exception { public void testSimpleCapturingInClass() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/simpleCapturingInClass"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/simpleCapturingInClass");
} }
@TestMetadata("simpleCapturingInPackage") @TestMetadata("simpleCapturingInPackage")
public void testSimpleCapturingInPackage() throws Exception { public void testSimpleCapturingInPackage() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/simpleCapturingInPackage"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/simpleCapturingInPackage");
} }
@TestMetadata("simpleDouble") @TestMetadata("simpleDouble")
public void testSimpleDouble() throws Exception { public void testSimpleDouble() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/simpleDouble"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/simpleDouble");
} }
@TestMetadata("simpleEnum") @TestMetadata("simpleEnum")
public void testSimpleEnum() throws Exception { public void testSimpleEnum() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/simpleEnum"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/simpleEnum");
} }
@TestMetadata("simpleGenerics") @TestMetadata("simpleGenerics")
public void testSimpleGenerics() throws Exception { public void testSimpleGenerics() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/simpleGenerics"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/simpleGenerics");
} }
@TestMetadata("simpleInt") @TestMetadata("simpleInt")
public void testSimpleInt() throws Exception { public void testSimpleInt() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/simpleInt"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/simpleInt");
} }
@TestMetadata("simpleLambda") @TestMetadata("simpleLambda")
public void testSimpleLambda() throws Exception { public void testSimpleLambda() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/simpleLambda"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/simpleLambda");
} }
@TestMetadata("simpleObject") @TestMetadata("simpleObject")
public void testSimpleObject() throws Exception { public void testSimpleObject() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/simpleObject"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/simpleObject");
} }
@TestMetadata("stackHeightBug") @TestMetadata("stackHeightBug")
public void testStackHeightBug() throws Exception { public void testStackHeightBug() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/stackHeightBug"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/stackHeightBug");
} }
@TestMetadata("trait") @TestMetadata("trait")
public void testTrait() throws Exception { public void testTrait() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/trait"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/trait");
} }
@TestMetadata("tryCatch") @TestMetadata("tryCatch")
public void testTryCatch() throws Exception { public void testTryCatch() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/tryCatch"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/tryCatch");
} }
@TestMetadata("tryCatch2") @TestMetadata("tryCatch2")
public void testTryCatch2() throws Exception { public void testTryCatch2() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/tryCatch2"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/tryCatch2");
} }
@TestMetadata("tryCatchFinally") @TestMetadata("tryCatchFinally")
public void testTryCatchFinally() throws Exception { public void testTryCatchFinally() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/tryCatchFinally"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/tryCatchFinally");
} }
@TestMetadata("use") @TestMetadata("use")
public void testUse() throws Exception { public void testUse() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/use"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/use");
} }
@TestMetadata("vararg") @TestMetadata("vararg")
public void testVararg() throws Exception { public void testVararg() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/vararg"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/vararg");
} }
@TestMetadata("with") @TestMetadata("with")
public void testWith() throws Exception { public void testWith() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/with"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/with");
} }
@TestMetadata("withoutInline") @TestMetadata("withoutInline")
public void testWithoutInline() throws Exception { public void testWithoutInline() throws Exception {
doBoxTest("compiler/testData/codegen/boxInline/withoutInline"); doBoxTestWithInlineCheck("compiler/testData/codegen/boxInline/withoutInline");
} }
} }
@@ -141,11 +141,11 @@ fun main(args: Array<String>) {
} }
testClass(javaClass<AbstractBlackBoxCodegenTest>(), "BlackBoxInlineCodegenTestGenerated") { testClass(javaClass<AbstractBlackBoxCodegenTest>(), "BlackBoxInlineCodegenTestGenerated") {
model("codegen/boxInline", extension = null, recursive = false, testMethod = "doTestMultiFile") model("codegen/boxInline", extension = null, recursive = false, testMethod = "doTestMultiFileWithInlineCheck")
} }
testClass(javaClass<AbstractCompileKotlinAgainstKotlinTest>(), "CompileKotlinAgainstInlineKotlinTestGenerated") { testClass(javaClass<AbstractCompileKotlinAgainstKotlinTest>(), "CompileKotlinAgainstInlineKotlinTestGenerated") {
model("codegen/boxInline", extension = null, recursive = false, testMethod = "doBoxTest") model("codegen/boxInline", extension = null, recursive = false, testMethod = "doBoxTestWithInlineCheck")
} }
testClass(javaClass<AbstractBlackBoxCodegenTest>(), "BlackBoxMultiFileCodegenTestGenerated") { testClass(javaClass<AbstractBlackBoxCodegenTest>(), "BlackBoxMultiFileCodegenTestGenerated") {