Skip visibility check when resolving class in debug mode
#KT-11326 Fixed
This commit is contained in:
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.incremental.KotlinLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||
import org.jetbrains.kotlin.resolve.calls.CallExpressionElement
|
||||
import org.jetbrains.kotlin.resolve.calls.unrollToLeftMostQualifiedExpression
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
@@ -64,12 +65,14 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
fun resolveDescriptorForType(
|
||||
userType: KtUserType,
|
||||
scope: LexicalScope,
|
||||
trace: BindingTrace
|
||||
trace: BindingTrace,
|
||||
isDebuggerContext: Boolean
|
||||
): TypeQualifierResolutionResult {
|
||||
val ownerDescriptor = if (!isDebuggerContext) scope.ownerDescriptor else null
|
||||
if (userType.qualifier == null && !userType.startWithPackage) { // optimization for non-qualified types
|
||||
val descriptor = userType.referenceExpression?.let {
|
||||
val classifier = scope.findClassifier(it.getReferencedNameAsName(), KotlinLookupLocation(it))
|
||||
storeResult(trace, it, classifier, scope.ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = false)
|
||||
storeResult(trace, it, classifier, ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = false)
|
||||
classifier
|
||||
}
|
||||
|
||||
@@ -80,7 +83,7 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
val (qualifierPartList, hasError) = userType.asQualifierPartList()
|
||||
if (hasError) {
|
||||
val descriptor = resolveToPackageOrClass(
|
||||
qualifierPartList, module, trace, scope.ownerDescriptor, scope, position = QualifierPosition.TYPE
|
||||
qualifierPartList, module, trace, ownerDescriptor, scope, position = QualifierPosition.TYPE
|
||||
) as? ClassifierDescriptor
|
||||
return TypeQualifierResolutionResult(qualifierPartList, descriptor)
|
||||
}
|
||||
@@ -90,7 +93,7 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
|
||||
val qualifier = resolveToPackageOrClass(
|
||||
qualifierPartList.subList(0, qualifierPartList.size - 1), module,
|
||||
trace, scope.ownerDescriptor, scope.check { !userType.startWithPackage }, position = QualifierPosition.TYPE
|
||||
trace, ownerDescriptor, scope.check { !userType.startWithPackage }, position = QualifierPosition.TYPE
|
||||
) ?: return TypeQualifierResolutionResult(qualifierPartList, null)
|
||||
|
||||
val lastPart = qualifierPartList.last()
|
||||
@@ -99,7 +102,7 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
is ClassDescriptor -> qualifier.unsubstitutedInnerClassesScope.getContributedClassifier(lastPart.name, lastPart.location)
|
||||
else -> null
|
||||
}
|
||||
storeResult(trace, lastPart.expression, classifier, scope.ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = false)
|
||||
storeResult(trace, lastPart.expression, classifier, ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = false)
|
||||
return TypeQualifierResolutionResult(qualifierPartList, classifier)
|
||||
}
|
||||
|
||||
@@ -141,11 +144,12 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
val path = importedReference.asQualifierPartList(trace)
|
||||
val lastPart = path.lastOrNull() ?: return null
|
||||
val packageFragmentForCheck =
|
||||
if (packageFragmentForVisibilityCheck is DeclarationDescriptorWithSource && packageFragmentForVisibilityCheck.source == SourceElement.NO_SOURCE) {
|
||||
PackageFragmentWithCustomSource(packageFragmentForVisibilityCheck, KotlinSourceElement(importDirective.getContainingKtFile()))
|
||||
}
|
||||
else {
|
||||
packageFragmentForVisibilityCheck
|
||||
when {
|
||||
importDirective.suppressDiagnosticsInDebugMode() -> null
|
||||
packageFragmentForVisibilityCheck is DeclarationDescriptorWithSource && packageFragmentForVisibilityCheck.source == SourceElement.NO_SOURCE -> {
|
||||
PackageFragmentWithCustomSource(packageFragmentForVisibilityCheck, KotlinSourceElement(importDirective.getContainingKtFile()))
|
||||
}
|
||||
else -> packageFragmentForVisibilityCheck
|
||||
}
|
||||
|
||||
if (importDirective.isAllUnder) {
|
||||
|
||||
@@ -25,9 +25,10 @@ public class TypeResolutionContext {
|
||||
public final boolean checkBounds;
|
||||
public final boolean allowBareTypes;
|
||||
public final boolean forceResolveLazyTypes;
|
||||
public final boolean isDebuggerContext;
|
||||
|
||||
public TypeResolutionContext(@NotNull LexicalScope scope, @NotNull BindingTrace trace, boolean checkBounds, boolean allowBareTypes) {
|
||||
this(scope, trace, checkBounds, allowBareTypes, allowBareTypes);
|
||||
public TypeResolutionContext(@NotNull LexicalScope scope, @NotNull BindingTrace trace, boolean checkBounds, boolean allowBareTypes, boolean isDebuggerContext) {
|
||||
this(scope, trace, checkBounds, allowBareTypes, allowBareTypes, isDebuggerContext);
|
||||
}
|
||||
|
||||
private TypeResolutionContext(
|
||||
@@ -35,16 +36,18 @@ public class TypeResolutionContext {
|
||||
@NotNull BindingTrace trace,
|
||||
boolean checkBounds,
|
||||
boolean allowBareTypes,
|
||||
boolean forceResolveLazyTypes
|
||||
boolean forceResolveLazyTypes,
|
||||
boolean isDebuggerContext
|
||||
) {
|
||||
this.scope = scope;
|
||||
this.trace = trace;
|
||||
this.checkBounds = checkBounds;
|
||||
this.allowBareTypes = allowBareTypes;
|
||||
this.forceResolveLazyTypes = forceResolveLazyTypes;
|
||||
this.isDebuggerContext = isDebuggerContext;
|
||||
}
|
||||
|
||||
public TypeResolutionContext noBareTypes() {
|
||||
return new TypeResolutionContext(scope, trace, checkBounds, false, forceResolveLazyTypes);
|
||||
return new TypeResolutionContext(scope, trace, checkBounds, false, forceResolveLazyTypes, isDebuggerContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.debugTypeInfo
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||
import org.jetbrains.kotlin.psi.debugText.getDebugText
|
||||
import org.jetbrains.kotlin.resolve.PossiblyBareType.type
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.recordScope
|
||||
@@ -65,7 +66,7 @@ class TypeResolver(
|
||||
|
||||
fun resolveType(scope: LexicalScope, typeReference: KtTypeReference, trace: BindingTrace, checkBounds: Boolean): KotlinType {
|
||||
// bare types are not allowed
|
||||
return resolveType(TypeResolutionContext(scope, trace, checkBounds, false), typeReference)
|
||||
return resolveType(TypeResolutionContext(scope, trace, checkBounds, false, typeReference.suppressDiagnosticsInDebugMode()), typeReference)
|
||||
}
|
||||
|
||||
private fun resolveType(c: TypeResolutionContext, typeReference: KtTypeReference): KotlinType {
|
||||
@@ -157,7 +158,7 @@ class TypeResolver(
|
||||
var result: PossiblyBareType? = null
|
||||
typeElement?.accept(object : KtVisitorVoid() {
|
||||
override fun visitUserType(type: KtUserType) {
|
||||
val qualifierResolutionResults = resolveDescriptorForType(c.scope, type, c.trace)
|
||||
val qualifierResolutionResults = resolveDescriptorForType(c.scope, type, c.trace, c.isDebuggerContext)
|
||||
val (qualifierParts, classifierDescriptor) = qualifierResolutionResults
|
||||
|
||||
if (classifierDescriptor == null) {
|
||||
@@ -564,11 +565,11 @@ class TypeResolver(
|
||||
}
|
||||
|
||||
fun resolveClass(
|
||||
scope: LexicalScope, userType: KtUserType, trace: BindingTrace
|
||||
): ClassifierDescriptor? = resolveDescriptorForType(scope, userType, trace).classifierDescriptor
|
||||
scope: LexicalScope, userType: KtUserType, trace: BindingTrace, isDebuggerContext: Boolean
|
||||
): ClassifierDescriptor? = resolveDescriptorForType(scope, userType, trace, isDebuggerContext).classifierDescriptor
|
||||
|
||||
fun resolveDescriptorForType(
|
||||
scope: LexicalScope, userType: KtUserType, trace: BindingTrace
|
||||
scope: LexicalScope, userType: KtUserType, trace: BindingTrace, isDebuggerContext: Boolean
|
||||
): QualifiedExpressionResolver.TypeQualifierResolutionResult {
|
||||
if (userType.qualifier != null) { // we must resolve all type references in arguments of qualifier type
|
||||
for (typeArgument in userType.qualifier!!.typeArguments) {
|
||||
@@ -578,7 +579,7 @@ class TypeResolver(
|
||||
}
|
||||
}
|
||||
|
||||
val result = qualifiedExpressionResolver.resolveDescriptorForType(userType, scope, trace)
|
||||
val result = qualifiedExpressionResolver.resolveDescriptorForType(userType, scope, trace, isDebuggerContext)
|
||||
if (result.classifierDescriptor != null) {
|
||||
PlatformTypesMappedToKotlinChecker.reportPlatformClassMappedToKotlin(
|
||||
moduleDescriptor, trace, userType, result.classifierDescriptor)
|
||||
|
||||
+3
-4
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.types.expressions;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
@@ -251,7 +250,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||
|
||||
boolean allowBareTypes = BARE_TYPES_ALLOWED.contains(operationType);
|
||||
TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, allowBareTypes);
|
||||
TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, allowBareTypes, context.isDebuggerContext);
|
||||
PossiblyBareType possiblyBareTarget = components.typeResolver.resolvePossiblyBareType(typeResolutionContext, right);
|
||||
|
||||
KotlinTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
|
||||
@@ -432,7 +431,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
KtUserType userType = (KtUserType) typeElement;
|
||||
// This may be just a superclass name even if the superclass is generic
|
||||
if (userType.getTypeArguments().isEmpty()) {
|
||||
classifierCandidate = components.typeResolver.resolveClass(context.scope, userType, context.trace);
|
||||
classifierCandidate = components.typeResolver.resolveClass(context.scope, userType, context.trace, context.isDebuggerContext);
|
||||
}
|
||||
else {
|
||||
supertype = components.typeResolver.resolveType(context.scope, superTypeQualifier, context.trace, true);
|
||||
@@ -612,7 +611,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
TypeResolutionContext context =
|
||||
new TypeResolutionContext(c.scope, c.trace, /* checkBounds = */ false, /* allowBareTypes = */ true);
|
||||
new TypeResolutionContext(c.scope, c.trace, /* checkBounds = */ false, /* allowBareTypes = */ true, /* isDebuggerContext */ false);
|
||||
PossiblyBareType possiblyBareType =
|
||||
components.typeResolver.resolvePossiblyBareType(context, typeReference);
|
||||
|
||||
|
||||
+1
-1
@@ -346,7 +346,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
||||
typeReferenceAfterIs: KtTypeReference,
|
||||
subjectDataFlowValue: DataFlowValue
|
||||
): ConditionalDataFlowInfo {
|
||||
val typeResolutionContext = TypeResolutionContext(context.scope, context.trace, true, /*allowBareTypes=*/ true)
|
||||
val typeResolutionContext = TypeResolutionContext(context.scope, context.trace, true, /*allowBareTypes=*/ true, context.isDebuggerContext)
|
||||
val possiblyBareTarget = components.typeResolver.resolvePossiblyBareType(typeResolutionContext, typeReferenceAfterIs)
|
||||
val targetType = TypeReconstructionUtil.reconstructBareType(typeReferenceAfterIs, possiblyBareTarget, subjectType, context.trace, components.builtIns)
|
||||
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
||||
import org.jetbrains.kotlin.idea.project.ResolveElementCache
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
@@ -67,7 +68,7 @@ class CodeFragmentAnalyzer(
|
||||
}
|
||||
|
||||
is KtTypeReference -> {
|
||||
val context = TypeResolutionContext(scopeForContextElement, trace, true, true).noBareTypes()
|
||||
val context = TypeResolutionContext(scopeForContextElement, trace, true, true, codeFragment.suppressDiagnosticsInDebugMode()).noBareTypes()
|
||||
typeResolver.resolvePossiblyBareType(context, codeFragmentElement)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -183,7 +183,7 @@ object ReplaceWithAnnotationAnalyzer {
|
||||
|
||||
val typeResolver = resolutionFacade.getFrontendService(TypeResolver::class.java)
|
||||
val bindingTrace = BindingTraceContext()
|
||||
typeResolver.resolvePossiblyBareType(TypeResolutionContext(scope, bindingTrace, false, true), typeReference)
|
||||
typeResolver.resolvePossiblyBareType(TypeResolutionContext(scope, bindingTrace, false, true, false), typeReference)
|
||||
|
||||
val typesToQualify = ArrayList<Pair<KtNameReferenceExpression, FqName>>()
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
LineBreakpoint created at privateClass.kt:5
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! privateClass.PrivateClassKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
privateClass.kt:5
|
||||
Compile bytecode for A.PrivateClass()
|
||||
Compile bytecode for A.PrivateClass().prop
|
||||
Compile bytecode for A().PrivateInnerClass()
|
||||
Compile bytecode for A().PrivateInnerClass().prop
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
@@ -0,0 +1,28 @@
|
||||
package privateClass
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
args.size
|
||||
}
|
||||
|
||||
class A {
|
||||
private class PrivateClass {
|
||||
private val prop = 1
|
||||
}
|
||||
|
||||
private inner class PrivateInnerClass {
|
||||
private val prop = 1
|
||||
}
|
||||
}
|
||||
|
||||
// EXPRESSION: A.PrivateClass()
|
||||
// RESULT: instance of privateClass.A$PrivateClass(id=ID): LprivateClass/A$PrivateClass;
|
||||
|
||||
// EXPRESSION: A.PrivateClass().prop
|
||||
// RESULT: 1: I
|
||||
|
||||
// EXPRESSION: A().PrivateInnerClass()
|
||||
// RESULT: instance of privateClass.A$PrivateInnerClass(id=ID): LprivateClass/A$PrivateInnerClass;
|
||||
|
||||
// EXPRESSION: A().PrivateInnerClass().prop
|
||||
// RESULT: 1: I
|
||||
+6
@@ -271,6 +271,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
doSingleBreakpointTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateClass.kt")
|
||||
public void testPrivateClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/privateClass.kt");
|
||||
doSingleBreakpointTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateMember.kt")
|
||||
public void testPrivateMember() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/privateMember.kt");
|
||||
|
||||
Reference in New Issue
Block a user