lightAnnotations: KtLightPsiClassObjectAccessExpression added
as implementation of `PsiClassObjectAccessExpression` for class literals in annotations
This commit is contained in:
committed by
xiexed
parent
92727d2945
commit
0fb879dfc2
+36
-18
@@ -9,14 +9,16 @@ import com.intellij.openapi.util.text.StringUtil
|
|||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.LanguageConstantExpressionEvaluator
|
import com.intellij.psi.impl.LanguageConstantExpressionEvaluator
|
||||||
import com.intellij.psi.impl.light.LightIdentifier
|
import com.intellij.psi.impl.light.LightIdentifier
|
||||||
|
import com.intellij.psi.impl.light.LightTypeElement
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
|
||||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class KtLightPsiArrayInitializerMemberValue(
|
class KtLightPsiArrayInitializerMemberValue(
|
||||||
override val kotlinOrigin: KtElement,
|
override val kotlinOrigin: KtElement,
|
||||||
@@ -30,7 +32,7 @@ class KtLightPsiArrayInitializerMemberValue(
|
|||||||
override fun isPhysical(): Boolean = false
|
override fun isPhysical(): Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
class KtLightPsiLiteral(
|
open class KtLightPsiLiteral(
|
||||||
override val kotlinOrigin: KtExpression,
|
override val kotlinOrigin: KtExpression,
|
||||||
val lightParent: PsiElement
|
val lightParent: PsiElement
|
||||||
) : KtLightElementBase(lightParent), PsiLiteralExpression {
|
) : KtLightElementBase(lightParent), PsiLiteralExpression {
|
||||||
@@ -41,19 +43,7 @@ class KtLightPsiLiteral(
|
|||||||
override fun getType(): PsiType? {
|
override fun getType(): PsiType? {
|
||||||
val bindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(kotlinOrigin)
|
val bindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(kotlinOrigin)
|
||||||
val kotlinType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, kotlinOrigin] ?: return null
|
val kotlinType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, kotlinOrigin] ?: return null
|
||||||
val typeFqName = kotlinType.constructor.declarationDescriptor?.fqNameSafe?.asString() ?: return null
|
return psiType(kotlinType, kotlinOrigin)
|
||||||
return when (typeFqName) {
|
|
||||||
"kotlin.Int" -> PsiType.INT
|
|
||||||
"kotlin.Long" -> PsiType.LONG
|
|
||||||
"kotlin.Short" -> PsiType.SHORT
|
|
||||||
"kotlin.Boolean" -> PsiType.BOOLEAN
|
|
||||||
"kotlin.Byte" -> PsiType.BYTE
|
|
||||||
"kotlin.Char" -> PsiType.CHAR
|
|
||||||
"kotlin.Double" -> PsiType.DOUBLE
|
|
||||||
"kotlin.Float" -> PsiType.FLOAT
|
|
||||||
"kotlin.String" -> PsiType.getJavaLangString(kotlinOrigin.manager, GlobalSearchScope.projectScope(kotlinOrigin.project))
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getParent(): PsiElement = lightParent
|
override fun getParent(): PsiElement = lightParent
|
||||||
@@ -70,6 +60,34 @@ class KtLightPsiLiteral(
|
|||||||
override fun getReferences(): Array<out PsiReference> = kotlinOrigin.references
|
override fun getReferences(): Array<out PsiReference> = kotlinOrigin.references
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class KtLightPsiClassObjectAccessExpression(override val kotlinOrigin: KtClassLiteralExpression, lightParent: PsiElement) :
|
||||||
|
KtLightPsiLiteral(kotlinOrigin, lightParent), PsiClassObjectAccessExpression {
|
||||||
|
override fun getType(): PsiType {
|
||||||
|
val bindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(kotlinOrigin)
|
||||||
|
val kotlinType = bindingContext[BindingContext.COMPILE_TIME_VALUE, kotlinOrigin]
|
||||||
|
?.getValue(TypeUtils.NO_EXPECTED_TYPE).safeAs<SimpleType>() ?: return PsiType.VOID
|
||||||
|
return psiType(kotlinType, kotlinOrigin) ?: return PsiType.VOID
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getOperand(): PsiTypeElement = LightTypeElement(kotlinOrigin.manager, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun psiType(kotlinType: KotlinType, context: PsiElement): PsiType? {
|
||||||
|
val typeFqName = kotlinType.constructor.declarationDescriptor?.fqNameSafe?.asString() ?: return null
|
||||||
|
return when (typeFqName) {
|
||||||
|
"kotlin.Int" -> PsiType.INT
|
||||||
|
"kotlin.Long" -> PsiType.LONG
|
||||||
|
"kotlin.Short" -> PsiType.SHORT
|
||||||
|
"kotlin.Boolean" -> PsiType.BOOLEAN
|
||||||
|
"kotlin.Byte" -> PsiType.BYTE
|
||||||
|
"kotlin.Char" -> PsiType.CHAR
|
||||||
|
"kotlin.Double" -> PsiType.DOUBLE
|
||||||
|
"kotlin.Float" -> PsiType.FLOAT
|
||||||
|
"kotlin.String" -> PsiType.getJavaLangString(context.manager, GlobalSearchScope.projectScope(context.project))
|
||||||
|
else -> PsiType.getTypeByName(typeFqName, context.project, context.resolveScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class KtLightPsiNameValuePair private constructor(
|
class KtLightPsiNameValuePair private constructor(
|
||||||
override val kotlinOrigin: KtElement,
|
override val kotlinOrigin: KtElement,
|
||||||
val valueArgument: KtValueArgument,
|
val valueArgument: KtValueArgument,
|
||||||
|
|||||||
+36
-18
@@ -9,14 +9,16 @@ import com.intellij.openapi.util.text.StringUtil
|
|||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.LanguageConstantExpressionEvaluator
|
import com.intellij.psi.impl.LanguageConstantExpressionEvaluator
|
||||||
import com.intellij.psi.impl.light.LightIdentifier
|
import com.intellij.psi.impl.light.LightIdentifier
|
||||||
|
import com.intellij.psi.impl.light.LightTypeElement
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
|
||||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class KtLightPsiArrayInitializerMemberValue(
|
class KtLightPsiArrayInitializerMemberValue(
|
||||||
override val kotlinOrigin: KtElement,
|
override val kotlinOrigin: KtElement,
|
||||||
@@ -30,7 +32,7 @@ class KtLightPsiArrayInitializerMemberValue(
|
|||||||
override fun isPhysical(): Boolean = true
|
override fun isPhysical(): Boolean = true
|
||||||
}
|
}
|
||||||
|
|
||||||
class KtLightPsiLiteral(
|
open class KtLightPsiLiteral(
|
||||||
override val kotlinOrigin: KtExpression,
|
override val kotlinOrigin: KtExpression,
|
||||||
val lightParent: PsiElement
|
val lightParent: PsiElement
|
||||||
) : KtLightElementBase(lightParent), PsiLiteralExpression {
|
) : KtLightElementBase(lightParent), PsiLiteralExpression {
|
||||||
@@ -41,19 +43,7 @@ class KtLightPsiLiteral(
|
|||||||
override fun getType(): PsiType? {
|
override fun getType(): PsiType? {
|
||||||
val bindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(kotlinOrigin)
|
val bindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(kotlinOrigin)
|
||||||
val kotlinType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, kotlinOrigin] ?: return null
|
val kotlinType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, kotlinOrigin] ?: return null
|
||||||
val typeFqName = kotlinType.constructor.declarationDescriptor?.fqNameSafe?.asString() ?: return null
|
return psiType(kotlinType, kotlinOrigin)
|
||||||
return when (typeFqName) {
|
|
||||||
"kotlin.Int" -> PsiType.INT
|
|
||||||
"kotlin.Long" -> PsiType.LONG
|
|
||||||
"kotlin.Short" -> PsiType.SHORT
|
|
||||||
"kotlin.Boolean" -> PsiType.BOOLEAN
|
|
||||||
"kotlin.Byte" -> PsiType.BYTE
|
|
||||||
"kotlin.Char" -> PsiType.CHAR
|
|
||||||
"kotlin.Double" -> PsiType.DOUBLE
|
|
||||||
"kotlin.Float" -> PsiType.FLOAT
|
|
||||||
"kotlin.String" -> PsiType.getJavaLangString(kotlinOrigin.manager, GlobalSearchScope.projectScope(kotlinOrigin.project))
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getParent(): PsiElement = lightParent
|
override fun getParent(): PsiElement = lightParent
|
||||||
@@ -70,6 +60,34 @@ class KtLightPsiLiteral(
|
|||||||
override fun getReferences(): Array<out PsiReference> = kotlinOrigin.references
|
override fun getReferences(): Array<out PsiReference> = kotlinOrigin.references
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class KtLightPsiClassObjectAccessExpression(override val kotlinOrigin: KtClassLiteralExpression, lightParent: PsiElement) :
|
||||||
|
KtLightPsiLiteral(kotlinOrigin, lightParent), PsiClassObjectAccessExpression {
|
||||||
|
override fun getType(): PsiType {
|
||||||
|
val bindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(kotlinOrigin)
|
||||||
|
val kotlinType = bindingContext[BindingContext.COMPILE_TIME_VALUE, kotlinOrigin]
|
||||||
|
?.getValue(TypeUtils.NO_EXPECTED_TYPE).safeAs<SimpleType>() ?: return PsiType.VOID
|
||||||
|
return psiType(kotlinType, kotlinOrigin) ?: return PsiType.VOID
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getOperand(): PsiTypeElement = LightTypeElement(kotlinOrigin.manager, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun psiType(kotlinType: KotlinType, context: PsiElement): PsiType? {
|
||||||
|
val typeFqName = kotlinType.constructor.declarationDescriptor?.fqNameSafe?.asString() ?: return null
|
||||||
|
return when (typeFqName) {
|
||||||
|
"kotlin.Int" -> PsiType.INT
|
||||||
|
"kotlin.Long" -> PsiType.LONG
|
||||||
|
"kotlin.Short" -> PsiType.SHORT
|
||||||
|
"kotlin.Boolean" -> PsiType.BOOLEAN
|
||||||
|
"kotlin.Byte" -> PsiType.BYTE
|
||||||
|
"kotlin.Char" -> PsiType.CHAR
|
||||||
|
"kotlin.Double" -> PsiType.DOUBLE
|
||||||
|
"kotlin.Float" -> PsiType.FLOAT
|
||||||
|
"kotlin.String" -> PsiType.getJavaLangString(context.manager, GlobalSearchScope.projectScope(context.project))
|
||||||
|
else -> PsiType.getTypeByName(typeFqName, context.project, context.resolveScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class KtLightPsiNameValuePair private constructor(
|
class KtLightPsiNameValuePair private constructor(
|
||||||
override val kotlinOrigin: KtElement,
|
override val kotlinOrigin: KtElement,
|
||||||
val valueArgument: KtValueArgument,
|
val valueArgument: KtValueArgument,
|
||||||
|
|||||||
@@ -330,6 +330,9 @@ private fun KtElement.getResolvedCall(): ResolvedCall<out CallableDescriptor>? {
|
|||||||
fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExpression): PsiAnnotationMemberValue {
|
fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExpression): PsiAnnotationMemberValue {
|
||||||
val argument = unwrapCall(argument)
|
val argument = unwrapCall(argument)
|
||||||
when (argument) {
|
when (argument) {
|
||||||
|
is KtClassLiteralExpression -> {
|
||||||
|
return KtLightPsiClassObjectAccessExpression(argument, lightParent)
|
||||||
|
}
|
||||||
is KtStringTemplateExpression, is KtConstantExpression -> {
|
is KtStringTemplateExpression, is KtConstantExpression -> {
|
||||||
return KtLightPsiLiteral(argument, lightParent)
|
return KtLightPsiLiteral(argument, lightParent)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -22,6 +22,7 @@ import com.intellij.psi.*
|
|||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.jetbrains.annotations.NotNull
|
import org.jetbrains.annotations.NotNull
|
||||||
import org.jetbrains.annotations.Nullable
|
import org.jetbrains.annotations.Nullable
|
||||||
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
||||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||||
@@ -331,6 +332,9 @@ private fun KtElement.getResolvedCall(): ResolvedCall<out CallableDescriptor>? {
|
|||||||
fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExpression): PsiAnnotationMemberValue {
|
fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExpression): PsiAnnotationMemberValue {
|
||||||
val argument = unwrapCall(argument)
|
val argument = unwrapCall(argument)
|
||||||
when (argument) {
|
when (argument) {
|
||||||
|
is KtClassLiteralExpression -> {
|
||||||
|
return KtLightPsiClassObjectAccessExpression(argument, lightParent)
|
||||||
|
}
|
||||||
is KtStringTemplateExpression, is KtConstantExpression -> {
|
is KtStringTemplateExpression, is KtConstantExpression -> {
|
||||||
return KtLightPsiLiteral(argument, lightParent)
|
return KtLightPsiLiteral(argument, lightParent)
|
||||||
}
|
}
|
||||||
@@ -393,8 +397,10 @@ private fun getAnnotationName(callee: KtExpression): String? {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestOnly
|
||||||
var accessAnnotationsClsDelegateIsAllowed = false
|
var accessAnnotationsClsDelegateIsAllowed = false
|
||||||
|
|
||||||
|
@TestOnly
|
||||||
fun <T> withAllowedAnnotationsClsDelegate(body: () -> T): T {
|
fun <T> withAllowedAnnotationsClsDelegate(body: () -> T): T {
|
||||||
val prev = accessAnnotationsClsDelegateIsAllowed
|
val prev = accessAnnotationsClsDelegateIsAllowed
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
|||||||
import org.jetbrains.kotlin.idea.completion.test.assertInstanceOf
|
import org.jetbrains.kotlin.idea.completion.test.assertInstanceOf
|
||||||
import org.jetbrains.kotlin.idea.facet.configureFacet
|
import org.jetbrains.kotlin.idea.facet.configureFacet
|
||||||
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
|
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
|
||||||
|
import org.jetbrains.kotlin.idea.search.projectScope
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
|
|
||||||
@@ -208,6 +209,32 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testClassLiteral() {
|
||||||
|
myFixture.addClass(
|
||||||
|
"""
|
||||||
|
public @interface ClazzAnnotation {
|
||||||
|
Class<?> cls();
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.configureByText(
|
||||||
|
"AnnotatedClass.kt", """
|
||||||
|
@ClazzAnnotation(cls = String::class)
|
||||||
|
class AnnotatedClass
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
myFixture.testHighlighting("AnnotatedClass.kt")
|
||||||
|
|
||||||
|
val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1)
|
||||||
|
val annotationAttributeVal = annotations.first().findAttributeValue("cls") as PsiClassObjectAccessExpression
|
||||||
|
assertTextAndRange("String::class", annotationAttributeVal)
|
||||||
|
TestCase.assertEquals(
|
||||||
|
PsiType.getJavaLangString(myFixture.psiManager, myFixture.project.projectScope()),
|
||||||
|
annotationAttributeVal.operand.type
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun testAnnotationsInAnnotationsArrayDeclarations() {
|
fun testAnnotationsInAnnotationsArrayDeclarations() {
|
||||||
myFixture.addClass("""
|
myFixture.addClass("""
|
||||||
public @interface OuterAnnotation {
|
public @interface OuterAnnotation {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
|||||||
import org.jetbrains.kotlin.idea.completion.test.assertInstanceOf
|
import org.jetbrains.kotlin.idea.completion.test.assertInstanceOf
|
||||||
import org.jetbrains.kotlin.idea.facet.configureFacet
|
import org.jetbrains.kotlin.idea.facet.configureFacet
|
||||||
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
|
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
|
||||||
|
import org.jetbrains.kotlin.idea.search.projectScope
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
|
|
||||||
@@ -209,6 +210,32 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testClassLiteral() {
|
||||||
|
myFixture.addClass(
|
||||||
|
"""
|
||||||
|
public @interface ClazzAnnotation {
|
||||||
|
Class<?> cls();
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.configureByText(
|
||||||
|
"AnnotatedClass.kt", """
|
||||||
|
@ClazzAnnotation(cls = String::class)
|
||||||
|
class AnnotatedClass
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
myFixture.testHighlighting("AnnotatedClass.kt")
|
||||||
|
|
||||||
|
val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1)
|
||||||
|
val annotationAttributeVal = annotations.first().findAttributeValue("cls") as PsiClassObjectAccessExpression
|
||||||
|
assertTextAndRange("String::class", annotationAttributeVal)
|
||||||
|
TestCase.assertEquals(
|
||||||
|
PsiType.getJavaLangString(myFixture.psiManager, myFixture.project.projectScope()),
|
||||||
|
annotationAttributeVal.operand.type
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun testAnnotationsInAnnotationsArrayDeclarations() {
|
fun testAnnotationsInAnnotationsArrayDeclarations() {
|
||||||
myFixture.addClass("""
|
myFixture.addClass("""
|
||||||
public @interface OuterAnnotation {
|
public @interface OuterAnnotation {
|
||||||
|
|||||||
Reference in New Issue
Block a user