Skip visibility check when resolving class in debug mode

#KT-11326 Fixed
This commit is contained in:
Natalia Ukhorskaya
2016-03-14 16:01:10 +03:00
parent 0fd8bec2ef
commit 26c153639a
10 changed files with 80 additions and 27 deletions
@@ -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)
@@ -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);
@@ -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)
@@ -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)
}
}
@@ -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>>()
+11
View File
@@ -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
@@ -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");