Binding trace filtering: do not calculate diagnostics if no one is going to query them

This commit is contained in:
Dmitry Jemerov
2016-09-26 12:48:46 +02:00
parent b365e547c4
commit d8b0c7aaec
24 changed files with 230 additions and 89 deletions
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.BindingTraceFilter
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
@@ -67,7 +68,8 @@ class GenerationState @JvmOverloads constructor(
// partial compilation. Module chunks are treated as a single module.
// TODO: get rid of it with the proper module infrastructure
val outDirectory: File? = null,
private val onIndependentPartCompilationEnd: GenerationStateEventCallback = GenerationStateEventCallback.DO_NOTHING
private val onIndependentPartCompilationEnd: GenerationStateEventCallback = GenerationStateEventCallback.DO_NOTHING,
wantsDiagnostics: Boolean = true
) {
abstract class GenerateClassFilter {
abstract fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean
@@ -129,7 +131,8 @@ class GenerationState @JvmOverloads constructor(
val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
val classBuilderMode: ClassBuilderMode = builderFactory.classBuilderMode
val bindingTrace: BindingTrace = DelegatingBindingTrace(bindingContext, "trace in GenerationState")
val bindingTrace: BindingTrace = DelegatingBindingTrace(bindingContext, "trace in GenerationState",
filter = if (wantsDiagnostics) BindingTraceFilter.ACCEPT_ALL else BindingTraceFilter.NO_DIAGNOSTICS)
val bindingContext: BindingContext = bindingTrace.bindingContext
val typeMapper: KotlinTypeMapper = KotlinTypeMapper(
this.bindingContext, classBuilderMode, fileClassesProvider, incrementalCacheForThisTarget,
@@ -86,13 +86,17 @@ class ControlFlowInformationProvider private constructor(
markUninitializedVariables()
markUnusedVariables()
if (trace.wantsDiagnostics()) {
markUnusedVariables()
}
markStatements()
markUnusedExpressions()
checkIfExpressions()
if (trace.wantsDiagnostics()) {
checkIfExpressions()
}
checkWhenExpressions()
@@ -82,6 +82,11 @@ public class PseudocodeUtil {
@Override
public void report(@NotNull Diagnostic diagnostic) {
}
@Override
public boolean wantsDiagnostics() {
return false;
}
};
return new ControlFlowProcessor(mockTrace).generatePseudocode(declaration);
}
@@ -30,6 +30,11 @@ public interface DiagnosticSink {
@Override
public void report(@NotNull Diagnostic diagnostic) {
}
@Override
public boolean wantsDiagnostics() {
return false;
}
};
DiagnosticSink THROW_EXCEPTION = new DiagnosticSink() {
@@ -42,7 +47,13 @@ public interface DiagnosticSink {
throw new IllegalStateException(diagnostic.getFactory().getName() + ": " + diagnosticText + " " + DiagnosticUtils.atLocation(psiFile, textRanges.get(0)));
}
}
@Override
public boolean wantsDiagnostics() {
return true;
}
};
void report(@NotNull Diagnostic diagnostic);
boolean wantsDiagnostics();
}
@@ -37,14 +37,15 @@ public class BindingTraceContext implements BindingTrace {
/* package */ final static boolean TRACK_WITH_STACK_TRACES = true;
private final MutableSlicedMap map;
private final MutableDiagnosticsWithSuppression mutableDiagnostics;
@Nullable private final MutableDiagnosticsWithSuppression mutableDiagnostics;
@NotNull private final BindingTraceFilter filter;
private final BindingContext bindingContext = new BindingContext() {
@NotNull
@Override
public Diagnostics getDiagnostics() {
return mutableDiagnostics;
return mutableDiagnostics != null ? mutableDiagnostics : Diagnostics.Companion.getEMPTY();
}
@Override
@@ -78,28 +79,45 @@ public class BindingTraceContext implements BindingTrace {
};
public BindingTraceContext() {
this(BindingTraceFilter.Companion.getACCEPT_ALL());
}
public BindingTraceContext(BindingTraceFilter filter) {
//noinspection ConstantConditions
this(TRACK_REWRITES ? new TrackingSlicedMap(TRACK_WITH_STACK_TRACES) : SlicedMapImpl.create());
this(TRACK_REWRITES ? new TrackingSlicedMap(TRACK_WITH_STACK_TRACES) : SlicedMapImpl.create(), filter);
}
private BindingTraceContext(@NotNull MutableSlicedMap map) {
private BindingTraceContext(@NotNull MutableSlicedMap map, BindingTraceFilter filter) {
this.map = map;
this.mutableDiagnostics = new MutableDiagnosticsWithSuppression(bindingContext, Diagnostics.Companion.getEMPTY());
this.mutableDiagnostics = !filter.getIgnoreDiagnostics()
? new MutableDiagnosticsWithSuppression(bindingContext, Diagnostics.Companion.getEMPTY())
: null;
this.filter = filter;
}
@TestOnly
public static BindingTraceContext createTraceableBindingTrace() {
return new BindingTraceContext(new TrackingSlicedMap(TRACK_WITH_STACK_TRACES));
return new BindingTraceContext(new TrackingSlicedMap(TRACK_WITH_STACK_TRACES), BindingTraceFilter.Companion.getACCEPT_ALL());
}
@Override
public void report(@NotNull Diagnostic diagnostic) {
if (mutableDiagnostics == null) {
return;
}
mutableDiagnostics.report(diagnostic);
}
public void clearDiagnostics() {
mutableDiagnostics.clear();
if (mutableDiagnostics != null) {
mutableDiagnostics.clear();
}
}
@Override
public boolean wantsDiagnostics() {
return mutableDiagnostics != null;
}
@NotNull
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2016 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
class BindingTraceFilter(val ignoreDiagnostics: Boolean) {
companion object {
val ACCEPT_ALL = BindingTraceFilter(false)
val NO_DIAGNOSTICS = BindingTraceFilter(true)
}
fun includesEverythingIn(otherFilter: BindingTraceFilter): Boolean {
if (ignoreDiagnostics && !otherFilter.ignoreDiagnostics) {
return false
}
return true
}
}
@@ -28,12 +28,13 @@ import org.jetbrains.kotlin.util.slicedMap.*
open class DelegatingBindingTrace(private val parentContext: BindingContext,
private val name: String,
withParentDiagnostics: Boolean = true) : BindingTrace {
withParentDiagnostics: Boolean = true,
private val filter: BindingTraceFilter = BindingTraceFilter.ACCEPT_ALL) : BindingTrace {
private val map = if (BindingTraceContext.TRACK_REWRITES) TrackingSlicedMap(BindingTraceContext.TRACK_WITH_STACK_TRACES) else SlicedMapImpl.create()
private val mutableDiagnostics: MutableDiagnosticsWithSuppression
private val mutableDiagnostics: MutableDiagnosticsWithSuppression?
private inner class MyBindingContext : BindingContext {
override fun getDiagnostics(): Diagnostics = mutableDiagnostics
override fun getDiagnostics(): Diagnostics = mutableDiagnostics ?: Diagnostics.EMPTY
override fun <K, V> get(slice: ReadOnlySlice<K, V>, key: K): V? {
return this@DelegatingBindingTrace.get(slice, key)
@@ -60,7 +61,9 @@ open class DelegatingBindingTrace(private val parentContext: BindingContext,
private val bindingContext = MyBindingContext()
init {
this.mutableDiagnostics = if (withParentDiagnostics)
this.mutableDiagnostics = if (filter.ignoreDiagnostics)
null
else if (withParentDiagnostics)
MutableDiagnosticsWithSuppression(bindingContext, parentContext.diagnostics)
else
MutableDiagnosticsWithSuppression(bindingContext)
@@ -68,7 +71,11 @@ open class DelegatingBindingTrace(private val parentContext: BindingContext,
constructor(parentContext: BindingContext,
debugName: String,
resolutionSubjectForMessage: Any?) : this(parentContext, AnalyzingUtils.formDebugNameForBindingTrace(debugName, resolutionSubjectForMessage)) {
resolutionSubjectForMessage: Any?,
filter: BindingTraceFilter = BindingTraceFilter.ACCEPT_ALL)
: this(parentContext,
AnalyzingUtils.formDebugNameForBindingTrace(debugName, resolutionSubjectForMessage),
filter = filter) {
}
override fun getBindingContext(): BindingContext = bindingContext
@@ -130,12 +137,17 @@ open class DelegatingBindingTrace(private val parentContext: BindingContext,
fun clear() {
map.clear()
mutableDiagnostics.clear()
mutableDiagnostics?.clear()
}
override fun report(diagnostic: Diagnostic) {
if (mutableDiagnostics == null) {
return
}
mutableDiagnostics.report(diagnostic)
}
override fun wantsDiagnostics(): Boolean = mutableDiagnostics != null
override fun toString(): String = name
}
@@ -91,5 +91,9 @@ public class ObservableBindingTrace implements BindingTrace {
handlers = handlers.plus(slice, handler);
return this;
}
@Override
public boolean wantsDiagnostics() {
return originalTrace.wantsDiagnostics();
}
}
@@ -23,7 +23,12 @@ public class TemporaryBindingTrace extends DelegatingBindingTrace {
@NotNull
public static TemporaryBindingTrace create(@NotNull BindingTrace trace, String debugName) {
return new TemporaryBindingTrace(trace, debugName);
return create(trace, debugName, BindingTraceFilter.Companion.getACCEPT_ALL());
}
@NotNull
public static TemporaryBindingTrace create(@NotNull BindingTrace trace, String debugName, BindingTraceFilter filter) {
return new TemporaryBindingTrace(trace, debugName, filter);
}
@NotNull
@@ -33,8 +38,8 @@ public class TemporaryBindingTrace extends DelegatingBindingTrace {
protected final BindingTrace trace;
protected TemporaryBindingTrace(@NotNull BindingTrace trace, String debugName) {
super(trace.getBindingContext(), debugName, true);
protected TemporaryBindingTrace(@NotNull BindingTrace trace, String debugName, BindingTraceFilter filter) {
super(trace.getBindingContext(), debugName, true, filter);
this.trace = trace;
}
@@ -47,4 +52,9 @@ public class TemporaryBindingTrace extends DelegatingBindingTrace {
addOwnDataTo(trace, filter, commitDiagnostics);
clear();
}
@Override
public boolean wantsDiagnostics() {
return trace.wantsDiagnostics();
}
}
@@ -94,9 +94,11 @@ class CallCompleter(
if (calleeExpression != null && !calleeExpression.isFakeElement) calleeExpression
else resolvedCall.call.callElement
val callCheckerContext = CallCheckerContext(context, languageVersionSettings)
for (callChecker in callCheckers) {
callChecker.check(resolvedCall, reportOn, callCheckerContext)
if (context.trace.wantsDiagnostics()) {
val callCheckerContext = CallCheckerContext(context, languageVersionSettings)
for (callChecker in callCheckers) {
callChecker.check(resolvedCall, reportOn, callCheckerContext)
}
}
resolveHandleResultCallForCoroutineLambdaExpressions(context, resolvedCall)
@@ -563,7 +563,7 @@ public class CallResolver {
if (CallResolverUtilKt.isInvokeCallOnVariable(call)) return;
DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
BindingContext.EMPTY, "delta trace for caching resolve of", context.call, BindingTraceFilter.Companion.getACCEPT_ALL());
traceToResolveCall.addOwnDataTo(deltasTraceToCacheResolve);
context.resolutionResultsCache.record(call, results, context, tracing, deltasTraceToCacheResolve);
@@ -37,7 +37,7 @@ class MutableDiagnosticsWithSuppression @JvmOverloads constructor(
CachedValueProvider.Result(DiagnosticsWithSuppression(bindingContext, allDiagnostics), modificationTracker)
})
private fun readonlyView() = cache.value!!
private fun readonlyView(): DiagnosticsWithSuppression = cache.value!!
override val modificationTracker = CompositeModificationTracker(delegateDiagnostics.modificationTracker)
@@ -46,7 +46,9 @@ class MutableDiagnosticsWithSuppression @JvmOverloads constructor(
override fun noSuppression() = readonlyView().noSuppression()
//essential that this list is readonly
fun getOwnDiagnostics(): List<Diagnostic> = diagnosticList
fun getOwnDiagnostics(): List<Diagnostic> {
return diagnosticList
}
fun report(diagnostic: Diagnostic) {
diagnosticList.add(diagnostic)
@@ -56,7 +56,7 @@ class FileScopeFactory(
fun createScopesForFile(file: KtFile, existingImports: ImportingScope? = null): FileScopes {
val debugName = "LazyFileScope for file " + file.name
val tempTrace = TemporaryBindingTrace.create(bindingTrace, "Transient trace for default imports lazy resolve")
val tempTrace = TemporaryBindingTrace.create(bindingTrace, "Transient trace for default imports lazy resolve", false)
infix fun <T> Collection<T>.concat(other: Collection<T>?) =
if (other == null || other.isEmpty()) this else this + other
@@ -81,5 +81,7 @@ class LockBasedLazyResolveStorageManager(private val storageManager: StorageMana
override fun report(diagnostic: Diagnostic) {
storageManager.compute { trace.report(diagnostic) }
}
override fun wantsDiagnostics() = trace.wantsDiagnostics()
}
}
@@ -609,9 +609,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
trace.record(RESOLVED_CALL, call, resolvedCall);
trace.record(CALL, expression, call);
CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageVersionSettings);
for (CallChecker checker : components.callCheckers) {
checker.check(resolvedCall, expression, callCheckerContext);
if (context.trace.wantsDiagnostics()) {
CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageVersionSettings);
for (CallChecker checker : components.callCheckers) {
checker.check(resolvedCall, expression, callCheckerContext);
}
}
}
@@ -910,7 +912,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (KtTokens.AUGMENTED_ASSIGNMENTS.contains(operationType)
|| operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) {
ResolvedCall<?> resolvedCall = ignoreReportsTrace.get(INDEXED_LVALUE_SET, expression);
if (resolvedCall != null) {
if (resolvedCall != null && trace.wantsDiagnostics()) {
// Call must be validated with the actual, not temporary trace in order to report operator diagnostic
// Only unary assignment expressions (++, --) and +=/... must be checked, normal assignments have the proper trace
CallCheckerContext callCheckerContext = new CallCheckerContext(context, trace, components.languageVersionSettings);
@@ -979,9 +981,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
);
resolvedCall.markCallAsCompleted();
CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageVersionSettings);
for (CallChecker checker : components.callCheckers) {
checker.check(resolvedCall, expression, callCheckerContext);
if (context.trace.wantsDiagnostics()) {
CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageVersionSettings);
for (CallChecker checker : components.callCheckers) {
checker.check(resolvedCall, expression, callCheckerContext);
}
}
}
@@ -99,7 +99,8 @@ abstract class LightClassDataProvider<T : WithFileStubAndExtraDiagnostics>(
context.bindingContext,
files.toMutableList(),
CompilerConfiguration.EMPTY,
generateClassFilter
generateClassFilter,
wantsDiagnostics = false
)
state.beforeCompile()
@@ -196,6 +196,11 @@ public class KotlinTestUtils {
throw new IllegalStateException("Unresolved: " + diagnostic.getPsiElement().getText());
}
}
@Override
public boolean wantsDiagnostics() {
return false;
}
};
public static BindingTrace DUMMY_EXCEPTION_ON_ERROR_TRACE = new BindingTrace() {
@@ -276,6 +281,11 @@ public class KotlinTestUtils {
throw new IllegalStateException(DefaultErrorMessages.render(diagnostic));
}
}
@Override
public boolean wantsDiagnostics() {
return true;
}
};
// We suspect sequences of eight consecutive hexadecimal digits to be a package part hash code
@@ -16,8 +16,21 @@
package org.jetbrains.kotlin.resolve.lazy
enum class BodyResolveMode {
FULL,
PARTIAL,
PARTIAL_FOR_COMPLETION
import org.jetbrains.kotlin.resolve.BindingTraceFilter
open class BodyResolveMode {
open val bindingTraceFilter: BindingTraceFilter = BindingTraceFilter.ACCEPT_ALL
companion object {
@JvmField val FULL = BodyResolveMode()
@JvmField val PARTIAL = object : BodyResolveMode() {
override val bindingTraceFilter: BindingTraceFilter
get() = BindingTraceFilter.NO_DIAGNOSTICS
}
@JvmField val PARTIAL_WITH_DIAGNOSTICS = BodyResolveMode()
@JvmField val PARTIAL_FOR_COMPLETION = BodyResolveMode()
}
}
@@ -83,10 +83,11 @@ class ResolveElementCache(
},
false)
private class CachedPartialResolve(val bindingContext: BindingContext, file: KtFile) {
private class CachedPartialResolve(val bindingContext: BindingContext, file: KtFile, val filter: BindingTraceFilter) {
private val modificationStamp: Long? = modificationStamp(file)
fun isUpToDate(file: KtFile) = modificationStamp == modificationStamp(file)
fun isUpToDate(file: KtFile, newFilter: BindingTraceFilter) =
modificationStamp == modificationStamp(file) && filter.includesEverythingIn(newFilter)
private fun modificationStamp(file: KtFile): Long? {
return if (!file.isPhysical) // for non-physical file we don't get MODIFICATION_COUNT increased and must reset data on any modification of the file
@@ -117,7 +118,7 @@ class ResolveElementCache(
= getElementsAdditionalResolve(function, null, BodyResolveMode.FULL)
fun resolvePrimaryConstructorParametersDefaultValues(ktClass: KtClass): BindingContext {
return constructorAdditionalResolve(resolveSession, ktClass, ktClass.getContainingKtFile()).bindingContext
return constructorAdditionalResolve(resolveSession, ktClass, ktClass.getContainingKtFile(), BindingTraceFilter.NO_DIAGNOSTICS).bindingContext
}
@Deprecated("Use getElementsAdditionalResolve")
@@ -149,7 +150,16 @@ class ResolveElementCache(
return bindingContext
}
BodyResolveMode.PARTIAL -> {
BodyResolveMode.PARTIAL_FOR_COMPLETION -> {
if (resolveElement !is KtDeclaration) {
return getElementsAdditionalResolve(resolveElement, null, BodyResolveMode.FULL)
}
// not cached
return performElementAdditionalResolve(resolveElement, contextElements, bodyResolveMode).first
}
else -> {
if (resolveElement !is KtDeclaration) {
return getElementsAdditionalResolve(resolveElement, null, BodyResolveMode.FULL)
}
@@ -158,18 +168,18 @@ class ResolveElementCache(
val statementsToResolve = contextElements!!.map { PartialBodyResolveFilter.findStatementToResolve(it, resolveElement) }.distinct()
val partialResolveMap = partialBodyResolveCache.value
val cachedResults = statementsToResolve.map { partialResolveMap[it ?: resolveElement] }
if (cachedResults.all { it != null && it.isUpToDate(file) }) { // partial resolve is already cached for these statements
if (cachedResults.all { it != null && it.isUpToDate(file, bodyResolveMode.bindingTraceFilter) }) { // partial resolve is already cached for these statements
return CompositeBindingContext.create(cachedResults.map { it!!.bindingContext }.distinct())
}
val (bindingContext, statementFilter) = performElementAdditionalResolve(resolveElement, contextElements, BodyResolveMode.PARTIAL)
val (bindingContext, statementFilter) = performElementAdditionalResolve(resolveElement, contextElements, bodyResolveMode)
if (statementFilter == StatementFilter.NONE) { // partial resolve is not supported for the given declaration - full resolve performed instead
fullResolveMap[resolveElement] = CachedFullResolve(bindingContext, resolveElement)
return bindingContext
}
val resolveToCache = CachedPartialResolve(bindingContext, file)
val resolveToCache = CachedPartialResolve(bindingContext, file, bodyResolveMode.bindingTraceFilter)
for (statement in (statementFilter as PartialBodyResolveFilter).allStatementsToResolve) {
if (!partialResolveMap.containsKey(statement) && bindingContext[BindingContext.PROCESSED, statement] == true) {
@@ -182,15 +192,6 @@ class ResolveElementCache(
return bindingContext
}
BodyResolveMode.PARTIAL_FOR_COMPLETION -> {
if (resolveElement !is KtDeclaration) {
return getElementsAdditionalResolve(resolveElement, null, BodyResolveMode.FULL)
}
// not cached
return performElementAdditionalResolve(resolveElement, contextElements, bodyResolveMode).first
}
}
}
@@ -311,17 +312,17 @@ class ResolveElementCache(
}
val trace: BindingTrace = when (resolveElement) {
is KtNamedFunction -> functionAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter())
is KtNamedFunction -> functionAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter(), bodyResolveMode.bindingTraceFilter)
is KtAnonymousInitializer -> initializerAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter())
is KtAnonymousInitializer -> initializerAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter(), bodyResolveMode.bindingTraceFilter)
is KtSecondaryConstructor -> secondaryConstructorAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter())
is KtSecondaryConstructor -> secondaryConstructorAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter(), bodyResolveMode.bindingTraceFilter)
is KtProperty -> propertyAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter())
is KtProperty -> propertyAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter(), bodyResolveMode.bindingTraceFilter)
is KtSuperTypeList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as KtClassOrObject, file)
is KtSuperTypeList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as KtClassOrObject, file, bodyResolveMode.bindingTraceFilter)
is KtInitializerList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as KtEnumEntry, file)
is KtInitializerList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as KtEnumEntry, file, bodyResolveMode.bindingTraceFilter)
is KtImportList -> {
val resolver = resolveSession.fileScopeProvider.getImportResolver(resolveElement.getContainingKtFile())
@@ -341,9 +342,9 @@ class ResolveElementCache(
is KtAnnotationEntry -> annotationAdditionalResolve(resolveSession, resolveElement)
is KtClass -> constructorAdditionalResolve(resolveSession, resolveElement, file)
is KtClass -> constructorAdditionalResolve(resolveSession, resolveElement, file, bodyResolveMode.bindingTraceFilter)
is KtTypeAlias -> typealiasAdditionalResolve(resolveSession, resolveElement)
is KtTypeAlias -> typealiasAdditionalResolve(resolveSession, resolveElement, bodyResolveMode.bindingTraceFilter)
is KtTypeParameter -> typeParameterAdditionalResolve(resolveSession, resolveElement)
@@ -353,7 +354,7 @@ class ResolveElementCache(
else -> {
if (resolveElement.getParentOfType<KtPackageDirective>(true) != null) {
packageRefAdditionalResolve(resolveSession, resolveElement)
packageRefAdditionalResolve(resolveSession, resolveElement, bodyResolveMode.bindingTraceFilter)
}
else {
error("Invalid type of the topmost parent: $resolveElement\n${resolveElement.getElementTextWithContext()}")
@@ -368,8 +369,9 @@ class ResolveElementCache(
return Pair(trace.bindingContext, statementFilterUsed)
}
private fun packageRefAdditionalResolve(resolveSession: ResolveSession, ktElement: KtElement): BindingTrace {
val trace = createDelegatingTrace(ktElement)
private fun packageRefAdditionalResolve(resolveSession: ResolveSession, ktElement: KtElement,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(ktElement, bindingTraceFilter)
if (ktElement is KtSimpleNameExpression) {
val header = ktElement.getParentOfType<KtPackageDirective>(true)!!
@@ -398,7 +400,7 @@ class ResolveElementCache(
}
private fun codeFragmentAdditionalResolve(codeFragment: KtCodeFragment, bodyResolveMode: BodyResolveMode): BindingTrace {
val trace = createDelegatingTrace(codeFragment)
val trace = createDelegatingTrace(codeFragment, bodyResolveMode.bindingTraceFilter)
val contextResolveMode = if (bodyResolveMode == BodyResolveMode.PARTIAL)
BodyResolveMode.PARTIAL_FOR_COMPLETION
@@ -456,8 +458,9 @@ class ResolveElementCache(
}
private fun delegationSpecifierAdditionalResolve(resolveSession: ResolveSession, ktElement: KtElement,
classOrObject: KtClassOrObject, file: KtFile): BindingTrace {
val trace = createDelegatingTrace(ktElement)
classOrObject: KtClassOrObject, file: KtFile,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(ktElement, bindingTraceFilter)
val descriptor = resolveSession.resolveToDescriptor(classOrObject) as LazyClassDescriptor
// Activate resolving of supertypes
@@ -475,8 +478,10 @@ class ResolveElementCache(
}
private fun propertyAdditionalResolve(resolveSession: ResolveSession, property: KtProperty,
file: KtFile, statementFilter: StatementFilter): BindingTrace {
val trace = createDelegatingTrace(property)
file: KtFile,
statementFilter: StatementFilter,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(property, bindingTraceFilter)
val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter)
val descriptor = resolveSession.resolveToDescriptor(property) as PropertyDescriptor
@@ -501,8 +506,9 @@ class ResolveElementCache(
}
private fun functionAdditionalResolve(resolveSession: ResolveSession, namedFunction: KtNamedFunction, file: KtFile,
statementFilter: StatementFilter): BindingTrace {
val trace = createDelegatingTrace(namedFunction)
statementFilter: StatementFilter,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(namedFunction, bindingTraceFilter)
val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(namedFunction)
val functionDescriptor = resolveSession.resolveToDescriptor(namedFunction) as FunctionDescriptor
@@ -517,8 +523,9 @@ class ResolveElementCache(
}
private fun secondaryConstructorAdditionalResolve(resolveSession: ResolveSession, constructor: KtSecondaryConstructor,
file: KtFile, statementFilter: StatementFilter): BindingTrace {
val trace = createDelegatingTrace(constructor)
file: KtFile, statementFilter: StatementFilter,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(constructor, bindingTraceFilter)
val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(constructor)
val constructorDescriptor = resolveSession.resolveToDescriptor(constructor) as ClassConstructorDescriptor
@@ -532,8 +539,8 @@ class ResolveElementCache(
return trace
}
private fun constructorAdditionalResolve(resolveSession: ResolveSession, klass: KtClass, file: KtFile): BindingTrace {
val trace = createDelegatingTrace(klass)
private fun constructorAdditionalResolve(resolveSession: ResolveSession, klass: KtClass, file: KtFile, filter : BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(klass, filter)
val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(klass)
val classDescriptor = resolveSession.resolveToDescriptor(klass) as ClassDescriptor
@@ -547,8 +554,9 @@ class ResolveElementCache(
return trace
}
private fun typealiasAdditionalResolve(resolveSession: ResolveSession, typeAlias: KtTypeAlias): BindingTrace {
val trace = createDelegatingTrace(typeAlias)
private fun typealiasAdditionalResolve(resolveSession: ResolveSession, typeAlias: KtTypeAlias,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(typeAlias, bindingTraceFilter)
val typeAliasDescriptor = resolveSession.resolveToDescriptor(typeAlias)
ForceResolveUtil.forceResolveAllContents(typeAliasDescriptor)
forceResolveAnnotationsInside(typeAlias)
@@ -556,8 +564,9 @@ class ResolveElementCache(
}
private fun initializerAdditionalResolve(resolveSession: ResolveSession, anonymousInitializer: KtAnonymousInitializer,
file: KtFile, statementFilter: StatementFilter): BindingTrace {
val trace = createDelegatingTrace(anonymousInitializer)
file: KtFile, statementFilter: StatementFilter,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(anonymousInitializer, bindingTraceFilter)
val classOrObjectDescriptor = resolveSession.resolveToDescriptor(anonymousInitializer.containingDeclaration) as LazyClassDescriptor
@@ -595,9 +604,9 @@ class ResolveElementCache(
}
// All additional resolve should be done to separate trace
private fun createDelegatingTrace(resolveElement: KtElement): BindingTrace {
private fun createDelegatingTrace(resolveElement: KtElement, filter: BindingTraceFilter): BindingTrace {
return resolveSession.storageManager.createSafeTrace(
DelegatingBindingTrace(resolveSession.bindingContext, "trace to resolve element", resolveElement))
DelegatingBindingTrace(resolveSession.bindingContext, "trace to resolve element", resolveElement, filter))
}
private class BodyResolveContextForLazy(
@@ -70,7 +70,7 @@ abstract class AbstractKtReference<T : KtElement>(element: T)
override fun isSoft(): Boolean = false
private fun resolveToPsiElements(): Collection<PsiElement> {
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
return resolveToPsiElements(bindingContext, getTargetDescriptors(bindingContext))
}
@@ -76,7 +76,7 @@ abstract class KotlinIntentionActionFactoryWithDelegate<E : KtElement, D : Any>
if (!diagnosticElement.isValid || !element.isValid) return@factory null
val currentDiagnostic =
element.analyze(BodyResolveMode.PARTIAL)
element.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
.diagnostics
.forElement(diagnosticElement)
.firstOrNull { DefaultErrorMessages.render(it) == diagnosticMessage } ?: return@factory null
@@ -111,7 +111,7 @@ class CreateTypeParameterFromUsageFix(
}
}
is KtCallElement -> {
if (it.analyze(BodyResolveMode.PARTIAL).diagnostics.forElement(it.calleeExpression!!).any {
if (it.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS).diagnostics.forElement(it.calleeExpression!!).any {
it.factory in Errors.TYPE_INFERENCE_ERRORS
}) {
callsToExplicateArguments += it
@@ -303,7 +303,7 @@ class KotlinInlineValHandler : InlineActionHandler() {
resolutionFacade: ResolutionFacade
): Boolean {
val functionLiteral = lambdaExpression.functionLiteral
val context = resolutionFacade.analyze(lambdaExpression, BodyResolveMode.PARTIAL)
val context = resolutionFacade.analyze(lambdaExpression, BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
return context.diagnostics.any { diagnostic ->
val factory = diagnostic.factory
val element = diagnostic.psiElement
@@ -784,7 +784,7 @@ fun getQualifiedTypeArgumentList(initializer: KtExpression): KtTypeArgumentList?
}
fun addTypeArgumentsIfNeeded(expression: KtExpression, typeArgumentList: KtTypeArgumentList) {
val context = expression.analyze(BodyResolveMode.PARTIAL)
val context = expression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
val call = expression.getCallWithAssert(context)
val callElement = call.callElement as? KtCallExpression ?: return
if (call.typeArgumentList != null) return