diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java index 093fd35ce24..1059b109f43 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java @@ -17,31 +17,27 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.util.slicedmap.*; import java.util.Collection; -import java.util.List; public class BindingTraceContext implements BindingTrace { - private final List diagnosticList = Lists.newArrayList(); - private final Diagnostics diagnostics; - // These flags are used for debugging of "Rewrite at slice..." exceptions /* package */ final static boolean TRACK_REWRITES = false; /* package */ final static boolean TRACK_WITH_STACK_TRACES = true; private final MutableSlicedMap map; + private final MutableDiagnosticsWithSuppression mutableDiagnostics; private final BindingContext bindingContext = new BindingContext() { @NotNull @Override public Diagnostics getDiagnostics() { - return diagnostics; + return mutableDiagnostics; } @Override @@ -71,7 +67,7 @@ public class BindingTraceContext implements BindingTrace { private BindingTraceContext(@NotNull MutableSlicedMap map) { this.map = map; - this.diagnostics = new DiagnosticsWithSuppression(getBindingContext(), diagnosticList); + this.mutableDiagnostics = new MutableDiagnosticsWithSuppression(bindingContext, Diagnostics.EMPTY); } @TestOnly @@ -81,11 +77,11 @@ public class BindingTraceContext implements BindingTrace { @Override public void report(@NotNull Diagnostic diagnostic) { - diagnosticList.add(diagnostic); + mutableDiagnostics.report(diagnostic); } public void clearDiagnostics() { - diagnosticList.clear(); + mutableDiagnostics.clear(); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatingBindingTrace.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatingBindingTrace.java index 4a12dbd5f72..1cce0933ced 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatingBindingTrace.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatingBindingTrace.java @@ -25,7 +25,6 @@ import org.jetbrains.annotations.TestOnly; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.util.slicedmap.*; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -35,16 +34,14 @@ public class DelegatingBindingTrace implements BindingTrace { private final MutableSlicedMap map = BindingTraceContext.TRACK_REWRITES ? new TrackingSlicedMap(BindingTraceContext.TRACK_WITH_STACK_TRACES) : SlicedMapImpl.create(); private final BindingContext parentContext; - private final List diagnostics = Lists.newArrayList(); private final String name; + private final MutableDiagnosticsWithSuppression mutableDiagnostics; private final BindingContext bindingContext = new BindingContext() { @NotNull @Override public Diagnostics getDiagnostics() { - ArrayList mergedDiagnostics = new ArrayList(diagnostics); - mergedDiagnostics.addAll(parentContext.getDiagnostics().noSuppression().all()); - return new DiagnosticsWithSuppression(this, mergedDiagnostics); + return mutableDiagnostics; } @Override @@ -73,6 +70,7 @@ public class DelegatingBindingTrace implements BindingTrace { public DelegatingBindingTrace(BindingContext parentContext, String debugName) { this.parentContext = parentContext; this.name = debugName; + this.mutableDiagnostics = new MutableDiagnosticsWithSuppression(bindingContext, parentContext.getDiagnostics()); } public DelegatingBindingTrace(BindingContext parentContext, String debugName, @Nullable Object resolutionSubjectForMessage) { @@ -147,7 +145,7 @@ public class DelegatingBindingTrace implements BindingTrace { if (!commitDiagnostics) return; - for (Diagnostic diagnostic : diagnostics) { + for (Diagnostic diagnostic : mutableDiagnostics.getOwnDiagnostics()) { if (filter == null || filter.accept(null, diagnostic.getPsiElement())) { trace.report(diagnostic); } @@ -156,12 +154,12 @@ public class DelegatingBindingTrace implements BindingTrace { public void clear() { map.clear(); - diagnostics.clear(); + mutableDiagnostics.clear(); } @Override public void report(@NotNull Diagnostic diagnostic) { - diagnostics.add(diagnostic); + mutableDiagnostics.report(diagnostic); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Diagnostics.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Diagnostics.kt index 88ef251d5c7..600c8001933 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Diagnostics.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Diagnostics.kt @@ -18,8 +18,13 @@ package org.jetbrains.jet.lang.resolve import com.intellij.psi.PsiElement import org.jetbrains.jet.lang.diagnostics.Diagnostic +import com.intellij.openapi.util.ModificationTracker public trait Diagnostics : Iterable { + //should not be called on readonly views + public val modificationTracker: ModificationTracker + get() = throw IllegalStateException("Trying to obtain modification tracker for Diagnostics object of class $javaClass") + public fun all(): Collection public fun forElement(psiElement: PsiElement): Collection @@ -31,9 +36,9 @@ public trait Diagnostics : Iterable { override fun iterator() = all().iterator() class object { - public val EMPTY: Diagnostics = object : Diagnostics { override fun noSuppression(): Diagnostics = this + override val modificationTracker: ModificationTracker = ModificationTracker.NEVER_CHANGED override fun all() = listOf() override fun forElement(psiElement: PsiElement) = listOf() } 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 f169857ea1e..d9a350c7698 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DiagnosticsWithSuppression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DiagnosticsWithSuppression.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.ImmutableSet; import com.intellij.openapi.diagnostic.Logger; 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; @@ -217,6 +218,12 @@ public class DiagnosticsWithSuppression implements Diagnostics { 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 JetAnnotated annotated; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/MutableDiagnosticsWithSuppression.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/MutableDiagnosticsWithSuppression.kt new file mode 100644 index 00000000000..78095977374 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/MutableDiagnosticsWithSuppression.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2014 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.jet.lang.resolve + +import org.jetbrains.jet.lang.diagnostics.Diagnostic +import java.util.ArrayList +import com.intellij.openapi.util.CompositeModificationTracker +import com.intellij.util.CachedValueImpl +import com.intellij.psi.util.CachedValueProvider +import com.intellij.psi.PsiElement + +public class MutableDiagnosticsWithSuppression( + private val bindingContext: BindingContext, + private val delegateDiagnostics: Diagnostics = Diagnostics.EMPTY +) : Diagnostics { + private val diagnosticList = ArrayList() + + //NOTE: CachedValuesManager is not used because it requires Project passed to this object + private val cache = CachedValueImpl(CachedValueProvider { + val allDiagnostics = delegateDiagnostics.noSuppression().all() + diagnosticList + CachedValueProvider.Result(DiagnosticsWithSuppression(bindingContext, allDiagnostics), modificationTracker) + }) + + private fun readonlyView() = cache.getValue()!! + + public override val modificationTracker = CompositeModificationTracker(delegateDiagnostics.modificationTracker) + + override fun all(): Collection = readonlyView().all() + override fun forElement(psiElement: PsiElement) = readonlyView().forElement(psiElement) + override fun noSuppression() = readonlyView().noSuppression() + + //essential that this list is readonly + fun getOwnDiagnostics(): List = diagnosticList + + fun report(diagnostic: Diagnostic) { + diagnosticList.add(diagnostic) + modificationTracker.incModificationCount() + } + + fun clear() { + diagnosticList.clear() + modificationTracker.incModificationCount() + } + +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index a32b9715664..a5702d0c009 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -124,7 +124,7 @@ public class JetTestUtils { @NotNull @Override public Diagnostics getDiagnostics() { - throw new UnsupportedOperationException(); // TODO + return Diagnostics.EMPTY; } @Override