Support for new double colon expressions in type checker
Despite the fact that the LHS of a double colon expression is now KtExpression instead of KtUserType, we must still consider it a type for callable references to work. Extract and reuse relevant parts of QualifiedExpressionResolver and TypeResolver to support this behavior
This commit is contained in:
@@ -22,6 +22,20 @@ import org.jetbrains.kotlin.KtNodeTypes
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
abstract class KtDoubleColonExpression(node: ASTNode) : KtExpressionImpl(node) {
|
abstract class KtDoubleColonExpression(node: ASTNode) : KtExpressionImpl(node) {
|
||||||
|
val receiverExpression: KtExpression?
|
||||||
|
get() = node.firstChildNode.psi as? KtExpression
|
||||||
|
|
||||||
|
val hasQuestionMarks: Boolean
|
||||||
|
get() {
|
||||||
|
for (element in generateSequence(node.firstChildNode, ASTNode::getTreeNext)) {
|
||||||
|
when (element.elementType) {
|
||||||
|
KtTokens.QUEST -> return true
|
||||||
|
KtTokens.COLONCOLON -> return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("Double colon expression must have '::': $text")
|
||||||
|
}
|
||||||
|
|
||||||
val typeReference: KtTypeReference?
|
val typeReference: KtTypeReference?
|
||||||
get() = findChildByType(KtNodeTypes.TYPE_REFERENCE)
|
get() = findChildByType(KtNodeTypes.TYPE_REFERENCE)
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.Qualifier;
|
|||||||
import org.jetbrains.kotlin.types.DeferredType;
|
import org.jetbrains.kotlin.types.DeferredType;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.expressions.CaptureKind;
|
import org.jetbrains.kotlin.types.expressions.CaptureKind;
|
||||||
|
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
|
||||||
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
|
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
|
||||||
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor;
|
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor;
|
||||||
import org.jetbrains.kotlin.util.Box;
|
import org.jetbrains.kotlin.util.Box;
|
||||||
@@ -102,6 +103,8 @@ public interface BindingContext {
|
|||||||
*/
|
*/
|
||||||
WritableSlice<KtExpression, Qualifier> QUALIFIER = new BasicWritableSlice<KtExpression, Qualifier>(DO_NOTHING);
|
WritableSlice<KtExpression, Qualifier> QUALIFIER = new BasicWritableSlice<KtExpression, Qualifier>(DO_NOTHING);
|
||||||
|
|
||||||
|
WritableSlice<KtExpression, DoubleColonLHS> DOUBLE_COLON_LHS = new BasicWritableSlice<KtExpression, DoubleColonLHS>(DO_NOTHING);
|
||||||
|
|
||||||
WritableSlice<KtSuperExpression, KotlinType> THIS_TYPE_FOR_SUPER_EXPRESSION =
|
WritableSlice<KtSuperExpression, KotlinType> THIS_TYPE_FOR_SUPER_EXPRESSION =
|
||||||
new BasicWritableSlice<KtSuperExpression, KotlinType>(DO_NOTHING);
|
new BasicWritableSlice<KtSuperExpression, KotlinType>(DO_NOTHING);
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
|
|||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||||
|
import org.jetbrains.kotlin.types.expressions.isWithoutValueArguments
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
|||||||
isDebuggerContext: Boolean
|
isDebuggerContext: Boolean
|
||||||
): TypeQualifierResolutionResult {
|
): TypeQualifierResolutionResult {
|
||||||
val ownerDescriptor = if (!isDebuggerContext) scope.ownerDescriptor else null
|
val ownerDescriptor = if (!isDebuggerContext) scope.ownerDescriptor else null
|
||||||
if (userType.qualifier == null && !userType.startWithPackage) { // optimization for non-qualified types
|
if (userType.qualifier == null && !userType.startWithPackage) {
|
||||||
val descriptor = userType.referenceExpression?.let {
|
val descriptor = userType.referenceExpression?.let {
|
||||||
val classifier = scope.findClassifier(it.getReferencedNameAsName(), KotlinLookupLocation(it))
|
val classifier = scope.findClassifier(it.getReferencedNameAsName(), KotlinLookupLocation(it))
|
||||||
storeResult(trace, it, classifier, ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = false)
|
storeResult(trace, it, classifier, ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = false)
|
||||||
@@ -87,13 +88,25 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
|||||||
) as? ClassifierDescriptor
|
) as? ClassifierDescriptor
|
||||||
return TypeQualifierResolutionResult(qualifierPartList, descriptor)
|
return TypeQualifierResolutionResult(qualifierPartList, descriptor)
|
||||||
}
|
}
|
||||||
assert(qualifierPartList.size >= 1) {
|
|
||||||
"Too short qualifier list for user type $userType : ${qualifierPartList.joinToString()}"
|
return resolveQualifierPartListForType(
|
||||||
}
|
qualifierPartList, ownerDescriptor, module, scope.check { !userType.startWithPackage }, trace, isQualifier = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveQualifierPartListForType(
|
||||||
|
qualifierPartList: List<QualifierPart>,
|
||||||
|
ownerDescriptor: DeclarationDescriptor?,
|
||||||
|
module: ModuleDescriptor,
|
||||||
|
scope: LexicalScope?,
|
||||||
|
trace: BindingTrace,
|
||||||
|
isQualifier: Boolean
|
||||||
|
): TypeQualifierResolutionResult {
|
||||||
|
assert(qualifierPartList.isNotEmpty()) { "Qualifier list should not be empty" }
|
||||||
|
|
||||||
val qualifier = resolveToPackageOrClass(
|
val qualifier = resolveToPackageOrClass(
|
||||||
qualifierPartList.subList(0, qualifierPartList.size - 1), module,
|
qualifierPartList.subList(0, qualifierPartList.size - 1), module, trace, ownerDescriptor, scope,
|
||||||
trace, ownerDescriptor, scope.check { !userType.startWithPackage }, position = QualifierPosition.TYPE
|
position = QualifierPosition.TYPE
|
||||||
) ?: return TypeQualifierResolutionResult(qualifierPartList, null)
|
) ?: return TypeQualifierResolutionResult(qualifierPartList, null)
|
||||||
|
|
||||||
val lastPart = qualifierPartList.last()
|
val lastPart = qualifierPartList.last()
|
||||||
@@ -102,10 +115,36 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
|||||||
is ClassDescriptor -> qualifier.unsubstitutedInnerClassesScope.getContributedClassifier(lastPart.name, lastPart.location)
|
is ClassDescriptor -> qualifier.unsubstitutedInnerClassesScope.getContributedClassifier(lastPart.name, lastPart.location)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
storeResult(trace, lastPart.expression, classifier, ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = false)
|
storeResult(trace, lastPart.expression, classifier, ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = isQualifier)
|
||||||
return TypeQualifierResolutionResult(qualifierPartList, classifier)
|
return TypeQualifierResolutionResult(qualifierPartList, classifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resolveDescriptorForDoubleColonLHS(
|
||||||
|
expression: KtExpression,
|
||||||
|
scope: LexicalScope,
|
||||||
|
trace: BindingTrace,
|
||||||
|
isDebuggerContext: Boolean
|
||||||
|
): TypeQualifierResolutionResult {
|
||||||
|
val ownerDescriptor = if (!isDebuggerContext) scope.ownerDescriptor else null
|
||||||
|
|
||||||
|
val qualifierPartList = expression.asQualifierPartList(doubleColonLHS = true)
|
||||||
|
if (qualifierPartList.isEmpty()) {
|
||||||
|
return TypeQualifierResolutionResult(qualifierPartList, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qualifierPartList.size == 1) {
|
||||||
|
val (name, simpleName) = qualifierPartList.single()
|
||||||
|
val descriptor = scope.findClassifier(name, KotlinLookupLocation(simpleName))
|
||||||
|
storeResult(trace, simpleName, descriptor, ownerDescriptor, position = QualifierPosition.TYPE, isQualifier = true)
|
||||||
|
|
||||||
|
return TypeQualifierResolutionResult(qualifierPartList, descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolveQualifierPartListForType(
|
||||||
|
qualifierPartList, ownerDescriptor, scope.ownerDescriptor.module, scope, trace, isQualifier = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private val KtUserType.startWithPackage: Boolean
|
private val KtUserType.startWithPackage: Boolean
|
||||||
get() {
|
get() {
|
||||||
var firstPart = this
|
var firstPart = this
|
||||||
@@ -270,24 +309,32 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
|||||||
storeResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom = null, position = QualifierPosition.IMPORT, isQualifier = false)
|
storeResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom = null, position = QualifierPosition.IMPORT, isQualifier = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtExpression.asQualifierPartList(): List<QualifierPart> {
|
private fun KtExpression.asQualifierPartList(doubleColonLHS: Boolean = false): List<QualifierPart> {
|
||||||
val result = SmartList<QualifierPart>()
|
val result = SmartList<QualifierPart>()
|
||||||
var expression: KtExpression? = this
|
|
||||||
loop@ while (expression != null) {
|
fun addQualifierPart(expression: KtExpression?): Boolean {
|
||||||
when (expression) {
|
if (expression is KtSimpleNameExpression) {
|
||||||
is KtSimpleNameExpression -> {
|
result.add(QualifierPart(expression))
|
||||||
result.add(QualifierPart(expression.getReferencedNameAsName(), expression))
|
return true
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
is KtQualifiedExpression -> {
|
|
||||||
(expression.selectorExpression as? KtSimpleNameExpression)?.let {
|
|
||||||
result.add(QualifierPart(it.getReferencedNameAsName(), it))
|
|
||||||
}
|
|
||||||
expression = expression.receiverExpression
|
|
||||||
}
|
|
||||||
else -> expression = null
|
|
||||||
}
|
}
|
||||||
|
if (doubleColonLHS && expression is KtCallExpression && expression.isWithoutValueArguments) {
|
||||||
|
val simpleName = expression.calleeExpression as KtSimpleNameExpression
|
||||||
|
result.add(QualifierPart(simpleName.getReferencedNameAsName(), simpleName, expression.typeArgumentList))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var expression: KtExpression? = this
|
||||||
|
while (true) {
|
||||||
|
if (addQualifierPart(expression)) break
|
||||||
|
if (expression !is KtQualifiedExpression) break
|
||||||
|
|
||||||
|
addQualifierPart(expression.selectorExpression)
|
||||||
|
|
||||||
|
expression = expression.receiverExpression
|
||||||
|
}
|
||||||
|
|
||||||
return result.asReversed()
|
return result.asReversed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ import org.jetbrains.kotlin.storage.StorageManager
|
|||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.Variance.*
|
import org.jetbrains.kotlin.types.Variance.*
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isArrayOfNothing
|
import org.jetbrains.kotlin.types.typeUtil.isArrayOfNothing
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class TypeResolver(
|
class TypeResolver(
|
||||||
private val annotationResolver: AnnotationResolver,
|
private val annotationResolver: AnnotationResolver,
|
||||||
@@ -163,37 +162,21 @@ class TypeResolver(
|
|||||||
var result: PossiblyBareType? = null
|
var result: PossiblyBareType? = null
|
||||||
typeElement?.accept(object : KtVisitorVoid() {
|
typeElement?.accept(object : KtVisitorVoid() {
|
||||||
override fun visitUserType(type: KtUserType) {
|
override fun visitUserType(type: KtUserType) {
|
||||||
val qualifierResolutionResults = resolveDescriptorForType(c.scope, type, c.trace, c.isDebuggerContext)
|
val qualifierResolutionResult = resolveDescriptorForType(c.scope, type, c.trace, c.isDebuggerContext)
|
||||||
val (qualifierParts, classifierDescriptor) = qualifierResolutionResults
|
val classifier = qualifierResolutionResult.classifierDescriptor
|
||||||
|
|
||||||
if (classifierDescriptor == null) {
|
if (classifier == null) {
|
||||||
val arguments = resolveTypeProjections(
|
val arguments = resolveTypeProjections(
|
||||||
c, ErrorUtils.createErrorType("No type").constructor, qualifierResolutionResults.allProjections)
|
c, ErrorUtils.createErrorType("No type").constructor, qualifierResolutionResult.allProjections
|
||||||
|
)
|
||||||
result = type(ErrorUtils.createErrorTypeWithArguments(type.getDebugText(), arguments))
|
result = type(ErrorUtils.createErrorTypeWithArguments(type.getDebugText(), arguments))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val referenceExpression = type.getReferenceExpression()
|
val referenceExpression = type.referenceExpression ?: return
|
||||||
val referencedName = type.getReferencedName()
|
c.trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifier)
|
||||||
if (referenceExpression == null || referencedName == null) return
|
|
||||||
|
|
||||||
c.trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor)
|
result = resolveTypeForClassifier(c, classifier, qualifierResolutionResult, type, annotations)
|
||||||
|
|
||||||
result = when (classifierDescriptor) {
|
|
||||||
is TypeParameterDescriptor -> {
|
|
||||||
assert(qualifierParts.size == 1) {
|
|
||||||
"Type parameter can be resolved only by it's short name, but '${type.text}' is contradiction " +
|
|
||||||
"with ${qualifierParts.size} qualifier parts"
|
|
||||||
}
|
|
||||||
|
|
||||||
type(resolveTypeForTypeParameter(c, annotations, classifierDescriptor, referenceExpression, type))
|
|
||||||
}
|
|
||||||
is ClassDescriptor ->
|
|
||||||
resolveTypeForClass(c, annotations, classifierDescriptor, type, qualifierResolutionResults)
|
|
||||||
is TypeAliasDescriptor ->
|
|
||||||
resolveTypeForTypeAlias(c, annotations, classifierDescriptor, type, qualifierResolutionResults)
|
|
||||||
else -> error("Unexpected classifier type: ${classifierDescriptor.javaClass}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitNullableType(nullableType: KtNullableType) {
|
override fun visitNullableType(nullableType: KtNullableType) {
|
||||||
@@ -308,13 +291,13 @@ class TypeResolver(
|
|||||||
c: TypeResolutionContext, annotations: Annotations,
|
c: TypeResolutionContext, annotations: Annotations,
|
||||||
typeParameter: TypeParameterDescriptor,
|
typeParameter: TypeParameterDescriptor,
|
||||||
referenceExpression: KtSimpleNameExpression,
|
referenceExpression: KtSimpleNameExpression,
|
||||||
type: KtUserType
|
typeArgumentList: KtTypeArgumentList?
|
||||||
): KotlinType {
|
): KotlinType {
|
||||||
val scopeForTypeParameter = getScopeForTypeParameter(c, typeParameter)
|
val scopeForTypeParameter = getScopeForTypeParameter(c, typeParameter)
|
||||||
|
|
||||||
val arguments = resolveTypeProjections(c, ErrorUtils.createErrorType("No type").constructor, type.typeArguments)
|
if (typeArgumentList != null) {
|
||||||
if (!arguments.isEmpty()) {
|
resolveTypeProjections(c, ErrorUtils.createErrorType("No type").constructor, typeArgumentList.arguments)
|
||||||
c.trace.report(TYPE_ARGUMENTS_NOT_ALLOWED.on(type.typeArgumentList!!, "for type parameters"))
|
c.trace.report(TYPE_ARGUMENTS_NOT_ALLOWED.on(typeArgumentList, "for type parameters"))
|
||||||
}
|
}
|
||||||
|
|
||||||
val containing = typeParameter.containingDeclaration
|
val containing = typeParameter.containingDeclaration
|
||||||
@@ -342,9 +325,34 @@ class TypeResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resolveTypeForClassifier(
|
||||||
|
c: TypeResolutionContext,
|
||||||
|
descriptor: ClassifierDescriptor,
|
||||||
|
qualifierResolutionResult: QualifiedExpressionResolver.TypeQualifierResolutionResult,
|
||||||
|
element: KtElement,
|
||||||
|
annotations: Annotations
|
||||||
|
): PossiblyBareType {
|
||||||
|
val qualifierParts = qualifierResolutionResult.qualifierParts
|
||||||
|
|
||||||
|
return when (descriptor) {
|
||||||
|
is TypeParameterDescriptor -> {
|
||||||
|
assert(qualifierParts.size == 1) {
|
||||||
|
"Type parameter can be resolved only by it's short name, but '${element.text}' is contradiction " +
|
||||||
|
"with ${qualifierParts.size} qualifier parts"
|
||||||
|
}
|
||||||
|
|
||||||
|
val qualifierPart = qualifierParts.single()
|
||||||
|
type(resolveTypeForTypeParameter(c, annotations, descriptor, qualifierPart.expression, qualifierPart.typeArguments))
|
||||||
|
}
|
||||||
|
is ClassDescriptor -> resolveTypeForClass(c, annotations, descriptor, element, qualifierResolutionResult)
|
||||||
|
is TypeAliasDescriptor -> resolveTypeForTypeAlias(c, annotations, descriptor, element as KtUserType /* TODO */, qualifierResolutionResult)
|
||||||
|
else -> error("Unexpected classifier type: ${descriptor.javaClass}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun resolveTypeForClass(
|
private fun resolveTypeForClass(
|
||||||
c: TypeResolutionContext, annotations: Annotations,
|
c: TypeResolutionContext, annotations: Annotations,
|
||||||
classDescriptor: ClassDescriptor, type: KtUserType,
|
classDescriptor: ClassDescriptor, element: KtElement,
|
||||||
qualifierResolutionResult: QualifiedExpressionResolver.TypeQualifierResolutionResult
|
qualifierResolutionResult: QualifiedExpressionResolver.TypeQualifierResolutionResult
|
||||||
): PossiblyBareType {
|
): PossiblyBareType {
|
||||||
val typeConstructor = classDescriptor.typeConstructor
|
val typeConstructor = classDescriptor.typeConstructor
|
||||||
@@ -366,7 +374,7 @@ class TypeResolver(
|
|||||||
|
|
||||||
assert(collectedArgumentAsTypeProjections.size <= parameters.size) {
|
assert(collectedArgumentAsTypeProjections.size <= parameters.size) {
|
||||||
"Collected arguments count should be not greater then parameters count," +
|
"Collected arguments count should be not greater then parameters count," +
|
||||||
" but ${collectedArgumentAsTypeProjections.size} instead of ${parameters.size} found in ${type.text}"
|
" but ${collectedArgumentAsTypeProjections.size} instead of ${parameters.size} found in ${element.text}"
|
||||||
}
|
}
|
||||||
|
|
||||||
val argumentsFromUserType = resolveTypeProjections(c, typeConstructor, collectedArgumentAsTypeProjections)
|
val argumentsFromUserType = resolveTypeProjections(c, typeConstructor, collectedArgumentAsTypeProjections)
|
||||||
@@ -374,7 +382,7 @@ class TypeResolver(
|
|||||||
|
|
||||||
assert(arguments.size == parameters.size) {
|
assert(arguments.size == parameters.size) {
|
||||||
"Collected arguments count should be equal to parameters count," +
|
"Collected arguments count should be equal to parameters count," +
|
||||||
" but ${collectedArgumentAsTypeProjections.size} instead of ${parameters.size} found in ${type.text}"
|
" but ${collectedArgumentAsTypeProjections.size} instead of ${parameters.size} found in ${element.text}"
|
||||||
}
|
}
|
||||||
|
|
||||||
val resultingType = KotlinTypeImpl.create(annotations, classDescriptor, false, arguments)
|
val resultingType = KotlinTypeImpl.create(annotations, classDescriptor, false, arguments)
|
||||||
@@ -397,7 +405,7 @@ class TypeResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (resultingType.isArrayOfNothing()) {
|
if (resultingType.isArrayOfNothing()) {
|
||||||
c.trace.report(UNSUPPORTED.on(type, "Array<Nothing> is illegal"))
|
c.trace.report(UNSUPPORTED.on(element, "Array<Nothing> is illegal"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return type(resultingType)
|
return type(resultingType)
|
||||||
@@ -783,10 +791,13 @@ class TypeResolver(
|
|||||||
TypeProjectionImpl((it.original as TypeParameterDescriptor).defaultType)
|
TypeProjectionImpl((it.original as TypeParameterDescriptor).defaultType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveTypeProjections(c: TypeResolutionContext, constructor: TypeConstructor, argumentElements: List<KtTypeProjection>): List<TypeProjection> {
|
fun resolveTypeProjections(
|
||||||
|
c: TypeResolutionContext,
|
||||||
|
constructor: TypeConstructor,
|
||||||
|
argumentElements: List<KtTypeProjection>
|
||||||
|
): List<TypeProjection> {
|
||||||
return argumentElements.mapIndexed { i, argumentElement ->
|
return argumentElements.mapIndexed { i, argumentElement ->
|
||||||
|
val projectionKind = argumentElement.projectionKind
|
||||||
val projectionKind = argumentElement.getProjectionKind()
|
|
||||||
ModifierCheckerCore.check(argumentElement, c.trace, null)
|
ModifierCheckerCore.check(argumentElement, c.trace, null)
|
||||||
if (projectionKind == KtProjectionKind.STAR) {
|
if (projectionKind == KtProjectionKind.STAR) {
|
||||||
val parameters = constructor.parameters
|
val parameters = constructor.parameters
|
||||||
|
|||||||
+2
-1
@@ -265,12 +265,13 @@ fun getReflectionTypeForCandidateDescriptor(
|
|||||||
fun createReflectionTypeForResolvedCallableReference(
|
fun createReflectionTypeForResolvedCallableReference(
|
||||||
reference: KtCallableReferenceExpression,
|
reference: KtCallableReferenceExpression,
|
||||||
lhsType: KotlinType?,
|
lhsType: KotlinType?,
|
||||||
|
ignoreReceiver: Boolean,
|
||||||
descriptor: CallableDescriptor,
|
descriptor: CallableDescriptor,
|
||||||
context: ResolutionContext<*>,
|
context: ResolutionContext<*>,
|
||||||
reflectionTypes: ReflectionTypes
|
reflectionTypes: ReflectionTypes
|
||||||
): KotlinType? {
|
): KotlinType? {
|
||||||
val type = createReflectionTypeForCallableDescriptor(
|
val type = createReflectionTypeForCallableDescriptor(
|
||||||
descriptor, lhsType, reflectionTypes, context.trace, reference.callableReference, reference.isEmptyLHS
|
descriptor, lhsType, reflectionTypes, context.trace, reference.callableReference, ignoreReceiver
|
||||||
) ?: return null
|
) ?: return null
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
is FunctionDescriptor -> {
|
is FunctionDescriptor -> {
|
||||||
|
|||||||
+126
-47
@@ -24,13 +24,9 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||||
import org.jetbrains.kotlin.diagnostics.Severity
|
import org.jetbrains.kotlin.diagnostics.Severity
|
||||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtClassLiteralExpression
|
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||||
import org.jetbrains.kotlin.psi.KtUserType
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
|
||||||
import org.jetbrains.kotlin.resolve.TypeResolutionContext
|
|
||||||
import org.jetbrains.kotlin.resolve.TypeResolver
|
|
||||||
import org.jetbrains.kotlin.resolve.callableReferences.createReflectionTypeForResolvedCallableReference
|
import org.jetbrains.kotlin.resolve.callableReferences.createReflectionTypeForResolvedCallableReference
|
||||||
import org.jetbrains.kotlin.resolve.callableReferences.resolveCallableReferenceTarget
|
import org.jetbrains.kotlin.resolve.callableReferences.resolveCallableReferenceTarget
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver
|
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver
|
||||||
@@ -43,63 +39,147 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.KotlinTypeImpl
|
import org.jetbrains.kotlin.types.KotlinTypeImpl
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
|
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
// TODO: use a language level option
|
||||||
|
val BOUND_REFERENCES_ENABLED by lazy { System.getProperty("kotlin.lang.enable.bound.references") == "true" }
|
||||||
|
|
||||||
|
sealed class DoubleColonLHS(val type: KotlinType) {
|
||||||
|
class Expression(val typeInfo: KotlinTypeInfo) : DoubleColonLHS(typeInfo.type!!)
|
||||||
|
|
||||||
|
class Type(type: KotlinType, val possiblyBareType: PossiblyBareType) : DoubleColonLHS(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if this expression has the form "A<B>" which means it's a type on the LHS of a double colon expression
|
||||||
|
internal val KtCallExpression.isWithoutValueArguments: Boolean
|
||||||
|
get() = valueArgumentList == null && lambdaArguments.isEmpty()
|
||||||
|
|
||||||
class DoubleColonExpressionResolver(
|
class DoubleColonExpressionResolver(
|
||||||
val callResolver: CallResolver,
|
val callResolver: CallResolver,
|
||||||
val callExpressionResolver: CallExpressionResolver,
|
val callExpressionResolver: CallExpressionResolver,
|
||||||
|
val qualifiedExpressionResolver: QualifiedExpressionResolver,
|
||||||
val dataFlowAnalyzer: DataFlowAnalyzer,
|
val dataFlowAnalyzer: DataFlowAnalyzer,
|
||||||
val reflectionTypes: ReflectionTypes,
|
val reflectionTypes: ReflectionTypes,
|
||||||
val typeResolver: TypeResolver
|
val typeResolver: TypeResolver
|
||||||
) {
|
) {
|
||||||
|
private lateinit var expressionTypingServices: ExpressionTypingServices
|
||||||
|
|
||||||
|
// component dependency cycle
|
||||||
|
@Inject
|
||||||
|
fun setExpressionTypingServices(expressionTypingServices: ExpressionTypingServices) {
|
||||||
|
this.expressionTypingServices = expressionTypingServices
|
||||||
|
}
|
||||||
|
|
||||||
fun visitClassLiteralExpression(expression: KtClassLiteralExpression, c: ExpressionTypingContext): KotlinTypeInfo {
|
fun visitClassLiteralExpression(expression: KtClassLiteralExpression, c: ExpressionTypingContext): KotlinTypeInfo {
|
||||||
val type = resolveClassLiteral(expression, c)
|
if (expression.isEmptyLHS) {
|
||||||
if (type != null && !type.isError) {
|
// "::class" will maybe mean "this::class", a class of "this" instance
|
||||||
return dataFlowAnalyzer.createCheckedTypeInfo(reflectionTypes.getKClassType(Annotations.EMPTY, type), c, expression)
|
c.trace.report(UNSUPPORTED.on(expression, "Class literals with empty left hand side are not yet supported"))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val result = resolveDoubleColonLHS(expression.receiverExpression!!, expression, c)
|
||||||
|
val type = result?.type
|
||||||
|
if (type != null && !type.isError) {
|
||||||
|
checkClassLiteral(c, expression, result!!)
|
||||||
|
return dataFlowAnalyzer.createCheckedTypeInfo(reflectionTypes.getKClassType(Annotations.EMPTY, type), c, expression)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return createTypeInfo(ErrorUtils.createErrorType("Unresolved class"), c)
|
return createTypeInfo(ErrorUtils.createErrorType("Unresolved class"), c)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveClassLiteral(expression: KtClassLiteralExpression, c: ExpressionTypingContext): KotlinType? {
|
private fun checkClassLiteral(c: ExpressionTypingContext, expression: KtClassLiteralExpression, result: DoubleColonLHS) {
|
||||||
if (expression.isEmptyLHS) {
|
if (result !is DoubleColonLHS.Type) return
|
||||||
// "::class" will maybe mean "this::class", a class of "this" instance
|
|
||||||
c.trace.report(UNSUPPORTED.on(expression, "Class literals with empty left hand side are not yet supported"))
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = TypeResolutionContext(
|
val type = result.type
|
||||||
c.scope, c.trace, /* checkBounds = */ false, /* allowBareTypes = */ true, /* isDebuggerContext = */ false
|
val reportError: Boolean
|
||||||
)
|
if (result.possiblyBareType.isBare) {
|
||||||
val possiblyBareType = typeResolver.resolvePossiblyBareType(context, expression.typeReference!!)
|
val descriptor = type.constructor.declarationDescriptor
|
||||||
|
if (descriptor is ClassDescriptor && KotlinBuiltIns.isNonPrimitiveArray(descriptor)) {
|
||||||
if (!possiblyBareType.isBare && possiblyBareType.actualType.isError) {
|
c.trace.report(ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT.on(expression))
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
var reportError = false
|
|
||||||
val type: KotlinType
|
|
||||||
if (possiblyBareType.isBare) {
|
|
||||||
val descriptor = possiblyBareType.bareTypeConstructor.declarationDescriptor as? ClassDescriptor
|
|
||||||
?: error("Only classes can produce bare types: $possiblyBareType")
|
|
||||||
if (KotlinBuiltIns.isNonPrimitiveArray(descriptor)) {
|
|
||||||
context.trace.report(ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT.on(expression))
|
|
||||||
}
|
}
|
||||||
|
reportError = false
|
||||||
type = KotlinTypeImpl.create(
|
|
||||||
Annotations.EMPTY, descriptor, possiblyBareType.isNullable,
|
|
||||||
descriptor.typeConstructor.parameters.map(TypeUtils::makeStarProjection)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
type = possiblyBareType.actualType
|
|
||||||
reportError = !isAllowedInClassLiteral(type)
|
reportError = !isAllowedInClassLiteral(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.isMarkedNullable || reportError) {
|
if (type.isMarkedNullable || reportError) {
|
||||||
context.trace.report(CLASS_LITERAL_LHS_NOT_A_CLASS.on(expression))
|
c.trace.report(CLASS_LITERAL_LHS_NOT_A_CLASS.on(expression))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the expression is not a call expression without value arguments (such as "A<B>") or a qualified expression
|
||||||
|
// which contains such call expression as one of its parts.
|
||||||
|
// In this case it's pointless to attempt to type check an expression on the LHS in "A<B>::class", since "A<B>" certainly means a type.
|
||||||
|
private fun KtExpression.canBeConsideredProperExpression(): Boolean {
|
||||||
|
return when (this) {
|
||||||
|
is KtCallExpression ->
|
||||||
|
!isWithoutValueArguments
|
||||||
|
is KtDotQualifiedExpression ->
|
||||||
|
receiverExpression.canBeConsideredProperExpression() &&
|
||||||
|
selectorExpression?.let { it.canBeConsideredProperExpression() } ?: false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveDoubleColonLHS(
|
||||||
|
expression: KtExpression, doubleColonExpression: KtDoubleColonExpression, c: ExpressionTypingContext
|
||||||
|
): DoubleColonLHS? {
|
||||||
|
// First, try resolving the LHS as expression, if possible
|
||||||
|
|
||||||
|
if (BOUND_REFERENCES_ENABLED && expression.canBeConsideredProperExpression() &&
|
||||||
|
!doubleColonExpression.hasQuestionMarks /* TODO: test this */) {
|
||||||
|
val traceForExpr = TemporaryTraceAndCache.create(c, "resolve '::' LHS as expression", expression)
|
||||||
|
val contextForExpr = c.replaceTraceAndCache(traceForExpr)
|
||||||
|
val typeInfo = expressionTypingServices.getTypeInfo(expression, contextForExpr)
|
||||||
|
val type = typeInfo.type
|
||||||
|
// TODO (!!!): it's wrong to only check type, should check that there's a companion qualifier
|
||||||
|
if (type != null && !DescriptorUtils.isCompanionObject(type.constructor.declarationDescriptor)) {
|
||||||
|
traceForExpr.commit()
|
||||||
|
return DoubleColonLHS.Expression(typeInfo).apply {
|
||||||
|
c.trace.record(BindingContext.DOUBLE_COLON_LHS, expression, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return type
|
// Then, try resolving it as type
|
||||||
|
|
||||||
|
val qualifierResolutionResult =
|
||||||
|
qualifiedExpressionResolver.resolveDescriptorForDoubleColonLHS(expression, c.scope, c.trace, c.isDebuggerContext)
|
||||||
|
|
||||||
|
val typeResolutionContext = TypeResolutionContext(
|
||||||
|
c.scope, c.trace, /* checkBounds = */ true, /* allowBareTypes = */ true,
|
||||||
|
/* isDebuggerContext = */ expression.suppressDiagnosticsInDebugMode() /* TODO: test this */
|
||||||
|
)
|
||||||
|
|
||||||
|
val classifier = qualifierResolutionResult.classifierDescriptor
|
||||||
|
if (classifier == null) {
|
||||||
|
typeResolver.resolveTypeProjections(
|
||||||
|
typeResolutionContext, ErrorUtils.createErrorType("No type").constructor, qualifierResolutionResult.allProjections
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val possiblyBareType = typeResolver.resolveTypeForClassifier(
|
||||||
|
typeResolutionContext, classifier, qualifierResolutionResult, expression, Annotations.EMPTY
|
||||||
|
)
|
||||||
|
|
||||||
|
val type = if (possiblyBareType.isBare) {
|
||||||
|
val descriptor = possiblyBareType.bareTypeConstructor.declarationDescriptor as? ClassDescriptor
|
||||||
|
?: error("Only classes can produce bare types: $possiblyBareType")
|
||||||
|
|
||||||
|
KotlinTypeImpl.create(
|
||||||
|
Annotations.EMPTY, descriptor, possiblyBareType.isNullable || doubleColonExpression.hasQuestionMarks,
|
||||||
|
descriptor.typeConstructor.parameters.map(TypeUtils::makeStarProjection)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TypeUtils.makeNullableAsSpecified(possiblyBareType.actualType, doubleColonExpression.hasQuestionMarks)
|
||||||
|
}
|
||||||
|
|
||||||
|
return DoubleColonLHS.Type(type, possiblyBareType).apply {
|
||||||
|
c.trace.record(BindingContext.DOUBLE_COLON_LHS, expression, this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isAllowedInClassLiteral(type: KotlinType): Boolean {
|
private fun isAllowedInClassLiteral(type: KotlinType): Boolean {
|
||||||
@@ -122,11 +202,8 @@ class DoubleColonExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun visitCallableReferenceExpression(expression: KtCallableReferenceExpression, c: ExpressionTypingContext): KotlinTypeInfo {
|
fun visitCallableReferenceExpression(expression: KtCallableReferenceExpression, c: ExpressionTypingContext): KotlinTypeInfo {
|
||||||
val typeReference = expression.typeReference
|
val lhs = expression.receiverExpression?.let { resolveDoubleColonLHS(it, expression, c) }
|
||||||
|
val receiverType = lhs?.type // TODO: handle .Expression and .Type
|
||||||
val receiverType = typeReference?.let { typeReference ->
|
|
||||||
typeResolver.resolveType(c.scope, typeReference, c.trace, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
val callableReference = expression.callableReference
|
val callableReference = expression.callableReference
|
||||||
if (callableReference.getReferencedName().isEmpty()) {
|
if (callableReference.getReferencedName().isEmpty()) {
|
||||||
@@ -136,7 +213,7 @@ class DoubleColonExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val trace = TemporaryBindingTrace.create(c.trace, "Callable reference type")
|
val trace = TemporaryBindingTrace.create(c.trace, "Callable reference type")
|
||||||
val result = getCallableReferenceType(expression, receiverType, c.replaceBindingTrace(trace))
|
val result = getCallableReferenceType(expression, receiverType, lhs is DoubleColonLHS.Expression, c.replaceBindingTrace(trace))
|
||||||
val hasErrors = hasErrors(trace) // Do not inline this local variable (execution order is important)
|
val hasErrors = hasErrors(trace) // Do not inline this local variable (execution order is important)
|
||||||
trace.commit()
|
trace.commit()
|
||||||
if (!hasErrors && result != null) {
|
if (!hasErrors && result != null) {
|
||||||
@@ -181,6 +258,7 @@ class DoubleColonExpressionResolver(
|
|||||||
private fun getCallableReferenceType(
|
private fun getCallableReferenceType(
|
||||||
expression: KtCallableReferenceExpression,
|
expression: KtCallableReferenceExpression,
|
||||||
lhsType: KotlinType?,
|
lhsType: KotlinType?,
|
||||||
|
isBound: Boolean,
|
||||||
context: ExpressionTypingContext
|
context: ExpressionTypingContext
|
||||||
): KotlinType? {
|
): KotlinType? {
|
||||||
val reference = expression.callableReference
|
val reference = expression.callableReference
|
||||||
@@ -205,6 +283,7 @@ class DoubleColonExpressionResolver(
|
|||||||
context.trace.report(CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR.on(reference))
|
context.trace.report(CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR.on(reference))
|
||||||
}
|
}
|
||||||
|
|
||||||
return createReflectionTypeForResolvedCallableReference(expression, lhsType, descriptor, context, reflectionTypes)
|
val ignoreReceiver = isBound || expression.isEmptyLHS
|
||||||
|
return createReflectionTypeForResolvedCallableReference(expression, lhsType, ignoreReceiver, descriptor, context, reflectionTypes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// MODULE: m1
|
||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package a
|
||||||
|
|
||||||
|
class b {
|
||||||
|
class c
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m2
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
package a.b
|
||||||
|
|
||||||
|
class c {
|
||||||
|
fun foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m3(m1, m2)
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
fun test() = a.b.c::foo
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// -- Module: <m1> --
|
||||||
|
package
|
||||||
|
|
||||||
|
package a {
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
public final class c {
|
||||||
|
public constructor c()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Module: <m2> --
|
||||||
|
package
|
||||||
|
|
||||||
|
package a {
|
||||||
|
|
||||||
|
package a.b {
|
||||||
|
|
||||||
|
public final class c {
|
||||||
|
public constructor c()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun foo(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Module: <m3> --
|
||||||
|
package
|
||||||
|
|
||||||
|
package a {
|
||||||
|
|
||||||
|
public final class b {
|
||||||
|
// -- Module: <m1> --
|
||||||
|
}
|
||||||
|
|
||||||
|
package a.b {
|
||||||
|
|
||||||
|
public final class c {
|
||||||
|
// -- Module: <m2> --
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package test {
|
||||||
|
public fun test(): kotlin.reflect.KFunction1<a.b.c, kotlin.Unit>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_EXPRESSION
|
||||||
|
// FILE: simpleName.kt
|
||||||
|
|
||||||
|
package foo
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<!UNRESOLVED_REFERENCE!>foo<!>::test
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: qualifiedName.kt
|
||||||
|
|
||||||
|
package foo.bar
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo.<!UNRESOLVED_REFERENCE!>bar<!>::test
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
package foo {
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
|
|
||||||
|
package foo.bar {
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
fun <T> bar(x: Int) = x
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
Foo::<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar<!> <!SYNTAX!>< <!DEBUG_INFO_MISSING_UNRESOLVED!>Int<!> ><!> <!SYNTAX!>(2 <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 2)<!>
|
||||||
|
}
|
||||||
Vendored
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
package test {
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
|
|
||||||
|
public final class Foo {
|
||||||
|
public constructor Foo()
|
||||||
|
public final fun </*0*/ T> bar(/*0*/ x: kotlin.Int): kotlin.Int
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
// !CHECK_TYPE
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
|
||||||
|
fun Foo?.bar() {}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val r1 = Foo ?:: bar
|
||||||
|
checkSubtype<(Foo?) -> Unit>(r1)
|
||||||
|
|
||||||
|
val r2 = Foo ? :: bar
|
||||||
|
checkSubtype<(Foo?) -> Unit>(r2)
|
||||||
|
|
||||||
|
val r3 = Foo ? ? :: bar
|
||||||
|
checkSubtype<(Foo?) -> Unit>(r3)
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
|
public fun Foo?.bar(): kotlin.Unit
|
||||||
|
|
||||||
|
public final class Foo {
|
||||||
|
public constructor Foo()
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
class A
|
class A
|
||||||
|
|
||||||
val a1 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>A?::class<!>
|
val a1 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>A?::class<!>
|
||||||
val a2 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>A?<!REDUNDANT_NULLABLE!>?<!>::class<!>
|
val a2 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>A??::class<!>
|
||||||
|
|
||||||
val l1 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>List<String>?::class<!>
|
val l1 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>List<String>?::class<!>
|
||||||
val l2 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>List?::class<!>
|
val l2 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>List?::class<!>
|
||||||
|
|||||||
@@ -1653,6 +1653,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference"), Pattern.compile("^(.+)\\.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classVsPackage.kt")
|
||||||
|
public void testClassVsPackage() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/classVsPackage.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ea81649_errorPropertyLHS.kt")
|
@TestMetadata("ea81649_errorPropertyLHS.kt")
|
||||||
public void testEa81649_errorPropertyLHS() throws Exception {
|
public void testEa81649_errorPropertyLHS() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/ea81649_errorPropertyLHS.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/ea81649_errorPropertyLHS.kt");
|
||||||
@@ -1677,12 +1683,30 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("packageInLhs.kt")
|
||||||
|
public void testPackageInLhs() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/packageInLhs.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("parsingPriorityOfGenericArgumentsVsLess.kt")
|
||||||
|
public void testParsingPriorityOfGenericArgumentsVsLess() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/parsingPriorityOfGenericArgumentsVsLess.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unused.kt")
|
@TestMetadata("unused.kt")
|
||||||
public void testUnused() throws Exception {
|
public void testUnused() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/unused.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/unused.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("whitespacesInExpression.kt")
|
||||||
|
public void testWhitespacesInExpression() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/whitespacesInExpression.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/callableReference/function")
|
@TestMetadata("compiler/testData/diagnostics/tests/callableReference/function")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user