Add ability for DeclarationDescriptor validation
Not fully initialized DeclarationDescriptor could leak to bindingTrace. It is hard to detect the outcome of that kind of leakage due to possibility to have not fully initialized instances if PCE happens in the middle of publication and instance full initialization. #KT-56364 #KT-56388 #KT-54085 #KT-55150
This commit is contained in:
committed by
Space Team
parent
a049fda75b
commit
b04b3d389f
@@ -17,9 +17,11 @@
|
||||
package org.jetbrains.kotlin.resolve;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.kotlin.descriptors.ValidateableDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.BindingContextSuppressCache;
|
||||
@@ -33,6 +35,7 @@ import org.jetbrains.kotlin.util.slicedMap.*;
|
||||
import java.util.Collection;
|
||||
|
||||
public class BindingTraceContext implements BindingTrace {
|
||||
private static final boolean VALIDATION = Boolean.parseBoolean(System.getProperty("kotlin.bindingTrace.validation"));
|
||||
// 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;
|
||||
@@ -40,6 +43,8 @@ public class BindingTraceContext implements BindingTrace {
|
||||
private final MutableSlicedMap map;
|
||||
private final MutableDiagnosticsWithSuppression mutableDiagnostics;
|
||||
|
||||
private final boolean isValidationEnabled;
|
||||
|
||||
private final BindingContext bindingContext = new CleanableBindingContext() {
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -91,20 +96,25 @@ public class BindingTraceContext implements BindingTrace {
|
||||
}
|
||||
|
||||
public BindingTraceContext(BindingTraceFilter filter, boolean allowSliceRewrite) {
|
||||
this(TRACK_REWRITES && !allowSliceRewrite ? new TrackingSlicedMap(TRACK_WITH_STACK_TRACES) : new SlicedMapImpl(allowSliceRewrite), filter);
|
||||
this(filter, allowSliceRewrite, VALIDATION);
|
||||
}
|
||||
|
||||
private BindingTraceContext(@NotNull MutableSlicedMap map, BindingTraceFilter filter) {
|
||||
public BindingTraceContext(BindingTraceFilter filter, boolean allowSliceRewrite, boolean isValidationEnabled) {
|
||||
this(TRACK_REWRITES && !allowSliceRewrite ? new TrackingSlicedMap(TRACK_WITH_STACK_TRACES) : new SlicedMapImpl(allowSliceRewrite), filter, isValidationEnabled);
|
||||
}
|
||||
|
||||
private BindingTraceContext(@NotNull MutableSlicedMap map, BindingTraceFilter filter, boolean isValidationEnabled) {
|
||||
this.map = map;
|
||||
this.mutableDiagnostics =
|
||||
filter.getIgnoreDiagnostics()
|
||||
? null
|
||||
: new MutableDiagnosticsWithSuppression(new BindingContextSuppressCache(bindingContext), Diagnostics.Companion.getEMPTY());
|
||||
this.isValidationEnabled = isValidationEnabled;
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public static BindingTraceContext createTraceableBindingTrace() {
|
||||
return new BindingTraceContext(new TrackingSlicedMap(TRACK_WITH_STACK_TRACES), BindingTraceFilter.Companion.getACCEPT_ALL());
|
||||
return new BindingTraceContext(new TrackingSlicedMap(TRACK_WITH_STACK_TRACES), BindingTraceFilter.Companion.getACCEPT_ALL(), VALIDATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -134,6 +144,9 @@ public class BindingTraceContext implements BindingTrace {
|
||||
|
||||
@Override
|
||||
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
|
||||
if (isValidationEnabled && value instanceof ValidateableDescriptor && !ProgressManager.getInstance().isInNonCancelableSection()) {
|
||||
((ValidateableDescriptor) value).validate();
|
||||
}
|
||||
map.put(slice, key, value);
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -76,7 +76,7 @@ class LazyAnnotations(
|
||||
class LazyAnnotationDescriptor(
|
||||
val c: LazyAnnotationsContext,
|
||||
val annotationEntry: KtAnnotationEntry
|
||||
) : AnnotationDescriptor, LazyEntity {
|
||||
) : AnnotationDescriptor, LazyEntity, ValidateableDescriptor {
|
||||
|
||||
override val type by c.storageManager.createLazyValue(
|
||||
computable = lazy@{
|
||||
@@ -128,6 +128,11 @@ class LazyAnnotationDescriptor(
|
||||
fun getSourceForArgument(name: Name): SourceElement =
|
||||
valueArgumentsWithSourceInfo[name]?.second ?: SourceElement.NO_SOURCE
|
||||
|
||||
|
||||
override fun validate() {
|
||||
checkNotNull(scope) { "scope == null for $this" }
|
||||
}
|
||||
|
||||
override fun forceResolveAllContents() {
|
||||
ForceResolveUtil.forceResolveAllContents(type)
|
||||
allValueArguments
|
||||
|
||||
+7
@@ -702,6 +702,13 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() {
|
||||
if (parameters == null) {
|
||||
throw new IllegalStateException("parameters == null for " + this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// not using DescriptorRenderer to preserve laziness
|
||||
|
||||
Reference in New Issue
Block a user