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)
This commit is contained in:
+17
-36
@@ -25,9 +25,6 @@ import com.intellij.util.containers.ConcurrentWeakValueHashMap;
|
|||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import com.intellij.util.containers.FilteringIterator;
|
import com.intellij.util.containers.FilteringIterator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Severity;
|
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.resolve.constants.StringValue;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
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 {
|
public class DiagnosticsWithSuppression implements Diagnostics {
|
||||||
|
|
||||||
@@ -50,9 +50,6 @@ public class DiagnosticsWithSuppression implements Diagnostics {
|
|||||||
// The cache is weak: we're OK with losing it
|
// The cache is weak: we're OK with losing it
|
||||||
private final Map<JetAnnotated, Suppressor> suppressors = new ConcurrentWeakValueHashMap<JetAnnotated, Suppressor>();
|
private final Map<JetAnnotated, Suppressor> suppressors = new ConcurrentWeakValueHashMap<JetAnnotated, Suppressor>();
|
||||||
|
|
||||||
// Caching frequently used values:
|
|
||||||
private final ClassDescriptor suppressClass;
|
|
||||||
private final ValueParameterDescriptor suppressParameter;
|
|
||||||
private final Condition<Diagnostic> filter = new Condition<Diagnostic>() {
|
private final Condition<Diagnostic> filter = new Condition<Diagnostic>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean value(Diagnostic diagnostic) {
|
public boolean value(Diagnostic diagnostic) {
|
||||||
@@ -64,11 +61,6 @@ public class DiagnosticsWithSuppression implements Diagnostics {
|
|||||||
public DiagnosticsWithSuppression(@NotNull BindingContext context, @NotNull Collection<Diagnostic> diagnostics) {
|
public DiagnosticsWithSuppression(@NotNull BindingContext context, @NotNull Collection<Diagnostic> diagnostics) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.diagnostics = diagnostics;
|
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
|
@NotNull
|
||||||
@@ -183,21 +175,20 @@ public class DiagnosticsWithSuppression implements Diagnostics {
|
|||||||
ImmutableSet.Builder<String> builder = ImmutableSet.builder();
|
ImmutableSet.Builder<String> builder = ImmutableSet.builder();
|
||||||
for (JetAnnotationEntry annotationEntry : annotated.getAnnotationEntries()) {
|
for (JetAnnotationEntry annotationEntry : annotated.getAnnotationEntries()) {
|
||||||
AnnotationDescriptor annotationDescriptor = context.get(BindingContext.ANNOTATION, annotationEntry);
|
AnnotationDescriptor annotationDescriptor = context.get(BindingContext.ANNOTATION, annotationEntry);
|
||||||
if (annotationDescriptor == null) {
|
if (annotationDescriptor == null) continue;
|
||||||
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<ValueParameterDescriptor, CompileTimeConstant<?>> arguments = annotationDescriptor.getAllValueArguments();
|
|
||||||
CompileTimeConstant<?> value = arguments.get(suppressParameter);
|
|
||||||
if (value instanceof ArrayValue) {
|
|
||||||
ArrayValue arrayValue = (ArrayValue) value;
|
|
||||||
List<CompileTimeConstant<?>> values = arrayValue.getValue();
|
|
||||||
|
|
||||||
addStrings(builder, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
@@ -208,16 +199,6 @@ public class DiagnosticsWithSuppression implements Diagnostics {
|
|||||||
return strings.contains(diagnostic.getFactory().getName().toLowerCase());
|
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<String> builder, List<CompileTimeConstant<?>> values) {
|
|
||||||
for (CompileTimeConstant<?> value : values) {
|
|
||||||
if (value instanceof StringValue) {
|
|
||||||
StringValue stringValue = (StringValue) value;
|
|
||||||
builder.add(stringValue.getValue().toLowerCase());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static abstract class Suppressor {
|
private static abstract class Suppressor {
|
||||||
private final JetAnnotated annotated;
|
private final JetAnnotated annotated;
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
|
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
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.annotations.Annotations;
|
||||||
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
|
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
@@ -103,6 +104,8 @@ public class KotlinBuiltIns {
|
|||||||
private final Map<JetType, JetType> primitiveJetTypeToJetArrayType;
|
private final Map<JetType, JetType> primitiveJetTypeToJetArrayType;
|
||||||
private final Map<JetType, JetType> jetArrayTypeToPrimitiveJetType;
|
private final Map<JetType, JetType> jetArrayTypeToPrimitiveJetType;
|
||||||
|
|
||||||
|
private final FqNames fqNames = new FqNames();
|
||||||
|
|
||||||
private KotlinBuiltIns() {
|
private KotlinBuiltIns() {
|
||||||
builtInsModule = new ModuleDescriptorImpl(Name.special("<built-ins lazy module>"),
|
builtInsModule = new ModuleDescriptorImpl(Name.special("<built-ins lazy module>"),
|
||||||
Collections.<ImportPath>emptyList(),
|
Collections.<ImportPath>emptyList(),
|
||||||
@@ -139,6 +142,15 @@ public class KotlinBuiltIns {
|
|||||||
jetArrayTypeToPrimitiveJetType.put(arrayType, type);
|
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
|
@NotNull
|
||||||
@@ -295,11 +307,6 @@ public class KotlinBuiltIns {
|
|||||||
return getBuiltInClassByName("inline");
|
return getBuiltInClassByName("inline");
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public ClassDescriptor getSuppressAnnotationClass() {
|
|
||||||
return getBuiltInClassByName("suppress");
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public ClassDescriptor getTailRecursiveAnnotationClass() {
|
public ClassDescriptor getTailRecursiveAnnotationClass() {
|
||||||
return getBuiltInClassByName("tailRecursive");
|
return getBuiltInClassByName("tailRecursive");
|
||||||
@@ -831,6 +838,11 @@ public class KotlinBuiltIns {
|
|||||||
return containsAnnotation(declarationDescriptor, getTailRecursiveAnnotationClass());
|
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) {
|
static boolean containsAnnotation(DeclarationDescriptor descriptor, ClassDescriptor annotationClass) {
|
||||||
FqName fqName = DescriptorUtils.getFqName(annotationClass).toSafe();
|
FqName fqName = DescriptorUtils.getFqName(annotationClass).toSafe();
|
||||||
return descriptor.getOriginal().getAnnotations().findAnnotation(fqName) != null;
|
return descriptor.getOriginal().getAnnotations().findAnnotation(fqName) != null;
|
||||||
|
|||||||
@@ -135,11 +135,10 @@ public class KotlinSuppressIntentionAction(
|
|||||||
private fun suppressAnnotationText(id: String) = "[suppress($id)]"
|
private fun suppressAnnotationText(id: String) = "[suppress($id)]"
|
||||||
|
|
||||||
private fun findSuppressAnnotation(annotated: JetAnnotated): JetAnnotationEntry? {
|
private fun findSuppressAnnotation(annotated: JetAnnotated): JetAnnotationEntry? {
|
||||||
val suppressAnnotationClass = KotlinBuiltIns.getInstance().getSuppressAnnotationClass()
|
|
||||||
val context = AnalyzerFacadeWithCache.getContextForElement(annotated)
|
val context = AnalyzerFacadeWithCache.getContextForElement(annotated)
|
||||||
for (entry in annotated.getAnnotationEntries()) {
|
for (entry in annotated.getAnnotationEntries()) {
|
||||||
val annotationDescriptor = context.get(BindingContext.ANNOTATION, entry)
|
val annotationDescriptor = context.get(BindingContext.ANNOTATION, entry)
|
||||||
if (annotationDescriptor != null && suppressAnnotationClass.getTypeConstructor() == annotationDescriptor.getType().getConstructor()) {
|
if (annotationDescriptor != null && KotlinBuiltIns.getInstance().isSuppressAnnotation(annotationDescriptor)) {
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user