Refactoring: extract separate class that can store suppressions

This commit is contained in:
Nikolay Krasko
2015-11-26 22:12:23 +03:00
committed by Nikolay Krasko
parent e562b73eff
commit 20379028e8
6 changed files with 268 additions and 280 deletions
@@ -16,73 +16,28 @@
package org.jetbrains.kotlin.resolve.diagnostics;
import com.google.common.collect.ImmutableSet;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.ConcurrentWeakValueHashMap;
import com.intellij.util.containers.FilteringIterator;
import kotlin.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.diagnostics.Severity;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.constants.ArrayValue;
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
import org.jetbrains.kotlin.resolve.constants.StringValue;
import org.jetbrains.kotlin.util.ExtensionProvider;
import java.util.*;
import java.util.Collection;
import java.util.Iterator;
public class DiagnosticsWithSuppression implements Diagnostics {
public interface SuppressStringProvider {
ExtensionPointName<SuppressStringProvider> EP_NAME = ExtensionPointName.create("org.jetbrains.kotlin.suppressStringProvider");
@NotNull
List<String> get(@NotNull AnnotationDescriptor annotationDescriptor);
}
public interface DiagnosticSuppressor {
ExtensionPointName<DiagnosticSuppressor> EP_NAME = ExtensionPointName.create("org.jetbrains.kotlin.diagnosticSuppressor");
boolean isSuppressed(@NotNull Diagnostic diagnostic);
}
private static final Logger LOG = Logger.getInstance(DiagnosticsWithSuppression.class);
private static final ExtensionProvider<SuppressStringProvider> ADDITIONAL_SUPPRESS_STRING_PROVIDERS
= ExtensionProvider.create(SuppressStringProvider.EP_NAME);
private static final ExtensionProvider<DiagnosticSuppressor> DIAGNOSTIC_SUPPRESSORS
= ExtensionProvider.create(DiagnosticSuppressor.EP_NAME);
private final BindingContext context;
private final SuppressionManager suppressionManager;
private final Collection<Diagnostic> diagnostics;
// The cache is weak: we're OK with losing it
private final Map<KtAnnotated, Suppressor> suppressors = new ConcurrentWeakValueHashMap<KtAnnotated, Suppressor>();
private final Function1<Diagnostic, Boolean> filter = new Function1<Diagnostic, Boolean>() {
@Override
public Boolean invoke(Diagnostic diagnostic) {
return !isSuppressed(diagnostic);
}
};
private final DiagnosticsElementsCache elementsCache = new DiagnosticsElementsCache(this, filter);
private final DiagnosticsElementsCache elementsCache;
public DiagnosticsWithSuppression(@NotNull BindingContext context, @NotNull Collection<Diagnostic> diagnostics) {
this.context = context;
this.diagnostics = diagnostics;
this.suppressionManager = new SuppressionManager(context);
this.elementsCache = new DiagnosticsElementsCache(this, suppressionManager.getFilter());
}
@NotNull
@@ -97,7 +52,7 @@ public class DiagnosticsWithSuppression implements Diagnostics {
return new FilteringIterator<Diagnostic, Diagnostic>(diagnostics.iterator(), new Condition<Diagnostic>() {
@Override
public boolean value(Diagnostic diagnostic) {
return filter.invoke(diagnostic);
return suppressionManager.getFilter().invoke(diagnostic);
}
});
}
@@ -105,7 +60,7 @@ public class DiagnosticsWithSuppression implements Diagnostics {
@NotNull
@Override
public Collection<Diagnostic> all() {
return CollectionsKt.filter(diagnostics, filter);
return CollectionsKt.filter(diagnostics, suppressionManager.getFilter());
}
@NotNull
@@ -119,223 +74,12 @@ public class DiagnosticsWithSuppression implements Diagnostics {
return all().isEmpty();
}
private boolean isSuppressed(@NotNull Diagnostic diagnostic) {
PsiElement element = diagnostic.getPsiElement();
// If diagnostics are reported in a synthetic file generated by KtPsiFactory (dummy.kt),
// there's no point to present such diagnostics to the user, because the user didn't write this code
PsiFile file = element.getContainingFile();
if (file instanceof KtFile) {
if (KtPsiFactoryKt.getDoNotAnalyze((KtFile) file) != null) return true;
}
for (DiagnosticSuppressor suppressor : DIAGNOSTIC_SUPPRESSORS.get()) {
if (suppressor.isSuppressed(diagnostic)) return true;
}
KtAnnotated annotated = KtStubbedPsiUtil.getPsiOrStubParent(element, KtAnnotated.class, false);
if (annotated == null) return false;
return isSuppressedByAnnotated(diagnostic, annotated, 0);
}
/*
The cache is optimized for the case where no warnings are suppressed (most frequent one)
trait Root {
suppress("X")
trait A {
trait B {
suppress("Y")
trait C {
fun foo() = warning
}
}
}
}
Nothing is suppressed at foo, so we look above. While looking above we went up to the root (once) and propagated
all the suppressors down, so now we have:
foo - suppress(Y) from C
C - suppress(Y) from C
B - suppress(X) from A
A - suppress(X) from A
Root - suppress() from Root
Next time we look up anything under foo, we try the Y-suppressor and then immediately the X-suppressor, then to the empty
suppressor at the root. All the intermediate empty nodes are skipped, because every suppressor remembers its definition point.
This way we need no more lookups than the number of suppress() annotations from here to the root.
*/
private boolean isSuppressedByAnnotated(@NotNull Diagnostic diagnostic, @NotNull KtAnnotated annotated, int debugDepth) {
if (LOG.isDebugEnabled()) {
LOG.debug("Annotated: ", annotated.getName());
LOG.debug("Depth: ", debugDepth);
LOG.debug("Cache size: ", suppressors.size(), "\n");
}
Suppressor suppressor = getOrCreateSuppressor(annotated);
if (suppressor.isSuppressed(diagnostic)) return true;
KtAnnotated annotatedAbove = KtStubbedPsiUtil.getPsiOrStubParent(suppressor.getAnnotatedElement(), KtAnnotated.class, true);
if (annotatedAbove == null) return false;
boolean suppressed = isSuppressedByAnnotated(diagnostic, annotatedAbove, debugDepth + 1);
Suppressor suppressorAbove = suppressors.get(annotatedAbove);
if (suppressorAbove != null && suppressorAbove.dominates(suppressor)) {
suppressors.put(annotated, suppressorAbove);
}
return suppressed;
}
@NotNull
private Suppressor getOrCreateSuppressor(@NotNull KtAnnotated annotated) {
Suppressor suppressor = suppressors.get(annotated);
if (suppressor == null) {
Set<String> strings = getSuppressingStrings(annotated);
if (strings.isEmpty()) {
suppressor = new EmptySuppressor(annotated);
}
else if (strings.size() == 1) {
suppressor = new SingularSuppressor(annotated, strings.iterator().next());
}
else {
suppressor = new MultiSuppressor(annotated, strings);
}
suppressors.put(annotated, suppressor);
}
return suppressor;
}
private Set<String> getSuppressingStrings(@NotNull KtAnnotated annotated) {
ImmutableSet.Builder<String> builder = ImmutableSet.builder();
DeclarationDescriptor descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, annotated);
if (descriptor != null) {
for (AnnotationDescriptor annotationDescriptor : descriptor.getAnnotations()) {
processAnnotation(builder, annotationDescriptor);
}
}
else {
for (KtAnnotationEntry annotationEntry : annotated.getAnnotationEntries()) {
AnnotationDescriptor annotationDescriptor = context.get(BindingContext.ANNOTATION, annotationEntry);
processAnnotation(builder, annotationDescriptor);
}
}
return builder.build();
}
private void processAnnotation(ImmutableSet.Builder<String> builder, AnnotationDescriptor annotationDescriptor) {
if (annotationDescriptor == null) return;
for (SuppressStringProvider suppressStringProvider : ADDITIONAL_SUPPRESS_STRING_PROVIDERS.get()) {
builder.addAll(suppressStringProvider.get(annotationDescriptor));
}
if (!KotlinBuiltIns.isSuppressAnnotation(annotationDescriptor)) return;
// We only add strings and skip other values to facilitate recovery in presence of erroneous code
for (ConstantValue<?> arrayValue : annotationDescriptor.getAllValueArguments().values()) {
if ((arrayValue instanceof ArrayValue)) {
for (ConstantValue<?> value : ((ArrayValue) arrayValue).getValue()) {
if (value instanceof StringValue) {
builder.add(String.valueOf(((StringValue) value).getValue()).toLowerCase());
}
}
}
}
}
public static boolean isSuppressedByStrings(@NotNull Diagnostic diagnostic, @NotNull Set<String> strings) {
if (strings.contains("warnings") && diagnostic.getSeverity() == Severity.WARNING) return true;
return strings.contains(diagnostic.getFactory().getName().toLowerCase());
}
@NotNull
@Override
public ModificationTracker getModificationTracker() {
throw new IllegalStateException("Trying to obtain modification tracker for readonly DiagnosticsWithSuppression.");
}
private static abstract class Suppressor {
private final KtAnnotated annotated;
protected Suppressor(@NotNull KtAnnotated annotated) {
this.annotated = annotated;
}
@NotNull
public KtAnnotated getAnnotatedElement() {
return annotated;
}
public abstract boolean isSuppressed(@NotNull Diagnostic diagnostic);
// true is \forall x. other.isSuppressed(x) -> this.isSuppressed(x)
public abstract boolean dominates(@NotNull Suppressor other);
}
private static class EmptySuppressor extends Suppressor {
private EmptySuppressor(@NotNull KtAnnotated annotated) {
super(annotated);
}
@Override
public boolean isSuppressed(@NotNull Diagnostic diagnostic) {
return false;
}
@Override
public boolean dominates(@NotNull Suppressor other) {
return other instanceof EmptySuppressor;
}
}
private static class SingularSuppressor extends Suppressor {
private final String string;
private SingularSuppressor(@NotNull KtAnnotated annotated, @NotNull String string) {
super(annotated);
this.string = string;
}
@Override
public boolean isSuppressed(@NotNull Diagnostic diagnostic) {
return isSuppressedByStrings(diagnostic, ImmutableSet.of(string));
}
@Override
public boolean dominates(@NotNull Suppressor other) {
return other instanceof EmptySuppressor
|| (other instanceof SingularSuppressor && ((SingularSuppressor) other).string.equals(string));
}
}
private static class MultiSuppressor extends Suppressor {
private final Set<String> strings;
private MultiSuppressor(@NotNull KtAnnotated annotated, @NotNull Set<String> strings) {
super(annotated);
this.strings = strings;
}
@Override
public boolean isSuppressed(@NotNull Diagnostic diagnostic) {
return isSuppressedByStrings(diagnostic, strings);
}
@Override
public boolean dominates(@NotNull Suppressor other) {
// it's too costly to check set inclusion
return other instanceof EmptySuppressor;
}
}
@TestOnly
@NotNull
public Collection<Diagnostic> getDiagnostics() {
@@ -37,7 +37,7 @@ public val PROPERTY_NOT_INITIALIZED_ERRORS: List<DiagnosticFactory0<KtProperty>>
public abstract class SuppressDiagnosticsByAnnotations(
diagnosticsToSuppress: List<DiagnosticFactory<out Diagnostic>>,
vararg annotationsFqName: FqName
) : DiagnosticsWithSuppression.SuppressStringProvider {
) : SuppressStringProvider {
private val annotationsFqName = annotationsFqName
private val stringsToSuppress = diagnosticsToSuppress.map { it.getName().toLowerCase() }
@@ -0,0 +1,244 @@
/*
* Copyright 2010-2015 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.kotlin.resolve.diagnostics
import com.google.common.collect.ImmutableSet
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.util.containers.ConcurrentWeakValueHashMap
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.psi.KtAnnotated
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtStubbedPsiUtil
import org.jetbrains.kotlin.psi.doNotAnalyze
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.util.ExtensionProvider
interface SuppressStringProvider {
operator fun get(annotationDescriptor: AnnotationDescriptor): List<String>
companion object {
val EP_NAME = ExtensionPointName.create<SuppressStringProvider>("org.jetbrains.kotlin.suppressStringProvider")
}
}
interface DiagnosticSuppressor {
fun isSuppressed(diagnostic: Diagnostic): Boolean
companion object {
val EP_NAME = ExtensionPointName.create<DiagnosticSuppressor>("org.jetbrains.kotlin.diagnosticSuppressor")
}
}
class SuppressionManager(val context: BindingContext) {
private val LOG = Logger.getInstance(DiagnosticsWithSuppression::class.java)
private val ADDITIONAL_SUPPRESS_STRING_PROVIDERS = ExtensionProvider.create(SuppressStringProvider.EP_NAME)
private val DIAGNOSTIC_SUPPRESSORS = ExtensionProvider.create(DiagnosticSuppressor.EP_NAME)
// The cache is weak: we're OK with losing it
private val suppressors = ConcurrentWeakValueHashMap<KtAnnotated, Suppressor>()
public val filter: (Diagnostic) -> Boolean = { diagnostic: Diagnostic -> !isSuppressed(diagnostic) }
private fun isSuppressed(diagnostic: Diagnostic): Boolean {
val element = diagnostic.psiElement
// If diagnostics are reported in a synthetic file generated by KtPsiFactory (dummy.kt),
// there's no point to present such diagnostics to the user, because the user didn't write this code
val file = element.containingFile
if (file is KtFile) {
if (file.doNotAnalyze != null) return true
}
for (suppressor in DIAGNOSTIC_SUPPRESSORS.get()) {
if (suppressor.isSuppressed(diagnostic)) return true
}
val annotated = KtStubbedPsiUtil.getPsiOrStubParent(element, KtAnnotated::class.java, false) ?: return false
return isSuppressedByAnnotated(diagnostic, annotated, 0)
}
/*
The cache is optimized for the case where no warnings are suppressed (most frequent one)
trait Root {
suppress("X")
trait A {
trait B {
suppress("Y")
trait C {
fun foo() = warning
}
}
}
}
Nothing is suppressed at foo, so we look above. While looking above we went up to the root (once) and propagated
all the suppressors down, so now we have:
foo - suppress(Y) from C
C - suppress(Y) from C
B - suppress(X) from A
A - suppress(X) from A
Root - suppress() from Root
Next time we look up anything under foo, we try the Y-suppressor and then immediately the X-suppressor, then to the empty
suppressor at the root. All the intermediate empty nodes are skipped, because every suppressor remembers its definition point.
This way we need no more lookups than the number of suppress() annotations from here to the root.
*/
private fun isSuppressedByAnnotated(diagnostic: Diagnostic, annotated: KtAnnotated, debugDepth: Int): Boolean {
if (LOG.isDebugEnabled) {
LOG.debug("Annotated: ", annotated.name)
LOG.debug("Depth: ", debugDepth)
LOG.debug("Cache size: ", suppressors.size, "\n")
}
val suppressor = getOrCreateSuppressor(annotated)
if (suppressor.isSuppressed(diagnostic)) return true
val annotatedAbove = KtStubbedPsiUtil.getPsiOrStubParent(suppressor.annotatedElement, KtAnnotated::class.java, true) ?: return false
val suppressed = isSuppressedByAnnotated(diagnostic, annotatedAbove, debugDepth + 1)
val suppressorAbove = suppressors[annotatedAbove]
if (suppressorAbove != null && suppressorAbove.dominates(suppressor)) {
suppressors.put(annotated, suppressorAbove)
}
return suppressed
}
private fun getOrCreateSuppressor(annotated: KtAnnotated): Suppressor {
var suppressor: Suppressor? = suppressors[annotated]
if (suppressor == null) {
val strings = getSuppressingStrings(annotated)
if (strings.isEmpty()) {
suppressor = EmptySuppressor(annotated)
}
else if (strings.size == 1) {
suppressor = SingularSuppressor(annotated, strings.iterator().next())
}
else {
suppressor = MultiSuppressor(annotated, strings)
}
suppressors.put(annotated, suppressor)
}
return suppressor
}
private fun getSuppressingStrings(annotated: KtAnnotated): Set<String> {
val builder = ImmutableSet.builder<String>()
val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, annotated)
if (descriptor != null) {
for (annotationDescriptor in descriptor.annotations) {
processAnnotation(builder, annotationDescriptor)
}
}
else {
for (annotationEntry in annotated.annotationEntries) {
val annotationDescriptor = context.get(BindingContext.ANNOTATION, annotationEntry)
processAnnotation(builder, annotationDescriptor)
}
}
return builder.build()
}
private fun processAnnotation(builder: ImmutableSet.Builder<String>, annotationDescriptor: AnnotationDescriptor?) {
if (annotationDescriptor == null) return
for (suppressStringProvider in ADDITIONAL_SUPPRESS_STRING_PROVIDERS.get()) {
builder.addAll(suppressStringProvider[annotationDescriptor])
}
if (!KotlinBuiltIns.isSuppressAnnotation(annotationDescriptor)) return
// We only add strings and skip other values to facilitate recovery in presence of erroneous code
for (arrayValue in annotationDescriptor.allValueArguments.values) {
if ((arrayValue is ArrayValue)) {
for (value in arrayValue.value) {
if (value is StringValue) {
builder.add(value.value.toString().toLowerCase())
}
}
}
}
}
companion object {
fun getDiagnosticSuppressKey(diagnostic: Diagnostic): String {
return diagnostic.factory.name.toLowerCase()
}
fun isSuppressedByStrings(key: String, strings: Set<String>, severity: Severity): Boolean {
if (strings.contains("warnings") && severity == Severity.WARNING) return true
return strings.contains(key)
}
}
private abstract class Suppressor protected constructor(val annotatedElement: KtAnnotated) {
abstract fun isSuppressed(diagnostic: Diagnostic): Boolean
abstract fun isSuppressed(suppressionKey: String, severity: Severity): Boolean
// true is \forall x. other.isSuppressed(x) -> this.isSuppressed(x)
abstract fun dominates(other: Suppressor): Boolean
}
private class EmptySuppressor(annotated: KtAnnotated) : Suppressor(annotated) {
override fun isSuppressed(diagnostic: Diagnostic): Boolean = false
override fun isSuppressed(suppressionKey: String, severity: Severity): Boolean = false
override fun dominates(other: Suppressor): Boolean = other is EmptySuppressor
}
private class SingularSuppressor(annotated: KtAnnotated, private val string: String) : Suppressor(annotated) {
override fun isSuppressed(diagnostic: Diagnostic): Boolean {
return isSuppressed(getDiagnosticSuppressKey(diagnostic), diagnostic.severity)
}
override fun isSuppressed(suppressionKey: String, severity: Severity): Boolean {
return isSuppressedByStrings(suppressionKey, ImmutableSet.of(string), severity)
}
override fun dominates(other: Suppressor): Boolean {
return other is EmptySuppressor || (other is SingularSuppressor && other.string == string)
}
}
private class MultiSuppressor(annotated: KtAnnotated, private val strings: Set<String>) : Suppressor(annotated) {
override fun isSuppressed(diagnostic: Diagnostic): Boolean {
return isSuppressed(getDiagnosticSuppressKey(diagnostic), diagnostic.severity)
}
override fun isSuppressed(suppressionKey: String, severity: Severity): Boolean {
return isSuppressedByStrings(suppressionKey, strings, severity)
}
override fun dominates(other: Suppressor): Boolean {
// it's too costly to check set inclusion
return other is EmptySuppressor
}
}
}
+2 -2
View File
@@ -5,9 +5,9 @@
<extensionPoint name="defaultErrorMessages"
interface="org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages$Extension"/>
<extensionPoint name="suppressStringProvider"
interface="org.jetbrains.kotlin.resolve.diagnostics.DiagnosticsWithSuppression$SuppressStringProvider"/>
interface="org.jetbrains.kotlin.resolve.diagnostics.SuppressStringProvider"/>
<extensionPoint name="diagnosticSuppressor"
interface="org.jetbrains.kotlin.resolve.diagnostics.DiagnosticsWithSuppression$DiagnosticSuppressor"/>
interface="org.jetbrains.kotlin.resolve.diagnostics.DiagnosticSuppressor"/>
<extensionPoint name="externalDeclarationsProvider"
interface="org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider"
area="IDEA_PROJECT"/>
@@ -20,9 +20,9 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticsWithSuppression
import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticSuppressor
public class DiagnosticSuppressorForDebugger : DiagnosticsWithSuppression.DiagnosticSuppressor {
public class DiagnosticSuppressorForDebugger : DiagnosticSuppressor {
override fun isSuppressed(diagnostic: Diagnostic): Boolean {
val element = diagnostic.getPsiElement()
val containingFile = element.getContainingFile()
@@ -16,20 +16,20 @@
package org.jetbrains.kotlin.js.analyze
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.js.PredefinedAnnotation.*
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.js.config.LibrarySourcesConfig
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticWithParameters1
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.js.PredefinedAnnotation.*
import org.jetbrains.kotlin.js.config.LibrarySourcesConfig
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticsWithSuppression
import org.jetbrains.kotlin.resolve.diagnostics.SuppressDiagnosticsByAnnotations
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticSuppressor
import org.jetbrains.kotlin.resolve.diagnostics.FUNCTION_NO_BODY_ERRORS
import org.jetbrains.kotlin.resolve.diagnostics.PROPERTY_NOT_INITIALIZED_ERRORS
import org.jetbrains.kotlin.resolve.diagnostics.SuppressDiagnosticsByAnnotations
private val NATIVE_ANNOTATIONS = arrayOf(NATIVE.fqName, NATIVE_INVOKE.fqName, NATIVE_GETTER.fqName, NATIVE_SETTER.fqName)
@@ -37,7 +37,7 @@ public class SuppressUnusedParameterForJsNative : SuppressDiagnosticsByAnnotatio
public class SuppressNoBodyErrorsForNativeDeclarations : SuppressDiagnosticsByAnnotations(FUNCTION_NO_BODY_ERRORS + PROPERTY_NOT_INITIALIZED_ERRORS, *NATIVE_ANNOTATIONS)
public class SuppressUninitializedErrorsForNativeDeclarations : DiagnosticsWithSuppression.DiagnosticSuppressor {
public class SuppressUninitializedErrorsForNativeDeclarations : DiagnosticSuppressor {
override fun isSuppressed(diagnostic: Diagnostic): Boolean {
if (diagnostic.getFactory() != Errors.UNINITIALIZED_VARIABLE) return false
@@ -50,7 +50,7 @@ public class SuppressUninitializedErrorsForNativeDeclarations : DiagnosticsWithS
}
}
public class SuppressWarningsFromExternalModules : DiagnosticsWithSuppression.DiagnosticSuppressor {
public class SuppressWarningsFromExternalModules : DiagnosticSuppressor {
override fun isSuppressed(diagnostic: Diagnostic): Boolean {
val file = diagnostic.getPsiFile()
return diagnostic.getSeverity() == Severity.WARNING &&