Support [throws] annotation

This commit is contained in:
Andrey Breslav
2014-01-22 15:37:27 +04:00
parent b66a76e7d2
commit 4ab0b00bd3
17 changed files with 284 additions and 7 deletions
@@ -19,6 +19,8 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
@@ -28,11 +30,15 @@ import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.PackageContext;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
import org.jetbrains.jet.lang.resolve.constants.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
@@ -253,4 +259,34 @@ public class CodegenUtil {
return null;
}
@NotNull
public static String[] getExceptions(@NotNull Annotated annotatedDescriptor, @NotNull final JetTypeMapper mapper) {
// Can't say 'throws.class', because 'throws' is a reserved work in Java
AnnotationDescriptor annotation = annotatedDescriptor.getAnnotations().findAnnotation(new FqName("kotlin.throws"));
if (annotation == null) return ArrayUtil.EMPTY_STRING_ARRAY;
Collection<CompileTimeConstant<?>> values = annotation.getAllValueArguments().values();
if (values.isEmpty()) return ArrayUtil.EMPTY_STRING_ARRAY;
Object value = values.iterator().next();
if (!(value instanceof ArrayValue)) return ArrayUtil.EMPTY_STRING_ARRAY;
ArrayValue arrayValue = (ArrayValue) value;
List<String> strings = ContainerUtil.mapNotNull(
arrayValue.getValue(),
new Function<CompileTimeConstant<?>, String>() {
@Override
public String fun(CompileTimeConstant<?> constant) {
if (constant instanceof JavaClassValue) {
JavaClassValue classValue = (JavaClassValue) constant;
ClassDescriptor classDescriptor = DescriptorUtils.getClassDescriptorForType(classValue.getValue());
return mapper.mapClass(classDescriptor).getInternalName();
}
return null;
}
}
);
return strings.toArray(new String[strings.size()]);
}
}
@@ -109,7 +109,7 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
asmMethod.getName(),
asmMethod.getDescriptor(),
jvmSignature.getGenericsSignature(),
null);
CodegenUtil.getExceptions(functionDescriptor, typeMapper));
if (owner instanceof PackageFacadeContext) {
Type ownerType = ((PackageFacadeContext) owner).getDelegateToClassType();
@@ -462,7 +462,8 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
return;
}
int flags = getVisibilityAccessFlag(constructorDescriptor);
MethodVisitor mv = classBuilder.newMethod(null, flags, "<init>", "()V", null, null);
MethodVisitor mv = classBuilder.newMethod(null, flags, "<init>", "()V", null,
CodegenUtil.getExceptions(constructorDescriptor, state.getTypeMapper()));
if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
@@ -531,7 +532,8 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
}
MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC),
isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX,
descriptor, null, null);
descriptor, null,
CodegenUtil.getExceptions(functionDescriptor, typeMapper));
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
generateDefaultImpl(owner, signature, functionDescriptor, isStatic, mv, loadStrategy);
@@ -739,7 +741,8 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
int flags = ACC_PUBLIC;
MethodVisitor mv = v.newMethod(null, flags, delegateMethod.getName(), delegateMethod.getDescriptor(), null, null);
MethodVisitor mv = v.newMethod(null, flags, delegateMethod.getName(), delegateMethod.getDescriptor(), null,
CodegenUtil.getExceptions(functionDescriptor, typeMapper));
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
mv.visitCode();
@@ -1425,7 +1425,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method methodInTrait = typeMapper.mapSignature(fun.getOriginal()).getAsmMethod();
PsiElement origin = descriptorToDeclaration(bindingContext, fun);
MethodVisitor mv = v.newMethod(origin, flags, methodToGenerate.getName(), methodToGenerate.getDescriptor(), null, null);
MethodVisitor mv = v.newMethod(origin, flags, methodToGenerate.getName(), methodToGenerate.getDescriptor(), null,
CodegenUtil.getExceptions(fun, typeMapper));
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(fun);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {