JavaDescriptorResolver: Add resolve for annotation parameters (array, annotation, enum)
Temporary change testData for LoadJavaTest because enums in parameters of annotations in kotlin files is now unsupported
This commit is contained in:
+319
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* 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.jvm.compiler;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.di.InjectorForJavaSemanticServices;
|
||||
import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.constants.AnnotationValue;
|
||||
import org.jetbrains.jet.lang.resolve.constants.ArrayValue;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
|
||||
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.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
import org.jetbrains.jet.test.TestCaseWithTmpdir;
|
||||
import org.jetbrains.jet.utils.PathUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver.getValueParameterDescriptorForAnnotationParameter;
|
||||
|
||||
/**
|
||||
* @author Natalia Ukhorskaya
|
||||
*/
|
||||
public class AnnotationJavaDescriptorResolverTest extends TestCaseWithTmpdir {
|
||||
|
||||
private static final String PATH = "compiler/testData/javaDescriptorResolver/annotations/";
|
||||
private static final String DEFAULT_PACKAGE = "annotations";
|
||||
|
||||
private JavaDescriptorResolver javaDescriptorResolver;
|
||||
|
||||
public void testCustomAnnotationWithKotlinEnum() throws IOException {
|
||||
File testFile = new File(PATH + "kotlinEnum.kt");
|
||||
|
||||
LoadDescriptorUtil.compileKotlinToDirAndGetAnalyzeExhaust(testFile, tmpdir, myTestRootDisposable);
|
||||
|
||||
StringBuilder builder = new StringBuilder(tmpdir.getAbsolutePath());
|
||||
builder.append(File.pathSeparator);
|
||||
File runtimePath = PathUtil.getDefaultRuntimePath();
|
||||
if (runtimePath != null) {
|
||||
builder.append(runtimePath.getAbsolutePath());
|
||||
builder.append(File.pathSeparator);
|
||||
}
|
||||
|
||||
File annotationsPath = PathUtil.getJdkAnnotationsPath();
|
||||
if (annotationsPath != null) {
|
||||
builder.append(annotationsPath.getAbsolutePath());
|
||||
}
|
||||
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("customAnnotationWithKotlinEnum.java", builder.toString());
|
||||
|
||||
String annotationTypeName = DEFAULT_PACKAGE + ".MyAnnotation";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("testClass", annotationTypeName);
|
||||
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "value");
|
||||
checkSimpleCompileTimeConstant(actualCompileTimeConstant, DEFAULT_PACKAGE + ".MyEnum", "MyEnum.ONE");
|
||||
}
|
||||
|
||||
public void testCustomAnnotation() throws IOException {
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("customAnnotation.java", null);
|
||||
String annotationTypeName = DEFAULT_PACKAGE + ".MyAnnotation";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("MyTest", annotationTypeName);
|
||||
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "value");
|
||||
checkSimpleCompileTimeConstant(actualCompileTimeConstant, DEFAULT_PACKAGE + ".MyEnum", "MyEnum.ONE");
|
||||
}
|
||||
|
||||
public void testCustomAnnotationWithDefaultParameter() throws IOException {
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("customAnnotationWithDefaultParameter.java", null);
|
||||
String annotationTypeName = DEFAULT_PACKAGE + ".MyAnnotation";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("MyTest", annotationTypeName);
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "first");
|
||||
checkSimpleCompileTimeConstant(actualCompileTimeConstant, "jet.String", "\"f\"");
|
||||
|
||||
actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "second");
|
||||
checkSimpleCompileTimeConstant(actualCompileTimeConstant, "jet.String", "\"s\"");
|
||||
}
|
||||
|
||||
public void testAnnotationWithAnnotationInParam() throws IOException {
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("annotationWithAnnotationInParam.java", null);
|
||||
String annotationTypeName = DEFAULT_PACKAGE + ".MyAnnotationWithParam";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("A",
|
||||
annotationTypeName);
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "value");
|
||||
assert actualCompileTimeConstant instanceof AnnotationValue;
|
||||
checkAnnotationCompileTimeConstant((AnnotationValue) actualCompileTimeConstant, "value",
|
||||
DEFAULT_PACKAGE + ".MyAnnotation", "jet.String", "\"test\"");
|
||||
|
||||
String annotationTypeName2 = DEFAULT_PACKAGE + ".MyAnnotationWithParam2";
|
||||
AnnotationDescriptor annotation2 = getAnnotationInClassByType("B", annotationTypeName2);
|
||||
actualCompileTimeConstant = getCompileTimeConstant(annotation2, annotationTypeName2, "value");
|
||||
assert actualCompileTimeConstant instanceof AnnotationValue;
|
||||
checkAnnotationCompileTimeConstant((AnnotationValue) actualCompileTimeConstant, "value",
|
||||
DEFAULT_PACKAGE + ".MyAnnotation2", "jet.Array<jet.String?>?", "[\"test\", \"test2\"]");
|
||||
|
||||
String annotationTypeName3 = DEFAULT_PACKAGE + ".MyAnnotationWithParam3";
|
||||
AnnotationDescriptor annotation3 = getAnnotationInClassByType("C", annotationTypeName3);
|
||||
|
||||
actualCompileTimeConstant = getCompileTimeConstant(annotation3, annotationTypeName3, "value");
|
||||
assert actualCompileTimeConstant instanceof AnnotationValue;
|
||||
checkAnnotationCompileTimeConstant((AnnotationValue) actualCompileTimeConstant, "first",
|
||||
DEFAULT_PACKAGE + ".MyAnnotation3", "jet.String", "\"f\"");
|
||||
checkAnnotationCompileTimeConstant((AnnotationValue) actualCompileTimeConstant, "second",
|
||||
DEFAULT_PACKAGE + ".MyAnnotation3", "jet.String", "\"s\"");
|
||||
}
|
||||
|
||||
public void testRecursiveAnnotation() throws IOException {
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("recursiveAnnotation.java", null);
|
||||
String annotationTypeName = DEFAULT_PACKAGE + ".B";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("A", annotationTypeName);
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "value");
|
||||
assert actualCompileTimeConstant instanceof AnnotationValue;
|
||||
checkAnnotationCompileTimeConstant((AnnotationValue) actualCompileTimeConstant, "value",
|
||||
DEFAULT_PACKAGE + ".A", "jet.String", "\"test\"");
|
||||
|
||||
AnnotationDescriptor annotation2 = getAnnotationInClassByType("B", annotationTypeName);
|
||||
actualCompileTimeConstant = getCompileTimeConstant(annotation2, annotationTypeName, "value");
|
||||
assert actualCompileTimeConstant instanceof AnnotationValue;
|
||||
checkAnnotationCompileTimeConstant((AnnotationValue) actualCompileTimeConstant, "value",
|
||||
DEFAULT_PACKAGE + ".A", "jet.String", "\"test\"");
|
||||
}
|
||||
|
||||
public void testRecursiveAnnotation2() throws IOException {
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("recursiveAnnotation2.java", null);
|
||||
String annotationTypeName = DEFAULT_PACKAGE + ".A";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("B", annotationTypeName);
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "value");
|
||||
assert actualCompileTimeConstant instanceof AnnotationValue;
|
||||
checkAnnotationCompileTimeConstant((AnnotationValue) actualCompileTimeConstant, "value",
|
||||
DEFAULT_PACKAGE + ".B", "jet.String", "\"test\"");
|
||||
}
|
||||
|
||||
public void testAnnotationWithEnumInParam() throws IOException {
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("annotationWithEnumInParam.java", null);
|
||||
String annotationTypeName = "java.lang.annotation.Retention";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("retentionAnnotation", annotationTypeName);
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "value");
|
||||
checkSimpleCompileTimeConstant(actualCompileTimeConstant, "java.lang.annotation.RetentionPolicy", "RetentionPolicy.RUNTIME");
|
||||
}
|
||||
|
||||
public void testAnnotationWithArrayOfEnumInParam() throws IOException {
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("annotationWithArrayOfEnumInParam.java", null);
|
||||
String annotationTypeName = "java.lang.annotation.Target";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("targetAnnotation", annotationTypeName);
|
||||
assertEquals("Number of arguments is incorrect", 1, annotation.getAllValueArguments().size());
|
||||
String[] values = new String[] {"ElementType.FIELD", "ElementType.CONSTRUCTOR"};
|
||||
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "value");
|
||||
assert actualCompileTimeConstant instanceof ArrayValue;
|
||||
checkArrayCompileTimeConstant((ArrayValue) actualCompileTimeConstant, "jet.Array<java.lang.annotation.ElementType?>?",
|
||||
"java.lang.annotation.ElementType", values);
|
||||
}
|
||||
|
||||
public void testAnnotationWithArrayOfStringInParam() throws IOException {
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("annotationWithArrayOfStringInParam.java", null);
|
||||
String annotationTypeName = DEFAULT_PACKAGE + ".MyAnnotation";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("A", annotationTypeName);
|
||||
assertEquals("Number of arguments is incorrect", 1, annotation.getAllValueArguments().size());
|
||||
String[] values = new String[] {"\"a\"", "\"b\"", "\"c\""};
|
||||
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "value");
|
||||
assert actualCompileTimeConstant instanceof ArrayValue;
|
||||
checkArrayCompileTimeConstant((ArrayValue) actualCompileTimeConstant, "jet.Array<jet.String?>?", "jet.String", values);
|
||||
}
|
||||
|
||||
public void testAnnotationWithEmptyArrayInParam() throws IOException {
|
||||
setUpJavaDescriptorResolver();
|
||||
compileJavaFile("annotationWithEmptyArrayInParam.java", null);
|
||||
String annotationTypeName = DEFAULT_PACKAGE + ".MyAnnotation";
|
||||
AnnotationDescriptor annotation = getAnnotationInClassByType("A", annotationTypeName);
|
||||
|
||||
assertEquals("Number of arguments is incorrect", 1, annotation.getAllValueArguments().size());
|
||||
String[] values = new String[] {};
|
||||
|
||||
CompileTimeConstant<?> actualCompileTimeConstant = getCompileTimeConstant(annotation, annotationTypeName, "value");
|
||||
assert actualCompileTimeConstant instanceof ArrayValue;
|
||||
checkArrayCompileTimeConstant((ArrayValue) actualCompileTimeConstant, "jet.Array<jet.String?>?", "jet.String", values);
|
||||
}
|
||||
|
||||
private void compileJavaFile(@NotNull String fileRelativePath, @Nullable String classPath)
|
||||
throws IOException {
|
||||
File javaFile = new File(PATH + fileRelativePath);
|
||||
assertNotNull(javaFile);
|
||||
List<String> options = new ArrayList<String>();
|
||||
options.add("-d");
|
||||
options.add(tmpdir.getPath());
|
||||
if (classPath != null) {
|
||||
options.add("-cp");
|
||||
options.add(classPath);
|
||||
}
|
||||
JetTestUtils.compileJavaFiles(Collections.singleton(javaFile), options);
|
||||
}
|
||||
|
||||
private void setUpJavaDescriptorResolver() {
|
||||
JetCoreEnvironment jetCoreEnvironment =
|
||||
new JetCoreEnvironment(myTestRootDisposable, CompileCompilerDependenciesTest.compilerConfigurationForTests(
|
||||
ConfigurationKind.JDK_ONLY, TestJdkKind.MOCK_JDK, JetTestUtils.getAnnotationsJar(), tmpdir));
|
||||
|
||||
InjectorForJavaSemanticServices injector = new InjectorForJavaSemanticServices(BuiltinsScopeExtensionMode.ALL,
|
||||
jetCoreEnvironment.getProject());
|
||||
javaDescriptorResolver = injector.getJavaDescriptorResolver();
|
||||
}
|
||||
|
||||
private static void compareJetTypeWithClass(@NotNull JetType actualType, @NotNull String expectedType) {
|
||||
assertEquals(expectedType, DescriptorRenderer.TEXT.renderType(actualType));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private CompileTimeConstant<?> getCompileTimeConstant(
|
||||
@NotNull AnnotationDescriptor annotationDescriptor,
|
||||
@NotNull String annotationType,
|
||||
@NotNull String parameterName
|
||||
) {
|
||||
ValueParameterDescriptor valueParameterDescriptor = getValueParameterDescriptor(annotationType, parameterName);
|
||||
CompileTimeConstant<?> actualCompileTimeValue = annotationDescriptor.getValueArgument(valueParameterDescriptor);
|
||||
assertNotNull(actualCompileTimeValue);
|
||||
return actualCompileTimeValue;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ValueParameterDescriptor getValueParameterDescriptor(@NotNull String annotationTypeName, @NotNull String parameterName) {
|
||||
ClassDescriptor clazz = javaDescriptorResolver.resolveClass(new FqName(annotationTypeName));
|
||||
assertNotNull("Cannot resolve class with name " + annotationTypeName, clazz);
|
||||
ValueParameterDescriptor valueParameterDescriptor =
|
||||
getValueParameterDescriptorForAnnotationParameter(Name.identifier(parameterName), clazz);
|
||||
assertNotNull("Cannot resolve value parameter for " + parameterName, valueParameterDescriptor);
|
||||
return valueParameterDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AnnotationDescriptor getAnnotationInClassByType(@NotNull String className, @NotNull String type) throws IOException {
|
||||
ClassDescriptor classDescriptor = javaDescriptorResolver.resolveClass(new FqName(DEFAULT_PACKAGE + "." + className));
|
||||
assertNotNull("Cannot resolve class with name " + className, classDescriptor);
|
||||
List<AnnotationDescriptor> annotations = classDescriptor.getAnnotations();
|
||||
assertEquals(annotations.size(), 1);
|
||||
for (AnnotationDescriptor annotation : annotations) {
|
||||
if (type.endsWith(annotation.getType().toString())) {
|
||||
compareJetTypeWithClass(annotation.getType(), type);
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
fail("Cannot find annotation for class " + className + ", type " + type);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void checkSimpleCompileTimeConstant(@NotNull CompileTimeConstant<?> actual, @NotNull String expectedType, @NotNull String expectedValue) {
|
||||
assertEquals(expectedValue, actual.toString());
|
||||
compareJetTypeWithClass(actual.getType(JetStandardLibrary.getInstance()), expectedType);
|
||||
}
|
||||
|
||||
private void checkAnnotationCompileTimeConstant(
|
||||
@NotNull AnnotationValue actual,
|
||||
@NotNull String parameterName,
|
||||
@NotNull String expectedType,
|
||||
@NotNull String expectedParameterType,
|
||||
@NotNull String expectedParameterValue
|
||||
) {
|
||||
compareJetTypeWithClass(actual.getType(JetStandardLibrary.getInstance()), expectedType);
|
||||
CompileTimeConstant<?> innerAnnotation = getCompileTimeConstant(actual.getValue(), expectedType, parameterName);
|
||||
checkSimpleCompileTimeConstant(innerAnnotation, expectedParameterType, expectedParameterValue);
|
||||
}
|
||||
|
||||
private static void checkArrayCompileTimeConstant(
|
||||
@NotNull ArrayValue actual,
|
||||
@NotNull String expectedType,
|
||||
@NotNull String expectedArgumentType,
|
||||
@NotNull String[] expectedValues
|
||||
) {
|
||||
JetType actualType = actual.getType(JetStandardLibrary.getInstance());
|
||||
compareJetTypeWithClass(actualType, expectedType);
|
||||
|
||||
List<CompileTimeConstant<?>> arrayValuesCompileTimeConst = actual.getValue();
|
||||
|
||||
assertEquals("Number of arguments is incorrect", expectedValues.length, arrayValuesCompileTimeConst.size());
|
||||
int i = 0;
|
||||
for (CompileTimeConstant<?> constant : arrayValuesCompileTimeConst) {
|
||||
checkSimpleCompileTimeConstant(constant, expectedArgumentType, expectedValues[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user