line number codegen tests

This commit is contained in:
Alexander Udalov
2012-08-20 22:49:22 +04:00
parent 86e772b852
commit ed1f22111b
18 changed files with 329 additions and 1 deletions
@@ -0,0 +1,5 @@
fun foo() {
{
test.lineNumber()
}()
}
+3
View File
@@ -0,0 +1,3 @@
package test
public fun lineNumber(): Int = 0
+7
View File
@@ -0,0 +1,7 @@
class A {
val prop = test.lineNumber()
fun foo() {
test.lineNumber()
}
}
@@ -0,0 +1,9 @@
class A {
class object {
val prop = test.lineNumber()
fun foo(): Int {
return test.lineNumber()
}
}
}
@@ -0,0 +1,2 @@
fun foo(param: Int = test.lineNumber()) {
}
+9
View File
@@ -0,0 +1,9 @@
enum class E {
E1
fun foo() = {
test.lineNumber()
}
val prop = test.lineNumber()
}
+5
View File
@@ -0,0 +1,5 @@
fun foo() {
for (i in 0..test.lineNumber()) {
test.lineNumber()
}
}
+15
View File
@@ -0,0 +1,15 @@
fun foo() {
if (test.lineNumber() > 0) {
test.lineNumber()
}
if (test.lineNumber() > 0) else {
test.lineNumber()
}
if (test.lineNumber() > 0) {
test.lineNumber()
} else {
test.lineNumber()
}
}
@@ -0,0 +1,9 @@
fun foo() {
test.lineNumber()
fun bar() {
test.lineNumber()
}
test.lineNumber()
bar()
test.lineNumber()
}
+5
View File
@@ -0,0 +1,5 @@
object A {
fun foo() = test.lineNumber()
val prop = test.lineNumber()
}
@@ -0,0 +1,6 @@
class A {
val prop : Int
get() {
return test.lineNumber()
}
}
+3
View File
@@ -0,0 +1,3 @@
fun main(args: Array<String>) {
test.lineNumber()
}
+3
View File
@@ -0,0 +1,3 @@
fun foo() = test.lineNumber()
val prop = test.lineNumber()
+7
View File
@@ -0,0 +1,7 @@
trait A {
fun foo() = test.lineNumber()
fun bar(): Int {
return test.lineNumber()
}
}
+7
View File
@@ -0,0 +1,7 @@
fun foo() {
try {
test.lineNumber()
} catch (e: Exception) {
test.lineNumber()
}
}
+9
View File
@@ -0,0 +1,9 @@
fun foo() {
while (test.lineNumber() > 0) {
test.lineNumber()
}
do {
test.lineNumber()
} while (test.lineNumber() > 0)
}
@@ -60,7 +60,7 @@ public class GenerationUtils {
@NotNull
private static GenerationState compileFilesGetGenerationState(@NotNull AnalyzeExhaust analyzeExhaust, @NotNull List<JetFile> files) {
analyzeExhaust.throwIfError();
GenerationState state = new GenerationState(ClassBuilderFactories.binaries(false), analyzeExhaust, files);
GenerationState state = new GenerationState(ClassBuilderFactories.TEST, analyzeExhaust, files);
state.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION);
return state;
}
@@ -0,0 +1,224 @@
/*
* 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.jet.codegen;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.asm4.*;
import org.jetbrains.jet.CompileCompilerDependenciesTest;
import org.jetbrains.jet.ConfigurationKind;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.TestJdkKind;
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.parsing.JetParsingTest;
import org.jetbrains.jet.test.TestCaseWithTmpdir;
import org.jetbrains.jet.utils.ExceptionUtils;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author udalov
*/
public class LineNumberTest extends TestCaseWithTmpdir {
private final String LINE_NUMBER_FUN = "lineNumber";
private final Pattern TEST_LINE_NUMBER_PATTERN = Pattern.compile("^.*test." + LINE_NUMBER_FUN + "\\(\\).*$");
private String getTestDataPath() {
return JetParsingTest.getTestDataDir() + "/lineNumber";
}
@Override
public void setUp() throws Exception {
super.setUp();
JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(myTestRootDisposable, ConfigurationKind.JDK_ONLY);
File base = new File(getTestDataPath(), "base.kt");
String text = FileUtil.loadFile(base);
JetFile psiFile = JetTestUtils.createFile(base.getName(), text, jetCoreEnvironment.getProject());
ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile);
CompileEnvironmentUtil.writeToOutputDirectory(classFileFactory, tmpdir);
}
private void doTest(File file) {
JetCoreEnvironment jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable, CompileCompilerDependenciesTest
.compilerConfigurationForTests(ConfigurationKind.JDK_ONLY, TestJdkKind.MOCK_JDK, JetTestUtils.getAnnotationsJar(), tmpdir));
String text;
try {
text = FileUtil.loadFile(file);
}
catch (IOException e) {
throw ExceptionUtils.rethrow(e);
}
JetFile psiFile = JetTestUtils.createFile(file.getName(), text, jetCoreEnvironment.getProject());
assert psiFile != null;
List<Integer> expectedLineNumbers = extractSelectedLineNumbers(text);
GenerationState state = GenerationUtils.compileFileGetGenerationStateForTest(psiFile);
ClassFileFactory factory = state.getFactory();
List<Integer> actualLineNumbers = Lists.newArrayList();
for (String filename : factory.files()) {
ClassReader cr = new ClassReader(factory.asBytes(filename));
try {
actualLineNumbers.addAll(readLineNumbers(cr));
}
catch (Throwable e) {
System.out.println(state.createText());
throw ExceptionUtils.rethrow(e);
}
}
assertSameElements(actualLineNumbers, expectedLineNumbers);
}
private void doTest() {
doTest(new File(getTestDataPath() + "/" + getTestName(true) + ".kt"));
}
private List<Integer> extractSelectedLineNumbers(String fileContent) {
List<Integer> lineNumbers = Lists.newArrayList();
String[] lines = StringUtil.convertLineSeparators(fileContent).split("\n");
for (int i = 0; i < lines.length; i++) {
Matcher matcher = TEST_LINE_NUMBER_PATTERN.matcher(lines[i]);
if (matcher.matches()) {
lineNumbers.add(i + 1);
}
}
return lineNumbers;
}
private List<Integer> readLineNumbers(ClassReader cr) {
final List<Label> labels = Lists.newArrayList();
final Map<Label, Integer> labels2LineNumbers = Maps.newHashMap();
ClassVisitor visitor = new ClassVisitor(Opcodes.ASM4) {
@Override
public MethodVisitor visitMethod(int access, String name, final String desc, final String signature, String[] exceptions) {
return new MethodVisitor(Opcodes.ASM4) {
private Label lastLabel;
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
if (LINE_NUMBER_FUN.equals(name)) {
assert lastLabel != null : "A function call with no preceding label";
labels.add(lastLabel);
}
lastLabel = null;
}
@Override
public void visitLabel(Label label) {
lastLabel = label;
}
@Override
public void visitLineNumber(int line, Label start) {
labels2LineNumbers.put(start, line);
}
};
}
};
cr.accept(visitor, ClassReader.SKIP_FRAMES);
List<Integer> lineNumbers = Lists.newArrayList();
for (Label label : labels) {
Integer lineNumber = labels2LineNumbers.get(label);
assert lineNumber != null : "No line number found for a label";
lineNumbers.add(lineNumber);
}
return lineNumbers;
}
public void testAnonymousFunction() {
doTest();
}
public void testClass() {
doTest();
}
public void testClassObject() {
doTest();
}
public void testDefaultParameter() {
doTest();
}
public void testEnum() {
doTest();
}
public void testFor() {
doTest();
}
public void testIf() {
doTest();
}
public void testLocalFunction() {
doTest();
}
public void testObject() {
doTest();
}
public void testPropertyAccessor() {
doTest();
}
public void testPsvm() {
doTest();
}
public void testTopLevel() {
doTest();
}
public void testTrait() {
doTest();
}
public void testTryCatch() {
doTest();
}
public void testWhile() {
doTest();
}
}