From c7c151a72620c3bdcb515fdba7e160f84ba58d0c Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Sun, 22 Sep 2013 22:05:45 +0400 Subject: [PATCH] Support suppression on expressions --- .../jet/lang/cfg/JetControlFlowProcessor.java | 10 +++ .../resolve/DiagnosticsWithSuppression.java | 72 +++++++++---------- .../suppressWarningsOnExpression.kt | 4 ++ .../suppress/manyWarnings/onExpression.kt | 4 ++ .../tests/suppress/oneWarning/onExpression.kt | 4 ++ .../checkers/JetDiagnosticsTestGenerated.java | 15 ++++ 6 files changed, 71 insertions(+), 38 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/suppress/allWarnings/suppressWarningsOnExpression.kt create mode 100644 compiler/testData/diagnostics/tests/suppress/manyWarnings/onExpression.kt create mode 100644 compiler/testData/diagnostics/tests/suppress/oneWarning/onExpression.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 506f33a618d..0427d825e38 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -150,6 +150,16 @@ public class JetControlFlowProcessor { } } + @Override + public void visitAnnotatedExpression(JetAnnotatedExpression expression) { + builder.read(expression); + + JetExpression baseExpression = expression.getBaseExpression(); + if (baseExpression != null) { + generateInstructions(baseExpression, inCondition); + } + } + @Override public void visitThisExpression(JetThisExpression expression) { builder.read(expression); 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 46c62b7ca26..cd7605741d3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DiagnosticsWithSuppression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DiagnosticsWithSuppression.java @@ -9,16 +9,14 @@ 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.annotations.Nullable; 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; +import org.jetbrains.jet.lang.psi.JetAnnotated; import org.jetbrains.jet.lang.psi.JetAnnotationEntry; -import org.jetbrains.jet.lang.psi.JetDeclaration; -import org.jetbrains.jet.lang.psi.JetModifierList; import org.jetbrains.jet.lang.resolve.constants.ArrayValue; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.StringValue; @@ -34,7 +32,7 @@ public class DiagnosticsWithSuppression implements Diagnostics { private final Collection diagnostics; // The cache is weak: we're OK with losing it - private final Map suppressors = new ConcurrentWeakValueHashMap(); + private final Map suppressors = new ConcurrentWeakValueHashMap(); // Caching frequently used values: private final ClassDescriptor suppressClass; @@ -82,14 +80,14 @@ public class DiagnosticsWithSuppression implements Diagnostics { private boolean isSuppressed(@NotNull Diagnostic diagnostic) { PsiElement element = diagnostic.getPsiElement(); - JetDeclaration declaration = PsiTreeUtil.getParentOfType(element, JetDeclaration.class, false); - if (declaration == null) return false; + JetAnnotated annotated = PsiTreeUtil.getParentOfType(element, JetAnnotated.class, false); + if (annotated == null) return false; - return isSuppressedByDeclaration(diagnostic, declaration, 0); + return isSuppressedByAnnotated(diagnostic, annotated, 0); } /* - The cache is optimized for the case where no warnings are suppressed at a declaration (most frequent one) + The cache is optimized for the case where no warnings are suppressed (most frequent one) trait Root { suppress("X") @@ -117,52 +115,50 @@ public class DiagnosticsWithSuppression implements Diagnostics { This way we need no more lookups than the number of suppress() annotations from here to the root. */ - private boolean isSuppressedByDeclaration(@NotNull Diagnostic diagnostic, @NotNull JetDeclaration declaration, int debugDepth) { + private boolean isSuppressedByAnnotated(@NotNull Diagnostic diagnostic, @NotNull JetAnnotated annotated, int debugDepth) { if (LOG.isDebugEnabled()) { - LOG.debug("Declaration: ", declaration.getName()); + LOG.debug("Annotated: ", annotated.getName()); LOG.debug("Depth: ", debugDepth); LOG.debug("Cache size: ", suppressors.size(), "\n"); } - Suppressor suppressor = getOrCreateSuppressor(declaration); + Suppressor suppressor = getOrCreateSuppressor(annotated); if (suppressor.isSuppressed(diagnostic)) return true; - JetDeclaration declarationAbove = PsiTreeUtil.getParentOfType(suppressor.getDeclaration(), JetDeclaration.class, true); - if (declarationAbove == null) return false; + JetAnnotated annotatedAbove = PsiTreeUtil.getParentOfType(suppressor.getAnnotatedElement(), JetAnnotated.class, true); + if (annotatedAbove == null) return false; - boolean suppressed = isSuppressedByDeclaration(diagnostic, declarationAbove, debugDepth + 1); - Suppressor suppressorAbove = suppressors.get(declarationAbove); + boolean suppressed = isSuppressedByAnnotated(diagnostic, annotatedAbove, debugDepth + 1); + Suppressor suppressorAbove = suppressors.get(annotatedAbove); if (suppressorAbove != null && suppressorAbove.dominates(suppressor)) { - suppressors.put(declaration, suppressorAbove); + suppressors.put(annotated, suppressorAbove); } return suppressed; } @NotNull - private Suppressor getOrCreateSuppressor(@NotNull JetDeclaration declaration) { - Suppressor suppressor = suppressors.get(declaration); + private Suppressor getOrCreateSuppressor(@NotNull JetAnnotated annotated) { + Suppressor suppressor = suppressors.get(annotated); if (suppressor == null) { - Set strings = getSuppressingStrings(declaration.getModifierList()); + Set strings = getSuppressingStrings(annotated); if (strings.isEmpty()) { - suppressor = new EmptySuppressor(declaration); + suppressor = new EmptySuppressor(annotated); } else if (strings.size() == 1) { - suppressor = new SingularSuppressor(declaration, strings.iterator().next()); + suppressor = new SingularSuppressor(annotated, strings.iterator().next()); } else { - suppressor = new MultiSuppressor(declaration, strings); + suppressor = new MultiSuppressor(annotated, strings); } - suppressors.put(declaration, suppressor); + suppressors.put(annotated, suppressor); } return suppressor; } - private Set getSuppressingStrings(@Nullable JetModifierList modifierList) { - if (modifierList == null) return ImmutableSet.of(); - + private Set getSuppressingStrings(@NotNull JetAnnotated annotated) { ImmutableSet.Builder builder = ImmutableSet.builder(); - for (JetAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) { + for (JetAnnotationEntry annotationEntry : annotated.getAnnotationEntries()) { AnnotationDescriptor annotationDescriptor = context.get(BindingContext.ANNOTATION, annotationEntry); if (annotationDescriptor == null) { continue; @@ -200,15 +196,15 @@ public class DiagnosticsWithSuppression implements Diagnostics { } private static abstract class Suppressor { - private final JetDeclaration declaration; + private final JetAnnotated annotated; - protected Suppressor(@NotNull JetDeclaration declaration) { - this.declaration = declaration; + protected Suppressor(@NotNull JetAnnotated annotated) { + this.annotated = annotated; } @NotNull - public JetDeclaration getDeclaration() { - return declaration; + public JetAnnotated getAnnotatedElement() { + return annotated; } public abstract boolean isSuppressed(@NotNull Diagnostic diagnostic); @@ -219,8 +215,8 @@ public class DiagnosticsWithSuppression implements Diagnostics { private static class EmptySuppressor extends Suppressor { - private EmptySuppressor(@NotNull JetDeclaration declaration) { - super(declaration); + private EmptySuppressor(@NotNull JetAnnotated annotated) { + super(annotated); } @Override @@ -237,8 +233,8 @@ public class DiagnosticsWithSuppression implements Diagnostics { private static class SingularSuppressor extends Suppressor { private final String string; - private SingularSuppressor(@NotNull JetDeclaration declaration, @NotNull String string) { - super(declaration); + private SingularSuppressor(@NotNull JetAnnotated annotated, @NotNull String string) { + super(annotated); this.string = string; } @@ -257,8 +253,8 @@ public class DiagnosticsWithSuppression implements Diagnostics { private static class MultiSuppressor extends Suppressor { private final Set strings; - private MultiSuppressor(@NotNull JetDeclaration declaration, @NotNull Set strings) { - super(declaration); + private MultiSuppressor(@NotNull JetAnnotated annotated, @NotNull Set strings) { + super(annotated); this.strings = strings; } diff --git a/compiler/testData/diagnostics/tests/suppress/allWarnings/suppressWarningsOnExpression.kt b/compiler/testData/diagnostics/tests/suppress/allWarnings/suppressWarningsOnExpression.kt new file mode 100644 index 00000000000..d3fc5cdb91d --- /dev/null +++ b/compiler/testData/diagnostics/tests/suppress/allWarnings/suppressWarningsOnExpression.kt @@ -0,0 +1,4 @@ +fun foo() { + [suppress("warnings")] + ("": String??) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/suppress/manyWarnings/onExpression.kt b/compiler/testData/diagnostics/tests/suppress/manyWarnings/onExpression.kt new file mode 100644 index 00000000000..df970125c19 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suppress/manyWarnings/onExpression.kt @@ -0,0 +1,4 @@ +fun foo(): Any? { + [suppress("REDUNDANT_NULLABLE", "UNNECESSARY_NOT_NULL_ASSERTION")] + return ""!! as String?? +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/suppress/oneWarning/onExpression.kt b/compiler/testData/diagnostics/tests/suppress/oneWarning/onExpression.kt new file mode 100644 index 00000000000..2735e70a695 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suppress/oneWarning/onExpression.kt @@ -0,0 +1,4 @@ +fun foo(): Any? { + [suppress("REDUNDANT_NULLABLE")] + return null as Nothing?? +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index d5b7ded5faf..7e7d55b2d5b 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -5598,6 +5598,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/suppress/allWarnings/suppressWarningsOnClassObject.kt"); } + @TestMetadata("suppressWarningsOnExpression.kt") + public void testSuppressWarningsOnExpression() throws Exception { + doTest("compiler/testData/diagnostics/tests/suppress/allWarnings/suppressWarningsOnExpression.kt"); + } + @TestMetadata("suppressWarningsOnFunction.kt") public void testSuppressWarningsOnFunction() throws Exception { doTest("compiler/testData/diagnostics/tests/suppress/allWarnings/suppressWarningsOnFunction.kt"); @@ -5646,6 +5651,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/suppress/manyWarnings/onClassObject.kt"); } + @TestMetadata("onExpression.kt") + public void testOnExpression() throws Exception { + doTest("compiler/testData/diagnostics/tests/suppress/manyWarnings/onExpression.kt"); + } + @TestMetadata("onFunction.kt") public void testOnFunction() throws Exception { doTest("compiler/testData/diagnostics/tests/suppress/manyWarnings/onFunction.kt"); @@ -5689,6 +5699,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/suppress/oneWarning/onClassObject.kt"); } + @TestMetadata("onExpression.kt") + public void testOnExpression() throws Exception { + doTest("compiler/testData/diagnostics/tests/suppress/oneWarning/onExpression.kt"); + } + @TestMetadata("onFunction.kt") public void testOnFunction() throws Exception { doTest("compiler/testData/diagnostics/tests/suppress/oneWarning/onFunction.kt");