Properly resolve values in 1st qualifier part (see implicitReceiverProperty test).

Look into QUALIFIER for left-most "unrolled" qualified expression
    in CallExpressionResolver#getQualifiedExpressionTypeInfo.
Drop some unused functions.
This commit is contained in:
Dmitry Petrov
2015-11-10 14:37:51 +03:00
parent 49570ba1ea
commit b532fa2bbf
13 changed files with 228 additions and 113 deletions
@@ -20,26 +20,24 @@ import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.CallExpressionElement
import org.jetbrains.kotlin.resolve.calls.unrollToLeftMostQualifiedExpression
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.createClassifierQualifier
import org.jetbrains.kotlin.resolve.scopes.utils.containsFunctionOrVariable
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.check
import java.util.*
public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator) {
@@ -52,7 +50,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
val packageNames = packageDirective.packageNames
for ((index, nameExpression) in packageNames.withIndex()) {
storeResult(trace, nameExpression, module.getPackage(packageDirective.getFqName(nameExpression)),
shouldBeVisibleFrom = null, inImport = false, isQualifier = index != packageNames.lastIndex)
shouldBeVisibleFrom = null, position = QualifierPosition.PACKAGE_HEADER, isQualifier = index != packageNames.lastIndex)
}
}
@@ -72,7 +70,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
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, inImport = false, isQualifier = false)
storeResult(trace, it, classifier, scope.ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = false)
classifier
}
@@ -102,8 +100,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
is ClassDescriptor -> qualifier.unsubstitutedInnerClassesScope.getContributedClassifier(lastPart.name, lastPart.location)
else -> null
}
storeResult(trace, lastPart.expression, classifier, scope.ownerDescriptor, inImport = false, isQualifier = false)
storeResult(trace, lastPart.expression, classifier, scope.ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = false)
return TypeQualifierResolutionResult(qualifierPartList, classifier)
}
@@ -181,14 +178,14 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
val candidates = collectCandidateDescriptors(lastPart, packageOrClassDescriptor)
if (candidates.isNotEmpty()) {
storeResult(trace, lastPart.expression, candidates, packageFragmentForVisibilityCheck, inImport = true, isQualifier = false)
storeResult(trace, lastPart.expression, candidates, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT, isQualifier = false)
}
else {
tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart)
return null
}
val importedDescriptors = candidates.filter { isVisible(it, packageFragmentForVisibilityCheck, inImport = true) }.
val importedDescriptors = candidates.filter { isVisible(it, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT) }.
check { it.isNotEmpty() } ?: candidates
return SingleImportScope(aliasName, importedDescriptors)
@@ -258,7 +255,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor")
}
storeResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom = null, inImport = true, isQualifier = false)
storeResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom = null, position = QualifierPosition.IMPORT, isQualifier = false)
}
private fun KtExpression.asQualifierPartList(trace: BindingTrace): List<QualifierPart> {
@@ -296,7 +293,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
}
private enum class QualifierPosition {
IMPORT, TYPE, EXPRESSION
PACKAGE_HEADER, IMPORT, TYPE, EXPRESSION
}
private fun resolveToPackageOrClass(
@@ -323,21 +320,20 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
trace: BindingTrace,
shouldBeVisibleFrom: DeclarationDescriptor?,
scopeForFirstPart: LexicalScope?,
position: QualifierPosition
position: QualifierPosition,
isValue: ((KtSimpleNameExpression) -> Boolean)? = null
): Pair<DeclarationDescriptor?, Int> {
if (path.isEmpty()) {
return Pair(moduleDescriptor.getPackage(FqName.ROOT), 0)
}
val inImport = position == QualifierPosition.IMPORT
val firstPart = path.first()
if (position == QualifierPosition.EXPRESSION) {
// In expression position, value wins against classifier (and package).
// If we see a function or variable (possibly ambiguous),
// tell resolver we have no qualifier and let it perform the context-dependent resolution.
if (scopeForFirstPart != null && scopeForFirstPart.containsFunctionOrVariable(firstPart.name, firstPart.location)) {
if (scopeForFirstPart != null && isValue != null && isValue(firstPart.expression)) {
return Pair(null, 0)
}
}
@@ -347,14 +343,14 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
}
if (classifierDescriptor != null) {
storeResult(trace, firstPart.expression, classifierDescriptor, shouldBeVisibleFrom, inImport)
storeResult(trace, firstPart.expression, classifierDescriptor, shouldBeVisibleFrom, position)
}
val (prefixDescriptor, nextIndexAfterPrefix) =
if (classifierDescriptor != null)
Pair(classifierDescriptor, 1)
else
moduleDescriptor.quickResolveToPackage(path, trace, inImport)
moduleDescriptor.quickResolveToPackage(path, trace, position)
var currentDescriptor: DeclarationDescriptor? = prefixDescriptor
for (qualifierPartIndex in nextIndexAfterPrefix .. path.size - 1) {
@@ -383,7 +379,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
// If we are in expression, this name can denote a value (not a package or class).
if (!(position == QualifierPosition.EXPRESSION && nextPackageOrClassDescriptor == null)) {
storeResult(trace, qualifierPart.expression, nextPackageOrClassDescriptor, shouldBeVisibleFrom, inImport)
storeResult(trace, qualifierPart.expression, nextPackageOrClassDescriptor, shouldBeVisibleFrom, position)
}
if (nextPackageOrClassDescriptor == null) {
@@ -399,69 +395,51 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
public fun resolveQualifierInExpressionAndUnroll(
expression: KtQualifiedExpression,
context: ExpressionTypingContext
context: ExpressionTypingContext,
isValue: (KtSimpleNameExpression) -> Boolean
): List<CallExpressionElement> {
val qualifiedExpressions = unrollToLeftMostQualifiedExpression(expression)
val maxPossibleQualifierPrefix = getMaxPossibleQualifierPrefix(qualifiedExpressions)
val (packageOrClassDescriptor, nextIndexAfterPrefix) = resolveToPackageOrClassPrefix(
val nextIndexAfterPrefix = resolveToPackageOrClassPrefix(
path = maxPossibleQualifierPrefix,
moduleDescriptor = context.scope.ownerDescriptor.module,
trace = context.trace,
shouldBeVisibleFrom = context.scope.ownerDescriptor,
scopeForFirstPart = context.scope,
position = QualifierPosition.EXPRESSION
)
position = QualifierPosition.EXPRESSION,
isValue = isValue
).second
if (nextIndexAfterPrefix > 0) {
val qualifierReferenceExpression = maxPossibleQualifierPrefix[nextIndexAfterPrefix - 1].expression
val qualifier =
when (packageOrClassDescriptor) {
is PackageViewDescriptor ->
PackageQualifier(qualifierReferenceExpression, packageOrClassDescriptor)
is ClassDescriptor ->
ClassQualifier(qualifierReferenceExpression, packageOrClassDescriptor)
else ->
null
}
if (qualifier != null) {
context.trace.record(BindingContext.QUALIFIER, qualifier.expression, qualifier)
}
}
val firstExpressionAfterQualifierIndex =
if (nextIndexAfterPrefix == 0) 0 else nextIndexAfterPrefix - 1
return qualifiedExpressions.map { CallExpressionElement(it) }
}
private fun unrollToLeftMostQualifiedExpression(expression: KtQualifiedExpression): List<KtQualifiedExpression> {
val unrolled = arrayListOf<KtQualifiedExpression>()
var finger = expression
while (true) {
unrolled.add(finger)
val receiver = finger.receiverExpression
if (receiver !is KtQualifiedExpression) {
break
}
finger = receiver
}
Collections.reverse(unrolled)
return unrolled
return qualifiedExpressions
.subList(firstExpressionAfterQualifierIndex, qualifiedExpressions.size)
.map { CallExpressionElement(it) }
}
private fun getMaxPossibleQualifierPrefix(qualifiedExpressions: List<KtQualifiedExpression>) : List<QualifierPart> {
if (qualifiedExpressions.isEmpty()) return emptyList()
val first = qualifiedExpressions.first()
if (first.operationSign != KtTokens.DOT) return emptyList()
if (first !is KtDotQualifiedExpression) return emptyList()
val firstReceiver = first.receiverExpression
if (firstReceiver !is KtSimpleNameExpression) return emptyList()
// Qualifier parts are receiver name for the leftmost expression
// and selector names for all but the rightmost qualified expressions
// (since rightmost selector should denote a value in expression position,
// and thus can't be a qualifier part).
// E.g.:
// qualified expression 'a.b': qualifier parts == ['a']
// qualified expression 'a.b.c.d': qualifier parts == ['a', 'b', 'c']
val qualifierParts = arrayListOf<QualifierPart>()
qualifierParts.add(QualifierPart(firstReceiver))
for (qualifiedExpression in qualifiedExpressions.dropLast(1)) {
if (qualifiedExpression.operationSign != KtTokens.DOT) break
if (qualifiedExpression !is KtDotQualifiedExpression) break
val selector = qualifiedExpression.selectorExpression
if (selector !is KtSimpleNameExpression) break
qualifierParts.add(QualifierPart(selector))
@@ -473,7 +451,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
private fun ModuleDescriptor.quickResolveToPackage(
path: List<QualifierPart>,
trace: BindingTrace,
inImport: Boolean
position: QualifierPosition
): Pair<PackageViewDescriptor, Int> {
val possiblePackagePrefixSize = path.indexOfFirst { it.typeArguments != null }.let { if (it == -1) path.size() else it + 1 }
var fqName = path.subList(0, possiblePackagePrefixSize).fold(FqName.ROOT) { fqName, qualifierPart ->
@@ -483,7 +461,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
while (!fqName.isRoot) {
val packageDescriptor = getPackage(fqName)
if (!packageDescriptor.isEmpty()) {
recordPackageViews(path.subList(0, prefixSize), packageDescriptor, trace, inImport)
recordPackageViews(path.subList(0, prefixSize), packageDescriptor, trace, position)
return Pair(packageDescriptor, prefixSize)
}
fqName = fqName.parent()
@@ -496,10 +474,10 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
path: List<QualifierPart>,
packageView: PackageViewDescriptor,
trace: BindingTrace,
inImport: Boolean
position: QualifierPosition
) {
path.foldRight(packageView) { qualifierPart, currentView ->
storeResult(trace, qualifierPart.expression, currentView, shouldBeVisibleFrom = null, inImport = inImport)
storeResult(trace, qualifierPart.expression, currentView, shouldBeVisibleFrom = null, position = position)
val parentView = currentView.containingDeclaration
assert(parentView != null) {
"Containing Declaration must be not null for package with fqName: ${currentView.fqName}, " +
@@ -514,11 +492,11 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
referenceExpression: KtSimpleNameExpression,
descriptors: Collection<DeclarationDescriptor>,
shouldBeVisibleFrom: DeclarationDescriptor?,
inImport: Boolean,
position: QualifierPosition,
isQualifier: Boolean = true
) {
if (descriptors.size() > 1) {
val visibleDescriptors = descriptors.filter { isVisible(it, shouldBeVisibleFrom, inImport) }
val visibleDescriptors = descriptors.filter { isVisible(it, shouldBeVisibleFrom, position) }
if (visibleDescriptors.isEmpty()) {
val descriptor = descriptors.first() as DeclarationDescriptorWithVisibility
trace.report(Errors.INVISIBLE_REFERENCE.on(referenceExpression, descriptor, descriptor.visibility, descriptor))
@@ -527,11 +505,11 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, visibleDescriptors)
}
else {
storeResult(trace, referenceExpression, visibleDescriptors.single(), null, inImport, isQualifier)
storeResult(trace, referenceExpression, visibleDescriptors.single(), null, position, isQualifier)
}
}
else {
storeResult(trace, referenceExpression, descriptors.singleOrNull(), shouldBeVisibleFrom, inImport, isQualifier)
storeResult(trace, referenceExpression, descriptors.singleOrNull(), shouldBeVisibleFrom, position, isQualifier)
}
}
@@ -540,7 +518,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
referenceExpression: KtSimpleNameExpression,
descriptor: DeclarationDescriptor?,
shouldBeVisibleFrom: DeclarationDescriptor?,
inImport: Boolean,
position: QualifierPosition,
isQualifier: Boolean = true
) {
if (descriptor == null) {
@@ -562,17 +540,17 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
else {
shouldBeVisibleFrom
}
if (!isVisible(descriptor, fromToCheck, inImport)) {
if (!isVisible(descriptor, fromToCheck, position)) {
trace.report(Errors.INVISIBLE_REFERENCE.on(referenceExpression, descriptor, descriptor.visibility, descriptor))
}
}
if (isQualifier) {
storageQualifier(trace, referenceExpression, descriptor)
storeQualifier(trace, referenceExpression, descriptor)
}
}
private fun storageQualifier(trace: BindingTrace, referenceExpression: KtSimpleNameExpression, descriptor: DeclarationDescriptor) {
private fun storeQualifier(trace: BindingTrace, referenceExpression: KtSimpleNameExpression, descriptor: DeclarationDescriptor) {
val qualifier =
when (descriptor) {
is PackageViewDescriptor -> PackageQualifier(referenceExpression, descriptor)
@@ -586,12 +564,12 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
private fun isVisible(
descriptor: DeclarationDescriptor,
shouldBeVisibleFrom: DeclarationDescriptor?,
inImport: Boolean
position: QualifierPosition
): Boolean {
if (descriptor !is DeclarationDescriptorWithVisibility || shouldBeVisibleFrom == null) return true
val visibility = descriptor.visibility
if (inImport) {
if (position == QualifierPosition.IMPORT) {
if (Visibilities.isPrivate(visibility)) return false
if (!visibility.mustCheckInImports()) return true
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
@@ -329,17 +330,51 @@ public class CallExpressionResolver {
*/
@NotNull
public KotlinTypeInfo getQualifiedExpressionTypeInfo(
@NotNull KtQualifiedExpression expression, @NotNull ExpressionTypingContext context
@NotNull KtQualifiedExpression expression, @NotNull final ExpressionTypingContext context
) {
ExpressionTypingContext currentContext = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
Function1<KtSimpleNameExpression, Boolean> isValueFunction = new Function1<KtSimpleNameExpression, Boolean>() {
@Override
public Boolean invoke(KtSimpleNameExpression nameExpression) {
TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create(
context, "trace to resolve as local variable or property", nameExpression);
Call call = CallMaker.makePropertyCall(ReceiverValue.NO_RECEIVER, null, nameExpression);
BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create(
context.replaceTraceAndCache(temporaryForVariable),
call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
if (resolutionResult.isSingleResult() &&
resolutionResult.getResultingDescriptor() instanceof FakeCallableDescriptorForObject) {
return false;
}
return !resolutionResult.isNothing();
}
};
List<CallExpressionElement> elementChain =
qualifiedExpressionResolver.resolveQualifierInExpressionAndUnroll(expression, context);
qualifiedExpressionResolver.resolveQualifierInExpressionAndUnroll(expression, context, isValueFunction);
KotlinTypeInfo receiverTypeInfo;
KotlinType receiverType;
DataFlowInfo receiverDataFlowInfo;
CallExpressionElement firstElement = elementChain.iterator().next();
KotlinTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfo(firstElement.getReceiver(), currentContext);
KotlinType receiverType = receiverTypeInfo.getType();
DataFlowInfo receiverDataFlowInfo = receiverTypeInfo.getDataFlowInfo();
KtExpression firstReceiver = firstElement.getReceiver();
Qualifier firstQualifier = context.trace.get(BindingContext.QUALIFIER, firstReceiver);
if (firstQualifier == null) {
receiverTypeInfo = expressionTypingServices.getTypeInfo(firstReceiver, currentContext);
receiverType = receiverTypeInfo.getType();
receiverDataFlowInfo = receiverTypeInfo.getDataFlowInfo();
}
else {
receiverType = null;
receiverDataFlowInfo = currentContext.dataFlowInfo;
//noinspection ConstantConditions
receiverTypeInfo = new KotlinTypeInfo(receiverType, receiverDataFlowInfo);
}
KotlinTypeInfo resultTypeInfo = receiverTypeInfo;
boolean unconditional = true;
@@ -366,7 +401,9 @@ public class CallExpressionResolver {
getSelectorReturnTypeInfo(receiver, element.getNode(), selectorExpression, currentContext);
KotlinType selectorReturnType = selectorReturnTypeInfo.getType();
resolveDeferredReceiverInQualifiedExpression(qualifierReceiver, element.getQualified(), currentContext);
if (qualifierReceiver != null) {
resolveDeferredReceiverInQualifiedExpression(qualifierReceiver, element.getQualified(), currentContext);
}
checkNestedClassAccess(element.getQualified(), currentContext);
boolean safeCall = element.getSafe();
@@ -415,11 +452,10 @@ public class CallExpressionResolver {
}
private void resolveDeferredReceiverInQualifiedExpression(
@Nullable QualifierReceiver qualifierReceiver,
@NotNull QualifierReceiver qualifierReceiver,
@NotNull KtQualifiedExpression qualifiedExpression,
@NotNull ExpressionTypingContext context
) {
if (qualifierReceiver == null) return;
KtExpression calleeExpression =
KtPsiUtil.deparenthesize(CallUtilKt.getCalleeExpressionIfAny(qualifiedExpression.getSelectorExpression()));
DeclarationDescriptor selectorDescriptor =
@@ -22,14 +22,20 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtQualifiedExpression
import java.util.*
internal fun unroll(root: KtQualifiedExpression): Deque<CallExpressionElement> {
var current: KtExpression = root
val result = linkedListOf<CallExpressionElement>()
while (current is KtQualifiedExpression) {
result.addFirst(CallExpressionElement(current))
current = result.first.receiver
public fun unrollToLeftMostQualifiedExpression(expression: KtQualifiedExpression): List<KtQualifiedExpression> {
val unrolled = arrayListOf<KtQualifiedExpression>()
var finger = expression
while (true) {
unrolled.add(finger)
val receiver = finger.receiverExpression
if (receiver !is KtQualifiedExpression) {
break
}
finger = receiver
}
return result
return unrolled.asReversed()
}
public data class CallExpressionElement internal constructor (val qualified: KtQualifiedExpression) {
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
import kotlin.properties.Delegates
public interface Qualifier: Receiver {
@@ -150,11 +149,7 @@ class ClassQualifier(
override fun toString() = "Class{$classifier}"
}
fun createQualifier(
expression: KtSimpleNameExpression,
receiver: Receiver,
context: ExpressionTypingContext
): QualifierReceiver? {
fun createQualifier(expression: KtSimpleNameExpression, receiver: Receiver, context: ExpressionTypingContext): QualifierReceiver? {
val receiverScope = when {
!receiver.exists() -> context.scope
receiver is QualifierReceiver -> receiver.scope.memberScopeAsImportingScope()
@@ -98,17 +98,6 @@ public fun HierarchicalScope.findFunction(name: Name, location: LookupLocation,
return null
}
public fun HierarchicalScope.containsFunctionOrVariable(name: Name, location: LookupLocation): Boolean {
processForMeAndParent {
if (it.getContributedFunctions(name, location).isNotEmpty() ||
it.getContributedVariables(name, location).isNotEmpty()
) {
return true
}
}
return false
}
public fun HierarchicalScope.collectSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation)
= collectAllFromImportingScopes { it.getContributedSyntheticExtensionProperties(receiverTypes, name, location) }
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.types.KotlinType
* At the end current data flow info is x != null && y != null, but jump data flow info is x != null only.
* Both break and continue are counted as possible jump outside of a loop, but return is not.
*/
class KotlinTypeInfo(
class KotlinTypeInfo @JvmOverloads constructor(
val type: KotlinType?,
val dataFlowInfo: DataFlowInfo,
val jumpOutPossible: Boolean = false,
@@ -0,0 +1,8 @@
class A {
@Deprecated("deprecated") companion object
class B
}
val x1 = A.B()
@@ -0,0 +1,24 @@
package
public val x1: A.B
public final class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final class B {
public constructor B()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.Deprecated(message = "deprecated") public companion object Companion {
private constructor Companion()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,33 @@
// FILE: a.kt
package a
class A(val b: String) {
companion object {
val c: String = ""
}
fun mtd() = c.length
}
// FILE: b.kt
package b
// FILE: c.kt
package c
// FILE: test.kt
package test
import a.A
fun <T, R> T.with(f: T.() -> R) = f()
fun A.extFun1() = b.length
// fun A.extFun2() = c.length // TODO fix KT-9953
val x1 = A("").with { b.length }
// val x2 = A("").with { c.length } // TODO fix KT-9953
val x3 = A.with { c.length }
@@ -0,0 +1,34 @@
package
package a {
public final class A {
public constructor A(/*0*/ b: kotlin.String)
public final val b: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun mtd(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion {
private constructor Companion()
public final val c: kotlin.String = ""
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
}
package b {
}
package c {
}
package test {
public val x1: kotlin.Int
public val x3: kotlin.Int
public fun a.A.extFun1(): kotlin.Int
public fun </*0*/ T, /*1*/ R> T.with(/*0*/ f: T.() -> R): R
}
@@ -4767,6 +4767,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("classWithCompanionObject.kt")
public void testClassWithCompanionObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/classWithCompanionObject.kt");
doTest(fileName);
}
@TestMetadata("componentUsage.kt")
public void testComponentUsage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/componentUsage.kt");
@@ -13074,6 +13080,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("implicitReceiverProperty.kt")
public void testImplicitReceiverProperty() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/implicitReceiverProperty.kt");
doTest(fileName);
}
@TestMetadata("incompleteConstructorInvocation.kt")
public void testIncompleteConstructorInvocation() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/incompleteConstructorInvocation.kt");
@@ -19,8 +19,8 @@ import bar.*
this./*c:foo.A*/a
this./*c:foo.A*/foo()
/*c:foo.A c:foo.A.Companion p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io c:foo.A(getBaz) c:foo.A(getBAZ)*/baz()
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io c:foo.A c:foo.A.Companion*/Companion./*c:foo.A.Companion*/a
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io c:foo.A c:foo.A.Companion*/O./*c:foo.A.O*/v = "OK"
/*c:foo.A c:foo.A.Companion p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/Companion./*c:foo.A.Companion*/a
/*c:foo.A c:foo.A.Companion p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/O./*c:foo.A.O*/v = "OK"
}
class B {
@@ -64,8 +64,8 @@ import bar.*
val a = 1
fun foo() {
/*c:foo.E*/a
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io c:foo.E*/Y./*c:foo.E*/a
/*c:foo.E p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/Y./*c:foo.E*/a
/*c:foo.E*/foo()
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io c:foo.E*/X./*c:foo.E*/foo()
/*c:foo.E p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/X./*c:foo.E*/foo()
}
}
@@ -9,15 +9,15 @@ import bar.*
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A()./*c:foo.A*/d = "new value"
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A()./*c:foo.A*/foo()
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A*/B()./*c:foo.A.B*/a
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A c:foo.A.Companion*/B./*c:foo.A.B c:foo.A.B.CO*/bar(1)
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A c:foo.A.Companion*/B./*c:foo.A.B c:foo.A.B.CO*/CO./*c:foo.A.B.CO*/bar(1)
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A*/B./*c:foo.A.B c:foo.A.B.CO*/bar(1)
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A*/B./*c:foo.A.B*/CO./*c:foo.A.B.CO*/bar(1)
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A c:foo.A.Companion*/a
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A c:foo.A.Companion*/baz()
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A*/Companion
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A c:foo.A.Companion*/Companion./*c:foo.A.Companion*/baz()
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A*/Companion./*c:foo.A.Companion*/baz()
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A*/O
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A c:foo.A.Companion*/O./*c:foo.A.O*/v = "OK"
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A*/O./*c:foo.A.O*/v = "OK"
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A c:foo.A.Companion p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io c:foo.A.Companion(getVala) c:foo.A.Companion(getVALA)*/vala
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io*/A./*c:foo.A c:foo.A.Companion p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.io c:foo.A.Companion(getVara) c:foo.A.Companion(getVARA)*/vara()