Don't break the world if enum in annotation isn't found
This commit is contained in:
@@ -50,4 +50,9 @@ public class ErrorValue implements CompileTimeConstant<Void> {
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +385,8 @@ public class ErrorUtils {
|
||||
return createErrorType(value + " is not allowed here", value.getType().getMemberScope());
|
||||
}
|
||||
|
||||
public static ClassifierDescriptor getErrorClass() {
|
||||
@NotNull
|
||||
public static ClassDescriptor getErrorClass() {
|
||||
return ERROR_CLASS;
|
||||
}
|
||||
|
||||
|
||||
BIN
Binary file not shown.
+12
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
// To regenerate this test:
|
||||
// 1. Compile this file
|
||||
// 2. Delete test/E.class
|
||||
// 3. Pack test/ into jar
|
||||
|
||||
enum class E { ENTRY }
|
||||
|
||||
annotation class Anno(val e: E)
|
||||
|
||||
Anno(E.ENTRY) open class Class
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
class Subclass : Class()
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
internal final annotation class Anno : jet.Annotation {
|
||||
public constructor Anno(/*0*/ e: [ERROR : test.E])
|
||||
internal final val e: [ERROR : test.E]
|
||||
}
|
||||
|
||||
test.Anno(e = Unresolved enum entry: test.E.ENTRY: [ERROR : Unresolved enum entry: test.E.ENTRY]) internal open class Class {
|
||||
public constructor Class()
|
||||
}
|
||||
|
||||
internal final class Subclass : test.Class {
|
||||
public constructor Subclass()
|
||||
}
|
||||
+3
-1
@@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.test.TestCaseWithTmpdir;
|
||||
import org.jetbrains.jet.test.util.DescriptorValidator;
|
||||
import org.jetbrains.jet.test.util.NamespaceComparator;
|
||||
import org.junit.Assert;
|
||||
|
||||
@@ -70,7 +71,8 @@ public abstract class AbstractCompileKotlinAgainstCustomJavaTest extends TestCas
|
||||
NamespaceDescriptor namespaceDescriptor = bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, namespaceFqn);
|
||||
assertNotNull("Failed to find namespace: " + namespaceFqn, namespaceDescriptor);
|
||||
|
||||
validateAndCompareNamespaceWithFile(namespaceDescriptor, NamespaceComparator.DONT_INCLUDE_METHODS_OF_OBJECT, expectedFile);
|
||||
validateAndCompareNamespaceWithFile(namespaceDescriptor, NamespaceComparator.DONT_INCLUDE_METHODS_OF_OBJECT.withValidationStrategy(
|
||||
DescriptorValidator.ValidationVisitor.ALLOW_ERROR_TYPES), expectedFile);
|
||||
}
|
||||
|
||||
private JetCoreEnvironment getEnvironment(File ktFile) {
|
||||
|
||||
+15
-1
@@ -31,7 +31,7 @@ import org.jetbrains.jet.jvm.compiler.AbstractCompileKotlinAgainstCustomJavaTest
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/compileKotlinAgainstCustomJava")
|
||||
@InnerTestClasses({CompileKotlinAgainstCustomJavaGenerated.DuplicateLibraries.class})
|
||||
@InnerTestClasses({CompileKotlinAgainstCustomJavaGenerated.DuplicateLibraries.class, CompileKotlinAgainstCustomJavaGenerated.MissingEnumReferencedInAnnotation.class})
|
||||
public class CompileKotlinAgainstCustomJavaGenerated extends AbstractCompileKotlinAgainstCustomJavaTest {
|
||||
public void testAllFilesPresentInCompileKotlinAgainstCustomJava() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/compileKotlinAgainstCustomJava"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
@@ -50,10 +50,24 @@ public class CompileKotlinAgainstCustomJavaGenerated extends AbstractCompileKotl
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/compileKotlinAgainstCustomJava/missingEnumReferencedInAnnotation")
|
||||
public static class MissingEnumReferencedInAnnotation extends AbstractCompileKotlinAgainstCustomJavaTest {
|
||||
public void testAllFilesPresentInMissingEnumReferencedInAnnotation() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/compileKotlinAgainstCustomJava/missingEnumReferencedInAnnotation"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("MissingEnumReferencedInAnnotation.kt")
|
||||
public void testMissingEnumReferencedInAnnotation() throws Exception {
|
||||
doTest("compiler/testData/compileKotlinAgainstCustomJava/missingEnumReferencedInAnnotation/MissingEnumReferencedInAnnotation.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite("CompileKotlinAgainstCustomJavaGenerated");
|
||||
suite.addTestSuite(CompileKotlinAgainstCustomJavaGenerated.class);
|
||||
suite.addTestSuite(DuplicateLibraries.class);
|
||||
suite.addTestSuite(MissingEnumReferencedInAnnotation.class);
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
|
||||
+29
-14
@@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.constants.EnumValue;
|
||||
import org.jetbrains.jet.lang.resolve.constants.ErrorValue;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
@@ -42,7 +43,7 @@ import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNotNull;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.IOException;
|
||||
@@ -184,8 +185,7 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
|
||||
if (ignoreAnnotation(desc)) return null;
|
||||
|
||||
FqName annotationFqName = convertJvmDescriptorToFqName(desc);
|
||||
final ClassDescriptor annotationClass = javaClassResolver.resolveClass(annotationFqName, IGNORE_KOTLIN_SOURCES);
|
||||
assert annotationClass != null : "Annotation class is not found: " + desc;
|
||||
final ClassDescriptor annotationClass = resolveAnnotationClass(annotationFqName);
|
||||
final AnnotationDescriptor annotation = new AnnotationDescriptor();
|
||||
annotation.setAnnotationType(annotationClass.getDefaultType());
|
||||
|
||||
@@ -194,22 +194,31 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
|
||||
@Override
|
||||
public void visit(String name, Object value) {
|
||||
CompileTimeConstant<?> argument = JavaAnnotationArgumentResolver.resolveCompileTimeConstantValue(value, null);
|
||||
if (argument != null) {
|
||||
setArgumentValueByName(name, argument);
|
||||
}
|
||||
setArgumentValueByName(name, argument != null ? argument : new ErrorValue("Unsupported annotation argument: " + name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(String name, String desc, String value) {
|
||||
FqName fqName = convertJvmDescriptorToFqName(desc);
|
||||
ClassDescriptor enumClass = javaClassResolver.resolveClass(fqName, IGNORE_KOTLIN_SOURCES);
|
||||
assert enumClass != null : "Enum class referenced in annotation is not found: " + desc;
|
||||
JetScope scope = DescriptorUtils.getEnumEntriesScope(enumClass);
|
||||
Collection<VariableDescriptor> properties = scope.getProperties(Name.identifier(value));
|
||||
assert properties.size() == 1 : "Enum class should have exactly one property with the referenced name: " + value +
|
||||
"\n" + properties + "\n" + enumClass;
|
||||
EnumValue enumValue = new EnumValue((PropertyDescriptor) properties.iterator().next());
|
||||
setArgumentValueByName(name, enumValue);
|
||||
setArgumentValueByName(name, enumEntryValue(fqName, Name.identifier(value)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private CompileTimeConstant<?> enumEntryValue(@NotNull FqName enumFqName, @NotNull Name name) {
|
||||
ClassDescriptor enumClass = javaClassResolver.resolveClass(enumFqName, IGNORE_KOTLIN_SOURCES);
|
||||
if (enumClass != null && enumClass.getKind() == ClassKind.ENUM_CLASS) {
|
||||
ClassDescriptor classObject = enumClass.getClassObjectDescriptor();
|
||||
if (classObject != null) {
|
||||
Collection<VariableDescriptor> properties = classObject.getDefaultType().getMemberScope().getProperties(name);
|
||||
if (properties.size() == 1) {
|
||||
VariableDescriptor property = properties.iterator().next();
|
||||
if (property instanceof PropertyDescriptor) {
|
||||
return new EnumValue((PropertyDescriptor) property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ErrorValue("Unresolved enum entry: " + enumFqName + "." + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,6 +236,12 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ClassDescriptor resolveAnnotationClass(@NotNull FqName fqName) {
|
||||
ClassDescriptor annotationClass = javaClassResolver.resolveClass(fqName, IGNORE_KOTLIN_SOURCES);
|
||||
return annotationClass != null ? annotationClass : ErrorUtils.getErrorClass();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<AnnotationDescriptor> loadCallableAnnotations(
|
||||
|
||||
Reference in New Issue
Block a user