From 5fdb9e6218cb85dadb5566732dd0d6b45f2e1ef0 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 14 May 2014 22:24:28 +0400 Subject: [PATCH] Change logic of loading "suppress" annotation class descriptor Instead of loading the descriptor and checking equals(), we now check if the annotation is in fact "suppress" by simply comparing its FQ name. This allows us to suppress warnings while compiling built-ins: the problem is that built-ins have its own "suppress" annotation class (defined in the sources) which differs from the one loaded by the compiler (from kotlin-compiler.jar) --- .../resolve/DiagnosticsWithSuppression.java | 53 ++++++------------- .../jet/lang/types/lang/KotlinBuiltIns.java | 22 ++++++-- .../quickfix/KotlinSuppressIntentionAction.kt | 3 +- 3 files changed, 35 insertions(+), 43 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DiagnosticsWithSuppression.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DiagnosticsWithSuppression.java index 1bea07ce0bf..1ea64c07395 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DiagnosticsWithSuppression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DiagnosticsWithSuppression.java @@ -25,9 +25,6 @@ import com.intellij.util.containers.ConcurrentWeakValueHashMap; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FilteringIterator; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Severity; @@ -38,7 +35,10 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.StringValue; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; -import java.util.*; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; public class DiagnosticsWithSuppression implements Diagnostics { @@ -50,9 +50,6 @@ public class DiagnosticsWithSuppression implements Diagnostics { // The cache is weak: we're OK with losing it private final Map suppressors = new ConcurrentWeakValueHashMap(); - // Caching frequently used values: - private final ClassDescriptor suppressClass; - private final ValueParameterDescriptor suppressParameter; private final Condition filter = new Condition() { @Override public boolean value(Diagnostic diagnostic) { @@ -64,11 +61,6 @@ public class DiagnosticsWithSuppression implements Diagnostics { public DiagnosticsWithSuppression(@NotNull BindingContext context, @NotNull Collection diagnostics) { this.context = context; this.diagnostics = diagnostics; - - this.suppressClass = KotlinBuiltIns.getInstance().getSuppressAnnotationClass(); - ConstructorDescriptor primaryConstructor = suppressClass.getUnsubstitutedPrimaryConstructor(); - assert primaryConstructor != null : "No primary constructor in " + suppressClass; - this.suppressParameter = primaryConstructor.getValueParameters().get(0); } @NotNull @@ -183,21 +175,20 @@ public class DiagnosticsWithSuppression implements Diagnostics { ImmutableSet.Builder builder = ImmutableSet.builder(); for (JetAnnotationEntry annotationEntry : annotated.getAnnotationEntries()) { AnnotationDescriptor annotationDescriptor = context.get(BindingContext.ANNOTATION, annotationEntry); - if (annotationDescriptor == null) { - continue; + if (annotationDescriptor == null) continue; + + if (!KotlinBuiltIns.getInstance().isSuppressAnnotation(annotationDescriptor)) continue; + + // We only add strings and skip other values to facilitate recovery in presence of erroneous code + for (CompileTimeConstant arrayValue : annotationDescriptor.getAllValueArguments().values()) { + if ((arrayValue instanceof ArrayValue)) { + for (CompileTimeConstant value : ((ArrayValue) arrayValue).getValue()) { + if (value instanceof StringValue) { + builder.add(String.valueOf(((StringValue) value).getValue()).toLowerCase()); + } + } + } } - - if (!suppressClass.equals(annotationDescriptor.getType().getConstructor().getDeclarationDescriptor())) continue; - - Map> arguments = annotationDescriptor.getAllValueArguments(); - CompileTimeConstant value = arguments.get(suppressParameter); - if (value instanceof ArrayValue) { - ArrayValue arrayValue = (ArrayValue) value; - List> values = arrayValue.getValue(); - - addStrings(builder, values); - } - } return builder.build(); } @@ -208,16 +199,6 @@ public class DiagnosticsWithSuppression implements Diagnostics { return strings.contains(diagnostic.getFactory().getName().toLowerCase()); } - // We only add strings and skip other values to facilitate recovery in presence of erroneous code - private static void addStrings(ImmutableSet.Builder builder, List> values) { - for (CompileTimeConstant value : values) { - if (value instanceof StringValue) { - StringValue stringValue = (StringValue) value; - builder.add(stringValue.getValue().toLowerCase()); - } - } - } - private static abstract class Suppressor { private final JetAnnotated annotated; diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java index 71b3f6b36c9..844ce2f394a 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java @@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.PlatformToKotlinClassMap; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl; import org.jetbrains.jet.lang.resolve.DescriptorUtils; @@ -103,6 +104,8 @@ public class KotlinBuiltIns { private final Map primitiveJetTypeToJetArrayType; private final Map jetArrayTypeToPrimitiveJetType; + private final FqNames fqNames = new FqNames(); + private KotlinBuiltIns() { builtInsModule = new ModuleDescriptorImpl(Name.special(""), Collections.emptyList(), @@ -139,6 +142,15 @@ public class KotlinBuiltIns { jetArrayTypeToPrimitiveJetType.put(arrayType, type); } + private static class FqNames { + public final FqNameUnsafe suppress = fqName("suppress"); + + @NotNull + private static FqNameUnsafe fqName(@NotNull String simpleName) { + return BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName)).toUnsafe(); + } + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @NotNull @@ -295,11 +307,6 @@ public class KotlinBuiltIns { return getBuiltInClassByName("inline"); } - @NotNull - public ClassDescriptor getSuppressAnnotationClass() { - return getBuiltInClassByName("suppress"); - } - @NotNull public ClassDescriptor getTailRecursiveAnnotationClass() { return getBuiltInClassByName("tailRecursive"); @@ -831,6 +838,11 @@ public class KotlinBuiltIns { return containsAnnotation(declarationDescriptor, getTailRecursiveAnnotationClass()); } + public boolean isSuppressAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) { + ClassifierDescriptor classifier = annotationDescriptor.getType().getConstructor().getDeclarationDescriptor(); + return classifier != null && fqNames.suppress.equals(DescriptorUtils.getFqName(classifier)); + } + static boolean containsAnnotation(DeclarationDescriptor descriptor, ClassDescriptor annotationClass) { FqName fqName = DescriptorUtils.getFqName(annotationClass).toSafe(); return descriptor.getOriginal().getAnnotations().findAnnotation(fqName) != null; diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/KotlinSuppressIntentionAction.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/KotlinSuppressIntentionAction.kt index 4c5ebf3c935..97ee7cf9dc0 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/KotlinSuppressIntentionAction.kt +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/KotlinSuppressIntentionAction.kt @@ -135,11 +135,10 @@ public class KotlinSuppressIntentionAction( private fun suppressAnnotationText(id: String) = "[suppress($id)]" private fun findSuppressAnnotation(annotated: JetAnnotated): JetAnnotationEntry? { - val suppressAnnotationClass = KotlinBuiltIns.getInstance().getSuppressAnnotationClass() val context = AnalyzerFacadeWithCache.getContextForElement(annotated) for (entry in annotated.getAnnotationEntries()) { val annotationDescriptor = context.get(BindingContext.ANNOTATION, entry) - if (annotationDescriptor != null && suppressAnnotationClass.getTypeConstructor() == annotationDescriptor.getType().getConstructor()) { + if (annotationDescriptor != null && KotlinBuiltIns.getInstance().isSuppressAnnotation(annotationDescriptor)) { return entry } }