Render '@' before each annotation

This commit is contained in:
Denis Zharkov
2015-09-15 19:40:26 +03:00
parent f518348565
commit 7ea7e3cc7c
11 changed files with 60 additions and 82 deletions
@@ -139,7 +139,7 @@ public abstract class AbstractAnnotationDescriptorResolveTest extends JetLiteFix
} }
}, " "); }, " ");
String expectedAnnotationWithTarget = "@" + AnnotationUseSiteTarget.FILE.getRenderName() + ":" + expectedAnnotation; String expectedAnnotationWithTarget = "@" + AnnotationUseSiteTarget.FILE.getRenderName() + ":" + expectedAnnotation.substring(1);
assertEquals(expectedAnnotationWithTarget, actualAnnotation); assertEquals(expectedAnnotationWithTarget, actualAnnotation);
} }
@@ -21,73 +21,73 @@ import java.io.IOException;
public class AnnotationDescriptorResolveTest extends AbstractAnnotationDescriptorResolveTest { public class AnnotationDescriptorResolveTest extends AbstractAnnotationDescriptorResolveTest {
public void testIntAnnotation() throws IOException { public void testIntAnnotation() throws IOException {
String content = getContent("AnnInt(1)"); String content = getContent("AnnInt(1)");
String expectedAnnotation = "AnnInt(a = 1)"; String expectedAnnotation = "@AnnInt(a = 1)";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testStringAnnotation() throws IOException { public void testStringAnnotation() throws IOException {
String content = getContent("AnnString(\"test\")"); String content = getContent("AnnString(\"test\")");
String expectedAnnotation = "AnnString(a = \"test\")"; String expectedAnnotation = "@AnnString(a = \"test\")";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testEnumAnnotation() throws IOException { public void testEnumAnnotation() throws IOException {
String content = getContent("AnnEnum(MyEnum.A)"); String content = getContent("AnnEnum(MyEnum.A)");
String expectedAnnotation = "AnnEnum(a = MyEnum.A)"; String expectedAnnotation = "@AnnEnum(a = MyEnum.A)";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testQualifiedEnumAnnotation() throws IOException { public void testQualifiedEnumAnnotation() throws IOException {
String content = getContent("AnnEnum(MyEnum.A)"); String content = getContent("AnnEnum(MyEnum.A)");
String expectedAnnotation = "AnnEnum(a = MyEnum.A)"; String expectedAnnotation = "@AnnEnum(a = MyEnum.A)";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testUnqualifiedEnumAnnotation() throws IOException { public void testUnqualifiedEnumAnnotation() throws IOException {
String content = getContent("AnnEnum(A)"); String content = getContent("AnnEnum(A)");
String expectedAnnotation = "AnnEnum(a = MyEnum.A)"; String expectedAnnotation = "@AnnEnum(a = MyEnum.A)";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testIntArrayAnnotation() throws IOException { public void testIntArrayAnnotation() throws IOException {
String content = getContent("AnnIntArray(intArray(1, 2))"); String content = getContent("AnnIntArray(intArray(1, 2))");
String expectedAnnotation = "AnnIntArray(a = {1, 2})"; String expectedAnnotation = "@AnnIntArray(a = {1, 2})";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testIntArrayVarargAnnotation() throws IOException { public void testIntArrayVarargAnnotation() throws IOException {
String content = getContent("AnnIntVararg(1, 2)"); String content = getContent("AnnIntVararg(1, 2)");
String expectedAnnotation = "AnnIntVararg(a = {1, 2})"; String expectedAnnotation = "@AnnIntVararg(a = {1, 2})";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testStringArrayVarargAnnotation() throws IOException { public void testStringArrayVarargAnnotation() throws IOException {
String content = getContent("AnnStringVararg(\"a\", \"b\")"); String content = getContent("AnnStringVararg(\"a\", \"b\")");
String expectedAnnotation = "AnnStringVararg(a = {\"a\", \"b\"})"; String expectedAnnotation = "@AnnStringVararg(a = {\"a\", \"b\"})";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testStringArrayAnnotation() throws IOException { public void testStringArrayAnnotation() throws IOException {
String content = getContent("AnnStringArray(array(\"a\"))"); String content = getContent("AnnStringArray(array(\"a\"))");
String expectedAnnotation = "AnnStringArray(a = {\"a\"})"; String expectedAnnotation = "@AnnStringArray(a = {\"a\"})";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testEnumArrayAnnotation() throws IOException { public void testEnumArrayAnnotation() throws IOException {
String content = getContent("AnnArrayOfEnum(array(MyEnum.A))"); String content = getContent("AnnArrayOfEnum(array(MyEnum.A))");
String expectedAnnotation = "AnnArrayOfEnum(a = {MyEnum.A})"; String expectedAnnotation = "@AnnArrayOfEnum(a = {MyEnum.A})";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testAnnotationAnnotation() throws Exception { public void testAnnotationAnnotation() throws Exception {
String content = getContent("AnnAnn(AnnInt(1))"); String content = getContent("AnnAnn(AnnInt(1))");
String expectedAnnotation = "AnnAnn(a = AnnInt(a = 1))"; String expectedAnnotation = "@AnnAnn(a = AnnInt(a = 1))";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
public void testJavaClassAnnotation() throws Exception { public void testJavaClassAnnotation() throws Exception {
String content = getContent("AnnClass(MyClass::class)"); String content = getContent("AnnClass(MyClass::class)");
String expectedAnnotation = "AnnClass(a = MyClass::class)"; String expectedAnnotation = "@AnnClass(a = MyClass::class)";
doTest(content, expectedAnnotation); doTest(content, expectedAnnotation);
} }
} }
@@ -341,7 +341,6 @@ internal class DescriptorRendererImpl(
if (DescriptorRendererModifier.ANNOTATIONS !in modifiers) return if (DescriptorRendererModifier.ANNOTATIONS !in modifiers) return
val excluded = if (annotated is JetType) excludedTypeAnnotationClasses else excludedAnnotationClasses val excluded = if (annotated is JetType) excludedTypeAnnotationClasses else excludedAnnotationClasses
var hasTargetedAnnotations = false
val annotationsBuilder = StringBuilder { val annotationsBuilder = StringBuilder {
// Sort is needed just to fix some order when annotations resolved from modifiers // Sort is needed just to fix some order when annotations resolved from modifiers
@@ -353,25 +352,12 @@ internal class DescriptorRendererImpl(
val annotationClass = annotation.getType().getConstructor().getDeclarationDescriptor() as ClassDescriptor val annotationClass = annotation.getType().getConstructor().getDeclarationDescriptor() as ClassDescriptor
if (!excluded.contains(DescriptorUtils.getFqNameSafe(annotationClass))) { if (!excluded.contains(DescriptorUtils.getFqNameSafe(annotationClass))) {
if (target != null && !hasTargetedAnnotations) {
hasTargetedAnnotations = true
}
append(renderAnnotation(annotation, target)).append(" ") append(renderAnnotation(annotation, target)).append(" ")
} }
} }
} }
if (!needBrackets || hasTargetedAnnotations) { builder.append(annotationsBuilder)
builder.append(annotationsBuilder)
}
else if (annotationsBuilder.length() > 0) {
// remove last whitespace
annotationsBuilder.setLength(annotationsBuilder.length() - 1)
builder.append("@[")
builder.append(annotationsBuilder)
builder.append("] ")
}
} }
private fun AnnotationDescriptor.isBuiltinModifier() private fun AnnotationDescriptor.isBuiltinModifier()
@@ -379,8 +365,9 @@ internal class DescriptorRendererImpl(
override fun renderAnnotation(annotation: AnnotationDescriptor, target: AnnotationUseSiteTarget?): String { override fun renderAnnotation(annotation: AnnotationDescriptor, target: AnnotationUseSiteTarget?): String {
return StringBuilder { return StringBuilder {
append('@')
if (target != null) { if (target != null) {
append("@" + target.renderName + ":") append(target.renderName + ":")
} }
append(renderType(annotation.getType())) append(renderType(annotation.getType()))
if (verbose) { if (verbose) {
@@ -411,7 +398,7 @@ internal class DescriptorRendererImpl(
private fun renderConstant(value: ConstantValue<*>): String { private fun renderConstant(value: ConstantValue<*>): String {
return when (value) { return when (value) {
is ArrayValue -> value.value.map { renderConstant(it) }.joinToString(", ", "{", "}") is ArrayValue -> value.value.map { renderConstant(it) }.joinToString(", ", "{", "}")
is AnnotationValue -> renderAnnotation(value.value) is AnnotationValue -> renderAnnotation(value.value).removePrefix("@")
is KClassValue -> renderType(value.value) + "::class" is KClassValue -> renderType(value.value) + "::class"
else -> value.toString() else -> value.toString()
} }
@@ -104,7 +104,7 @@ private class CallableClsStubBuilder(
val kind = callableProto.annotatedCallableKind val kind = callableProto.annotatedCallableKind
val annotationIds = c.components.annotationLoader.loadCallableAnnotations(protoContainer, callableProto, c.nameResolver, kind) val annotationIds = c.components.annotationLoader.loadCallableAnnotations(protoContainer, callableProto, c.nameResolver, kind)
createTargetedAnnotationStubs(annotationIds, modifierListStubImpl, needWrappingAnnotationEntries = isPrimaryConstructor) createTargetedAnnotationStubs(annotationIds, modifierListStubImpl)
} }
private fun doCreateCallableStub(): StubElement<out PsiElement> { private fun doCreateCallableStub(): StubElement<out PsiElement> {
@@ -94,7 +94,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
} }
private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, annotations: List<ClassId>) { private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, annotations: List<ClassId>) {
createAnnotationStubs(annotations, parent, needWrappingAnnotationEntries = true) createAnnotationStubs(annotations, parent)
} }
private fun createTypeArgumentListStub(typeStub: KotlinUserTypeStub, typeArgumentProtoList: List<Type.Argument>) { private fun createTypeArgumentListStub(typeStub: KotlinUserTypeStub, typeArgumentProtoList: List<Type.Argument>) {
@@ -216,25 +216,20 @@ fun createModifierListStub(
) )
} }
fun createAnnotationStubs(annotationIds: List<ClassId>, parent: KotlinStubBaseImpl<*>, needWrappingAnnotationEntries: Boolean = false) { fun createAnnotationStubs(annotationIds: List<ClassId>, parent: KotlinStubBaseImpl<*>) {
return createTargetedAnnotationStubs(annotationIds.map { ClassIdWithTarget(it, null) }, parent, needWrappingAnnotationEntries) return createTargetedAnnotationStubs(annotationIds.map { ClassIdWithTarget(it, null) }, parent)
} }
fun createTargetedAnnotationStubs( fun createTargetedAnnotationStubs(
annotationIds: List<ClassIdWithTarget>, annotationIds: List<ClassIdWithTarget>,
parent: KotlinStubBaseImpl<*>, parent: KotlinStubBaseImpl<*>
needWrappingAnnotationEntries: Boolean = false
) { ) {
if (annotationIds.isEmpty()) return if (annotationIds.isEmpty()) return
val entriesParent =
if (needWrappingAnnotationEntries) KotlinPlaceHolderStubImpl<JetAnnotation>(parent, JetStubElementTypes.ANNOTATION)
else parent
annotationIds.forEach { annotation -> annotationIds.forEach { annotation ->
val (annotationClassId, target) = annotation val (annotationClassId, target) = annotation
val annotationEntryStubImpl = KotlinAnnotationEntryStubImpl( val annotationEntryStubImpl = KotlinAnnotationEntryStubImpl(
entriesParent, parent,
shortName = annotationClassId.getShortClassName().ref(), shortName = annotationClassId.getShortClassName().ref(),
hasValueArguments = false hasValueArguments = false
) )
@@ -3,8 +3,8 @@
package test package test
dependency.A dependency.B dependency.C kotlin.data public final class Annotations public constructor() { @dependency.A @dependency.B @dependency.C @kotlin.data public final class Annotations public constructor() {
dependency.A dependency.B dependency.C kotlin.inline public final val p: @[dependency.B] kotlin.Int /* compiled code */ @dependency.A @dependency.B @dependency.C @kotlin.inline public final val p: @dependency.B kotlin.Int /* compiled code */
dependency.A dependency.B dependency.C kotlin.inline public final fun f(dependency.A dependency.B dependency.C kotlin.Deprecated i: @[dependency.A] kotlin.Int): kotlin.Unit { /* compiled code */ } @dependency.A @dependency.B @dependency.C @kotlin.inline public final fun f(@dependency.A @dependency.B @dependency.C @kotlin.Deprecated i: @dependency.A kotlin.Int): kotlin.Unit { /* compiled code */ }
} }
@@ -3,5 +3,5 @@
package test package test
public final class AnnotationsOnPrimaryCtr @[dependency.A dependency.B dependency.C] private constructor() { public final class AnnotationsOnPrimaryCtr @dependency.A @dependency.B @dependency.C private constructor() {
} }
@@ -4,7 +4,7 @@
package test package test
public final class SecondaryConstructors public constructor(x: kotlin.Boolean) { public final class SecondaryConstructors public constructor(x: kotlin.Boolean) {
test.anno public constructor(x: kotlin.String) { /* compiled code */ } @test.anno public constructor(x: kotlin.String) { /* compiled code */ }
private constructor(x: kotlin.Int) { /* compiled code */ } private constructor(x: kotlin.Int) { /* compiled code */ }
@@ -13,7 +13,7 @@ public final class SecondaryConstructors public constructor(x: kotlin.Boolean) {
} }
public final class Nested { public final class Nested {
test.anno public constructor(z: kotlin.Int) { /* compiled code */ } @test.anno public constructor(z: kotlin.Int) { /* compiled code */ }
internal constructor() { /* compiled code */ } internal constructor() { /* compiled code */ }
} }
@@ -10,12 +10,11 @@ PsiJetFileStubImpl[package=]
REFERENCE_EXPRESSION:[referencedName=a] REFERENCE_EXPRESSION:[referencedName=a]
PRIMARY_CONSTRUCTOR: PRIMARY_CONSTRUCTOR:
MODIFIER_LIST:[private] MODIFIER_LIST:[private]
ANNOTATION: ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a] CONSTRUCTOR_CALLEE:
CONSTRUCTOR_CALLEE: TYPE_REFERENCE:
TYPE_REFERENCE: USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false] REFERENCE_EXPRESSION:[referencedName=a]
REFERENCE_EXPRESSION:[referencedName=a]
VALUE_PARAMETER_LIST: VALUE_PARAMETER_LIST:
VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=c1] VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=c1]
MODIFIER_LIST:[] MODIFIER_LIST:[]
@@ -144,33 +143,31 @@ PsiJetFileStubImpl[package=]
VALUE_PARAMETER_LIST: VALUE_PARAMETER_LIST:
VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=param] VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=param]
TYPE_REFERENCE: TYPE_REFERENCE:
ANNOTATION: ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a] CONSTRUCTOR_CALLEE:
CONSTRUCTOR_CALLEE: TYPE_REFERENCE:
TYPE_REFERENCE: USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false] REFERENCE_EXPRESSION:[referencedName=a]
REFERENCE_EXPRESSION:[referencedName=a] ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b] CONSTRUCTOR_CALLEE:
CONSTRUCTOR_CALLEE: TYPE_REFERENCE:
TYPE_REFERENCE: USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false] REFERENCE_EXPRESSION:[referencedName=b]
REFERENCE_EXPRESSION:[referencedName=b]
USER_TYPE:[isAbsoluteInRootPackage=false] USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false] USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin] REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=DoubleRange] REFERENCE_EXPRESSION:[referencedName=DoubleRange]
TYPE_REFERENCE: TYPE_REFERENCE:
ANNOTATION: ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a] CONSTRUCTOR_CALLEE:
CONSTRUCTOR_CALLEE: TYPE_REFERENCE:
TYPE_REFERENCE: USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false] REFERENCE_EXPRESSION:[referencedName=a]
REFERENCE_EXPRESSION:[referencedName=a] ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b] CONSTRUCTOR_CALLEE:
CONSTRUCTOR_CALLEE: TYPE_REFERENCE:
TYPE_REFERENCE: USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false] REFERENCE_EXPRESSION:[referencedName=b]
REFERENCE_EXPRESSION:[referencedName=b]
USER_TYPE:[isAbsoluteInRootPackage=false] USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false] USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin] REFERENCE_EXPRESSION:[referencedName=kotlin]
@@ -179,11 +176,10 @@ PsiJetFileStubImpl[package=]
MODIFIER_LIST:[public final] MODIFIER_LIST:[public final]
PRIMARY_CONSTRUCTOR: PRIMARY_CONSTRUCTOR:
MODIFIER_LIST:[private] MODIFIER_LIST:[private]
ANNOTATION: ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a]
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a] CONSTRUCTOR_CALLEE:
CONSTRUCTOR_CALLEE: TYPE_REFERENCE:
TYPE_REFERENCE: USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false] REFERENCE_EXPRESSION:[referencedName=a]
REFERENCE_EXPRESSION:[referencedName=a]
VALUE_PARAMETER_LIST: VALUE_PARAMETER_LIST:
CLASS_BODY: CLASS_BODY:
+1 -1
View File
@@ -2,4 +2,4 @@ fun test() {
listOf(1, 2, 4).<caret>filter { it > 0 } listOf(1, 2, 4).<caret>filter { it > 0 }
} }
//INFO: inline <b>public</b> <b>fun</b> &lt;T&gt; Iterable&lt;T&gt;.filter(predicate: (T) &rarr; Boolean): List&lt;T&gt; <i>defined in</i> kotlin<p>Returns a list containing all elements matching the given <a href="psi_element://predicate">predicate</a>.</p> //INFO: @inline <b>public</b> <b>fun</b> &lt;T&gt; Iterable&lt;T&gt;.filter(predicate: (T) &rarr; Boolean): List&lt;T&gt; <i>defined in</i> kotlin<p>Returns a list containing all elements matching the given <a href="psi_element://predicate">predicate</a>.</p>