Generate package$src files for each package

This commit is contained in:
Natalia.Ukhorskaya
2013-02-28 16:01:42 +04:00
parent a9415204f6
commit faf994d872
15 changed files with 138 additions and 103 deletions
@@ -84,8 +84,6 @@ public class NamespaceCodegen extends MemberCodegen {
} }
public void generate(CompilationErrorHandler errorHandler) { public void generate(CompilationErrorHandler errorHandler) {
boolean multiFile = CodegenBinding.isMultiFileNamespace(state.getBindingContext(), name);
if (shouldGenerateNSClass(files)) { if (shouldGenerateNSClass(files)) {
AnnotationVisitor packageClassAnnotation = v.getClassBuilder().newAnnotation(JvmStdlibNames.JET_PACKAGE_CLASS.getDescriptor(), true); AnnotationVisitor packageClassAnnotation = v.getClassBuilder().newAnnotation(JvmStdlibNames.JET_PACKAGE_CLASS.getDescriptor(), true);
packageClassAnnotation.visit(JvmStdlibNames.ABI_VERSION_NAME, JvmAbi.VERSION); packageClassAnnotation.visit(JvmStdlibNames.ABI_VERSION_NAME, JvmAbi.VERSION);
@@ -95,7 +93,7 @@ public class NamespaceCodegen extends MemberCodegen {
for (JetFile file : files) { for (JetFile file : files) {
VirtualFile vFile = file.getVirtualFile(); VirtualFile vFile = file.getVirtualFile();
try { try {
generate(file, multiFile); generate(file);
} }
catch (ProcessCanceledException e) { catch (ProcessCanceledException e) {
throw e; throw e;
@@ -117,19 +115,17 @@ public class NamespaceCodegen extends MemberCodegen {
} }
} }
private void generate(JetFile file, boolean multiFile) { private void generate(JetFile file) {
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file); NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
assert descriptor != null : "No namespace found for file " + file + " declared package: " + file.getPackageName(); assert descriptor != null : "No namespace found for file " + file + " declared package: " + file.getPackageName();
int countOfDeclarationsInSrcClass = 0;
for (JetDeclaration declaration : file.getDeclarations()) { for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder()); genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
} }
else if (declaration instanceof JetNamedFunction) { else if (declaration instanceof JetNamedFunction) {
if (!multiFile) { countOfDeclarationsInSrcClass++;
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
} }
else if (declaration instanceof JetClassOrObject) { else if (declaration instanceof JetClassOrObject) {
if (state.isGenerateDeclaredClasses()) { if (state.isGenerateDeclaredClasses()) {
@@ -141,47 +137,38 @@ public class NamespaceCodegen extends MemberCodegen {
} }
} }
if (multiFile) { if (countOfDeclarationsInSrcClass > 0) {
int k = 0; String namespaceInternalName = JvmClassName.byFqNameWithoutInnerClasses(
PackageClassUtils.getPackageClassFqName(name)).getInternalName();
String className = getMultiFileNamespaceInternalName(namespaceInternalName, file);
ClassBuilder builder = state.getFactory().forNamespacepart(className, file);
builder.defineClass(file, V1_6,
ACC_PUBLIC | ACC_FINAL,
className,
null,
//"jet/lang/Namespace",
"java/lang/Object",
new String[0]
);
builder.visitSource(file.getName(), null);
for (JetDeclaration declaration : file.getDeclarations()) { for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetNamedFunction) { if (declaration instanceof JetNamedFunction) {
k++; {
} final CodegenContext context =
} CodegenContext.STATIC.intoNamespace(descriptor);
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, builder);
if (k > 0) { }
String namespaceInternalName = JvmClassName.byFqNameWithoutInnerClasses( {
PackageClassUtils.getPackageClassFqName(name)).getInternalName(); final CodegenContext context =
String className = getMultiFileNamespaceInternalName(namespaceInternalName, file); CodegenContext.STATIC.intoNamespacePart(className, descriptor);
ClassBuilder builder = state.getFactory().forNamespacepart(className, file); genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
builder.defineClass(file, V1_6,
ACC_PUBLIC | ACC_FINAL,
className,
null,
//"jet/lang/Namespace",
"java/lang/Object",
new String[0]
);
builder.visitSource(file.getName(), null);
for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetNamedFunction) {
{
final CodegenContext context =
CodegenContext.STATIC.intoNamespace(descriptor);
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, builder);
}
{
final CodegenContext context =
CodegenContext.STATIC.intoNamespacePart(className, descriptor);
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
} }
} }
builder.done();
} }
builder.done();
} }
} }
@@ -3,4 +3,4 @@ fun foo() {
42 42
} }
// 3 // 1 3
@@ -8,4 +8,4 @@ fun foo() {
} }
} }
// 2 3 6 7 6 // 1 2 3 6 7 6
@@ -12,4 +12,4 @@ fun foo() {
} }
} }
// 2 3 5 8 9 11 8 // 1 2 3 5 8 9 11 8
@@ -12,4 +12,4 @@ fun foo() {
} }
} }
// 2 3 5 8 9 11 8 // 1 2 3 5 8 9 11 8
@@ -16,4 +16,4 @@ fun foo() {
} }
} }
// 2 3 7 5 7 10 11 15 13 15 10 // 1 2 3 7 5 7 10 11 15 13 15 10
@@ -12,4 +12,4 @@ fun foo() {
} }
} }
// 2 3 5 8 9 11 8 // 1 2 3 5 8 9 11 8
+1 -1
View File
@@ -12,4 +12,4 @@ fun foo(x: Int) {
} }
} }
// 3 4 5 9 10 11 8 // 1 3 4 5 9 10 11 8
@@ -12,4 +12,4 @@ fun foo(x: Int) {
} }
} }
// 2 3 4 5 8 9 10 11 8 // 1 2 3 4 5 8 9 10 11 8
@@ -1,2 +1,4 @@
fun foo(param: Int = test.lineNumber()) { class A {
fun foo(param: Int = test.lineNumber()) {
}
} }
@@ -17,7 +17,11 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import jet.JetObject; import jet.JetObject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.ConfigurationKind;
import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import java.lang.annotation.*; import java.lang.annotation.*;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@@ -32,41 +36,65 @@ public class AnnotationGenTest extends CodegenTestCase {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL); createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL);
} }
public void testPropField() throws NoSuchFieldException, NoSuchMethodException { private ClassLoader loadFileGetClassLoader(@NotNull String text) {
loadText("[Deprecated] var x = 0"); loadText(text);
Class aClass = generateNamespaceClass(); ClassFileFactory state = generateClassesInFile();
assertNull(aClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class)); return createClassLoader(state);
assertNull(aClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
assertNotNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class));
} }
public void testPropGetter() throws NoSuchFieldException, NoSuchMethodException { private Class getPackageClass(@NotNull ClassLoader loader) throws ClassNotFoundException {
loadText("var x = 0\n" + return loader.loadClass(PackageClassUtils.getPackageClassName(JetPsiUtil.getFQName(myFiles.getPsiFile())));
}
private Class getPackageSrcClass(@NotNull ClassLoader loader) throws ClassNotFoundException {
return loader.loadClass(NamespaceCodegen.getNamespacePartInternalName(myFiles.getPsiFile()));
}
public void testPropField() throws Exception {
ClassLoader loader = loadFileGetClassLoader("[Deprecated] var x = 0");
Class packageClass = getPackageClass(loader);
assertNull(packageClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNull(packageClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
Class srcClass = getPackageSrcClass(loader);
assertNull(srcClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNull(srcClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
assertNotNull(srcClass.getDeclaredField("x").getAnnotation(Deprecated.class));
}
public void testPropGetter() throws Exception {
ClassLoader loader = loadFileGetClassLoader("var x = 0\n" +
"[Deprecated] get"); "[Deprecated] get");
Class packageClass = getPackageClass(loader);
Class aClass = generateNamespaceClass(); assertNotNull(packageClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNotNull(aClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class)); assertNull(packageClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
assertNull(aClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class)); Class srcClass = getPackageSrcClass(loader);
assertNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class)); assertNotNull(srcClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNull(srcClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
assertNull(srcClass.getDeclaredField("x").getAnnotation(Deprecated.class));
} }
public void testPropSetter() throws NoSuchFieldException, NoSuchMethodException { public void testPropSetter() throws Exception {
loadText("var x = 0\n" + ClassLoader loader = loadFileGetClassLoader("var x = 0\n" +
"[Deprecated] set"); "[Deprecated] set");
Class aClass = generateNamespaceClass(); Class packageClass = getPackageClass(loader);
assertNull(aClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class)); assertNull(packageClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNotNull(aClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class)); assertNotNull(packageClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
assertNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class)); Class scrClass = getPackageSrcClass(loader);
assertNull(scrClass.getDeclaredMethod("getX").getAnnotation(Deprecated.class));
assertNotNull(scrClass.getDeclaredMethod("setX", int.class).getAnnotation(Deprecated.class));
assertNull(scrClass.getDeclaredField("x").getAnnotation(Deprecated.class));
} }
public void testAnnotationForParamInGlobalFunction() throws NoSuchFieldException, NoSuchMethodException { public void testAnnotationForParamInGlobalFunction() throws Exception {
loadText("fun x([Deprecated] i: Int) {}"); ClassLoader loader = loadFileGetClassLoader("fun x([Deprecated] i: Int) {}");
Class aClass = generateNamespaceClass(); Class packageClass = getPackageClass(loader);
Method x = aClass.getMethod("x", int.class); Method packageClassMethod = packageClass.getMethod("x", int.class);
assertNotNull(x); assertNotNull(packageClassMethod);
// Get annotations for first parameter assertNotNull(getDeprecatedAnnotationFromList(packageClassMethod.getParameterAnnotations()[0]));
Annotation[] annotations = x.getParameterAnnotations()[0]; Class srcClass = getPackageSrcClass(loader);
assertNotNull(getDeprecatedAnnotationFromList(annotations)); Method srcClassMethod = srcClass.getMethod("x", int.class);
assertNotNull(srcClassMethod);
assertNotNull(getDeprecatedAnnotationFromList(srcClassMethod.getParameterAnnotations()[0]));
} }
public void testAnnotationForParamInLocalFunction() throws NoSuchFieldException, NoSuchMethodException { public void testAnnotationForParamInLocalFunction() throws NoSuchFieldException, NoSuchMethodException {
@@ -102,23 +130,29 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class)); assertNotNull(aClass.getDeclaredField("x").getAnnotation(Deprecated.class));
} }
public void testAnnotationWithParamForParamInFunction() throws NoSuchFieldException, NoSuchMethodException { public void testAnnotationWithParamForParamInFunction() throws Exception {
loadText("import java.lang.annotation.*\n" + ClassLoader loader = loadFileGetClassLoader("import java.lang.annotation.*\n" +
"Retention(RetentionPolicy.RUNTIME) annotation class A(val a: String)\n" + "Retention(RetentionPolicy.RUNTIME) annotation class A(val a: String)\n" +
"fun x(A(\"239\") i: Int) {}"); "fun x(A(\"239\") i: Int) {}");
Class aClass = generateNamespaceClass(); Class packageClass = getPackageSrcClass(loader);
Method x = aClass.getMethod("x", int.class); Method packageClassMethod = packageClass.getMethod("x", int.class);
assertNotNull(x); assertNotNull(packageClassMethod);
// Get annotations for first parameter assertNotNull(getAnnotationByName(packageClassMethod.getParameterAnnotations()[0], "A"));
Annotation[] annotations = x.getParameterAnnotations()[0];
Annotation resultAnnotation = null; Class srcClass = getPackageSrcClass(loader);
Method srcClassMethod = srcClass.getMethod("x", int.class);
assertNotNull(srcClassMethod);
assertNotNull(getAnnotationByName(srcClassMethod.getParameterAnnotations()[0], "A"));
}
@Nullable
private Annotation getAnnotationByName(@NotNull Annotation[] annotations, @NotNull String name) {
for (Annotation annotation : annotations) { for (Annotation annotation : annotations) {
if (annotation.annotationType().getCanonicalName().equals("A")) { if (annotation.annotationType().getCanonicalName().equals(name)) {
resultAnnotation = annotation; return annotation;
break;
} }
} }
assertNotNull(resultAnnotation); return null;
} }
private Deprecated getDeprecatedAnnotationFromList(Annotation[] annotations) { private Deprecated getDeprecatedAnnotationFromList(Annotation[] annotations) {
@@ -138,12 +172,17 @@ public class AnnotationGenTest extends CodegenTestCase {
assertNotNull(annotation); assertNotNull(annotation);
} }
public void testMethod() throws NoSuchFieldException, NoSuchMethodException { public void testMethod() throws Exception {
loadText("[Deprecated] fun x () {}"); ClassLoader loader = loadFileGetClassLoader("[Deprecated] fun x () {}");
Class aClass = generateNamespaceClass();
Method x = aClass.getDeclaredMethod("x"); Class packageClass = getPackageClass(loader);
Deprecated annotation = (Deprecated) x.getAnnotation(Deprecated.class); Method packageClassMethod = packageClass.getDeclaredMethod("x");
assertNotNull(annotation); assertNotNull(packageClassMethod.getAnnotation(Deprecated.class));
Class srcClass = getPackageSrcClass(loader);
Method srcClassMethod = srcClass.getDeclaredMethod("x");
assertNotNull(srcClassMethod.getAnnotation(Deprecated.class));
} }
public void testClass() throws NoSuchFieldException, NoSuchMethodException { public void testClass() throws NoSuchFieldException, NoSuchMethodException {
@@ -140,6 +140,12 @@ public abstract class CodegenTestCase extends UsefulTestCase {
return generateClass(name.getFqName().getFqName()); return generateClass(name.getFqName().getFqName());
} }
@NotNull
protected Class<?> generateNamespaceSrcClass() {
String name = NamespaceCodegen.getNamespacePartInternalName(myFiles.getPsiFile());
return generateClass(name);
}
@NotNull @NotNull
protected Class generateClass(@NotNull String name) { protected Class generateClass(@NotNull String name) {
try { try {
@@ -66,8 +66,9 @@ public class LineNumberTest extends TestCaseWithTmpdir {
super.setUp(); super.setUp();
JetCoreEnvironment environment = createEnvironment(); JetCoreEnvironment environment = createEnvironment();
JetFile psiFile = JetPsiFactory.createFile(environment.getProject(), JetFile psiFile = JetTestUtils.createFile(LINE_NUMBER_FUN + ".kt",
"package test;\n\npublic fun " + LINE_NUMBER_FUN + "(): Int = 0\n"); "package test;\n\npublic fun " + LINE_NUMBER_FUN + "(): Int = 0\n",
environment.getProject());
ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile); ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile);
CompileEnvironmentUtil.writeToOutputDirectory(classFileFactory, tmpdir); CompileEnvironmentUtil.writeToOutputDirectory(classFileFactory, tmpdir);
@@ -58,7 +58,7 @@ public class CompileEnvironmentTest extends TestCase {
try { try {
final List<String> entries = listEntries(is); final List<String> entries = listEntries(is);
assertTrue(entries.contains("Smoke/" + PackageClassUtils.getPackageClassName(new FqName("Smoke")) + ".class")); assertTrue(entries.contains("Smoke/" + PackageClassUtils.getPackageClassName(new FqName("Smoke")) + ".class"));
assertEquals(1, entries.size()); assertEquals(2, entries.size());
} }
finally { finally {
is.close(); is.close();
@@ -88,7 +88,7 @@ public class CompileEnvironmentTest extends TestCase {
"-annotations", jdkAnnotations.getAbsolutePath()); "-annotations", jdkAnnotations.getAbsolutePath());
Assert.assertEquals(ExitCode.OK, exitCode); Assert.assertEquals(ExitCode.OK, exitCode);
assertEquals(1, out.listFiles().length); assertEquals(1, out.listFiles().length);
assertEquals(1, out.listFiles()[0].listFiles().length); assertEquals(2, out.listFiles()[0].listFiles().length);
} finally { } finally {
FileUtil.delete(tempDir); FileUtil.delete(tempDir);
} }
@@ -144,7 +144,7 @@ public final class LoadDescriptorUtil {
public static JetFileAndExhaust createJetFileAndAnalyze(@NotNull File kotlinFile, @NotNull Disposable disposable, @NotNull ConfigurationKind configurationKind) public static JetFileAndExhaust createJetFileAndAnalyze(@NotNull File kotlinFile, @NotNull Disposable disposable, @NotNull ConfigurationKind configurationKind)
throws IOException { throws IOException {
JetCoreEnvironment jetCoreEnvironment = createEnvironmentWithMockJdkAndIdeaAnnotations(disposable, configurationKind); JetCoreEnvironment jetCoreEnvironment = createEnvironmentWithMockJdkAndIdeaAnnotations(disposable, configurationKind);
JetFile jetFile = createFile(jetCoreEnvironment.getProject(), kotlinFile.getName(), FileUtil.loadFile(kotlinFile, true)); JetFile jetFile = JetTestUtils.createFile(kotlinFile.getName(), FileUtil.loadFile(kotlinFile, true), jetCoreEnvironment.getProject());
AnalyzeExhaust exhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( AnalyzeExhaust exhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors(
jetFile, Collections.<AnalyzerScriptParameter>emptyList()); jetFile, Collections.<AnalyzerScriptParameter>emptyList());
return new JetFileAndExhaust(jetFile, exhaust); return new JetFileAndExhaust(jetFile, exhaust);