New J2K: use nullable type for unknown for public declarations & prepare for mutability inference
#KT-32518 fixed
This commit is contained in:
@@ -46,7 +46,7 @@ class KtClassBody : KtElementImplStub<KotlinPlaceHolderStub<KtClassBody>>, KtDec
|
|||||||
val properties: List<KtProperty>
|
val properties: List<KtProperty>
|
||||||
get() = getStubOrPsiChildrenAsList(KtStubElementTypes.PROPERTY)
|
get() = getStubOrPsiChildrenAsList(KtStubElementTypes.PROPERTY)
|
||||||
|
|
||||||
val functions: List<KtFunction>
|
val functions: List<KtNamedFunction>
|
||||||
get() = getStubOrPsiChildrenAsList(KtStubElementTypes.FUNCTION)
|
get() = getStubOrPsiChildrenAsList(KtStubElementTypes.FUNCTION)
|
||||||
|
|
||||||
val enumEntries: List<KtEnumEntry>
|
val enumEntries: List<KtEnumEntry>
|
||||||
|
|||||||
+33
-27
@@ -36,37 +36,41 @@ interface BoundTypeCalculator {
|
|||||||
): BoundType
|
): BoundType
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoundTypeCalculatorImpl(
|
open class BoundTypeCalculatorImpl(
|
||||||
private val resolutionFacade: ResolutionFacade,
|
private val resolutionFacade: ResolutionFacade,
|
||||||
private val enhancer: BoundTypeEnhancer
|
private val enhancer: BoundTypeEnhancer
|
||||||
) : BoundTypeCalculator {
|
) : BoundTypeCalculator {
|
||||||
private val cache = mutableMapOf<KtExpression, BoundType>()
|
private val cache = mutableMapOf<KtExpression, BoundType>()
|
||||||
|
|
||||||
override fun expressionsWithBoundType() = cache.toList()
|
final override fun expressionsWithBoundType() = cache.toList()
|
||||||
|
|
||||||
override fun KtExpression.boundType(inferenceContext: InferenceContext): BoundType = cache.getOrPut(this) {
|
final override fun KtExpression.boundType(inferenceContext: InferenceContext): BoundType = cache.getOrPut(this) {
|
||||||
calculateBoundType(inferenceContext, this)
|
calculateBoundType(inferenceContext, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateBoundType(inferenceContext: InferenceContext, expression: KtExpression): BoundType = when {
|
open fun interceptCalculateBoundType(inferenceContext: InferenceContext, expression: KtExpression): BoundType? =
|
||||||
expression.isNullExpression() -> BoundType.NULL
|
null
|
||||||
expression is KtParenthesizedExpression -> expression.expression?.boundType(inferenceContext)
|
|
||||||
expression is KtConstantExpression
|
private fun calculateBoundType(inferenceContext: InferenceContext, expression: KtExpression): BoundType =
|
||||||
|| expression is KtStringTemplateExpression
|
interceptCalculateBoundType(inferenceContext, expression) ?: when {
|
||||||
|| expression.node?.elementType == KtNodeTypes.BOOLEAN_CONSTANT
|
expression.isNullExpression() -> BoundType.NULL
|
||||||
|| expression is KtBinaryExpression ->
|
expression is KtParenthesizedExpression -> expression.expression?.boundType(inferenceContext)
|
||||||
BoundType.LITERAL
|
expression is KtConstantExpression
|
||||||
expression is KtQualifiedExpression -> expression.toBoundTypeAsQualifiedExpression(inferenceContext)
|
|| expression is KtStringTemplateExpression
|
||||||
expression is KtBinaryExpressionWithTypeRHS -> expression.toBoundTypeAsCastExpression(inferenceContext)
|
|| expression.node?.elementType == KtNodeTypes.BOOLEAN_CONSTANT
|
||||||
expression is KtNameReferenceExpression -> expression.toBoundTypeAsReferenceExpression(inferenceContext)
|
|| expression is KtBinaryExpression ->
|
||||||
expression is KtCallExpression -> expression.toBoundTypeAsCallableExpression(null, inferenceContext)
|
BoundType.LITERAL
|
||||||
expression is KtLambdaExpression -> expression.toBoundTypeAsLambdaExpression(inferenceContext)
|
expression is KtQualifiedExpression -> expression.toBoundTypeAsQualifiedExpression(inferenceContext)
|
||||||
expression is KtLabeledExpression -> expression.baseExpression?.boundType(inferenceContext)
|
expression is KtBinaryExpressionWithTypeRHS -> expression.toBoundTypeAsCastExpression(inferenceContext)
|
||||||
expression is KtIfExpression -> expression.toBoundTypeAsIfExpression(inferenceContext)
|
expression is KtNameReferenceExpression -> expression.toBoundTypeAsReferenceExpression(inferenceContext)
|
||||||
else -> null
|
expression is KtCallExpression -> expression.toBoundTypeAsCallableExpression(null, inferenceContext)
|
||||||
}?.let { boundType ->
|
expression is KtLambdaExpression -> expression.toBoundTypeAsLambdaExpression(inferenceContext)
|
||||||
enhancer.enhance(expression, boundType, inferenceContext)
|
expression is KtLabeledExpression -> expression.baseExpression?.boundType(inferenceContext)
|
||||||
} ?: BoundType.LITERAL
|
expression is KtIfExpression -> expression.toBoundTypeAsIfExpression(inferenceContext)
|
||||||
|
else -> null
|
||||||
|
}?.let { boundType ->
|
||||||
|
enhancer.enhance(expression, boundType, inferenceContext)
|
||||||
|
} ?: BoundType.LITERAL
|
||||||
|
|
||||||
private fun KtIfExpression.toBoundTypeAsIfExpression(inferenceContext: InferenceContext): BoundType? {
|
private fun KtIfExpression.toBoundTypeAsIfExpression(inferenceContext: InferenceContext): BoundType? {
|
||||||
val isNullLiteralPossible = then?.isNullExpression() == true || `else`?.isNullExpression() == true
|
val isNullLiteralPossible = then?.isNullExpression() == true || `else`?.isNullExpression() == true
|
||||||
@@ -166,7 +170,7 @@ class BoundTypeCalculatorImpl(
|
|||||||
return selectorExpression.toBoundTypeAsCallableExpression(receiverBoundType, inferenceContext)
|
return selectorExpression.toBoundTypeAsCallableExpression(receiverBoundType, inferenceContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun KotlinType.boundType(
|
final override fun KotlinType.boundType(
|
||||||
typeVariable: TypeVariable?,
|
typeVariable: TypeVariable?,
|
||||||
contextBoundType: BoundType?,
|
contextBoundType: BoundType?,
|
||||||
call: ResolvedCall<*>?,
|
call: ResolvedCall<*>?,
|
||||||
@@ -220,8 +224,9 @@ class BoundTypeCalculatorImpl(
|
|||||||
when {
|
when {
|
||||||
containingDeclaration == call?.candidateDescriptor?.original -> {
|
containingDeclaration == call?.candidateDescriptor?.original -> {
|
||||||
val returnTypeVariable = inferenceContext.typeElementToTypeVariable[
|
val returnTypeVariable = inferenceContext.typeElementToTypeVariable[
|
||||||
call.call.typeArguments.getOrNull(target.index)?.typeReference?.typeElement ?: return null
|
call.call.typeArguments.getOrNull(target.index)?.typeReference?.typeElement
|
||||||
] ?: return null
|
?: return BoundType.STAR_PROJECTION
|
||||||
|
] ?: return BoundType.STAR_PROJECTION
|
||||||
BoundTypeImpl(
|
BoundTypeImpl(
|
||||||
TypeVariableLabel(returnTypeVariable),
|
TypeVariableLabel(returnTypeVariable),
|
||||||
returnTypeVariable.typeParameters
|
returnTypeVariable.typeParameters
|
||||||
@@ -238,8 +243,9 @@ class BoundTypeCalculatorImpl(
|
|||||||
// `this` or `super` call case
|
// `this` or `super` call case
|
||||||
containingDeclaration == call?.candidateDescriptor.safeAs<ConstructorDescriptor>()?.constructedClass -> {
|
containingDeclaration == call?.candidateDescriptor.safeAs<ConstructorDescriptor>()?.constructedClass -> {
|
||||||
val returnTypeVariable = inferenceContext.typeElementToTypeVariable[
|
val returnTypeVariable = inferenceContext.typeElementToTypeVariable[
|
||||||
call?.call?.typeArguments?.getOrNull(target.index)?.typeReference?.typeElement ?: return null
|
call?.call?.typeArguments?.getOrNull(target.index)?.typeReference?.typeElement
|
||||||
] ?: return null
|
?: return BoundType.STAR_PROJECTION
|
||||||
|
] ?: return BoundType.STAR_PROJECTION
|
||||||
BoundTypeImpl(
|
BoundTypeImpl(
|
||||||
TypeVariableLabel(returnTypeVariable),
|
TypeVariableLabel(returnTypeVariable),
|
||||||
returnTypeVariable.typeParameters
|
returnTypeVariable.typeParameters
|
||||||
|
|||||||
@@ -54,28 +54,8 @@ class LiteralBound private constructor(val state: State) : ConstraintBound() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val TypeVariable.constraintBound: TypeVariableBound
|
fun State.constraintBound(): LiteralBound = when (this) {
|
||||||
get() = TypeVariableBound(this)
|
State.LOWER -> LiteralBound.LOWER
|
||||||
|
State.UPPER -> LiteralBound.UPPER
|
||||||
val State.constraintBound: LiteralBound
|
State.UNKNOWN -> LiteralBound.UNKNOWN
|
||||||
get() = when (this) {
|
}
|
||||||
State.LOWER -> LiteralBound.LOWER
|
|
||||||
State.UPPER -> LiteralBound.UPPER
|
|
||||||
State.UNKNOWN -> LiteralBound.UNKNOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
val BoundTypeLabel.constraintBound: ConstraintBound?
|
|
||||||
get() = when (this) {
|
|
||||||
is TypeVariableLabel -> typeVariable.constraintBound
|
|
||||||
is TypeParameterLabel -> null
|
|
||||||
is GenericLabel -> null
|
|
||||||
StarProjectionLabel -> null
|
|
||||||
NullLiteralLabel -> LiteralBound.UPPER
|
|
||||||
LiteralLabel -> LiteralBound.LOWER
|
|
||||||
}
|
|
||||||
|
|
||||||
val BoundType.constraintBound: ConstraintBound?
|
|
||||||
get() = when (this) {
|
|
||||||
is BoundTypeImpl -> label.constraintBound
|
|
||||||
is WithForcedStateBoundType -> forcedState.constraintBound
|
|
||||||
}
|
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.nj2k.inference.common
|
||||||
|
|
||||||
|
interface ConstraintBoundProvider {
|
||||||
|
fun TypeVariable.constraintBound(): TypeVariableBound
|
||||||
|
fun BoundType.constraintBound(): ConstraintBound?
|
||||||
|
fun BoundTypeLabel.constraintBound(): ConstraintBound?
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ConstraintBoundProviderImpl : ConstraintBoundProvider {
|
||||||
|
final override fun TypeVariable.constraintBound(): TypeVariableBound =
|
||||||
|
TypeVariableBound(this)
|
||||||
|
|
||||||
|
final override fun BoundType.constraintBound(): ConstraintBound? = when (this) {
|
||||||
|
is BoundTypeImpl -> label.constraintBound()
|
||||||
|
is WithForcedStateBoundType -> forcedState.constraintBound()
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-7
@@ -13,8 +13,9 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class ConstraintBuilder(
|
class ConstraintBuilder(
|
||||||
private val inferenceContext: InferenceContext,
|
private val inferenceContext: InferenceContext,
|
||||||
private val boundTypeCalculator: BoundTypeCalculator
|
private val boundTypeCalculator: BoundTypeCalculator,
|
||||||
) : BoundTypeCalculator by boundTypeCalculator {
|
private val constraintBoundProvider: ConstraintBoundProvider
|
||||||
|
) : BoundTypeCalculator by boundTypeCalculator, ConstraintBoundProvider by constraintBoundProvider {
|
||||||
private val constraints = mutableListOf<Constraint>()
|
private val constraints = mutableListOf<Constraint>()
|
||||||
|
|
||||||
fun TypeVariable.isSubtypeOf(supertype: BoundType, priority: ConstraintPriority) {
|
fun TypeVariable.isSubtypeOf(supertype: BoundType, priority: ConstraintPriority) {
|
||||||
@@ -39,7 +40,7 @@ class ConstraintBuilder(
|
|||||||
|
|
||||||
fun KtExpression.isTheSameTypeAs(other: State, priority: ConstraintPriority) {
|
fun KtExpression.isTheSameTypeAs(other: State, priority: ConstraintPriority) {
|
||||||
boundType().label.safeAs<TypeVariableLabel>()?.typeVariable?.let { typeVariable ->
|
boundType().label.safeAs<TypeVariableLabel>()?.typeVariable?.let { typeVariable ->
|
||||||
constraints += EqualsConstraint(typeVariable.constraintBound, other.constraintBound, priority)
|
constraints += EqualsConstraint(typeVariable.constraintBound(), other.constraintBound(), priority)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +105,8 @@ class ConstraintBuilder(
|
|||||||
|
|
||||||
if (typeVariable !in ignoreTypeVariables && other.typeVariable !in ignoreTypeVariables) {
|
if (typeVariable !in ignoreTypeVariables && other.typeVariable !in ignoreTypeVariables) {
|
||||||
constraints += EqualsConstraint(
|
constraints += EqualsConstraint(
|
||||||
constraintBound ?: return,
|
constraintBound() ?: return,
|
||||||
other.constraintBound ?: return,
|
other.constraintBound() ?: return,
|
||||||
priority
|
priority
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -121,8 +122,8 @@ class ConstraintBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
constraints += SubtypeConstraint(
|
constraints += SubtypeConstraint(
|
||||||
constraintBound ?: return,
|
constraintBound() ?: return,
|
||||||
supertype.constraintBound ?: return,
|
supertype.constraintBound() ?: return,
|
||||||
priority
|
priority
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -14,14 +14,15 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
|||||||
|
|
||||||
class ConstraintsCollectorAggregator(
|
class ConstraintsCollectorAggregator(
|
||||||
private val resolutionFacade: ResolutionFacade,
|
private val resolutionFacade: ResolutionFacade,
|
||||||
private val collectors: List<ConstraintsCollector>
|
private val constraintBoundProvider: ConstraintBoundProvider,
|
||||||
|
val collectors: List<ConstraintsCollector>
|
||||||
) {
|
) {
|
||||||
fun collectConstraints(
|
fun collectConstraints(
|
||||||
boundTypeCalculator: BoundTypeCalculator,
|
boundTypeCalculator: BoundTypeCalculator,
|
||||||
inferenceContext: InferenceContext,
|
inferenceContext: InferenceContext,
|
||||||
elements: List<KtElement>
|
elements: List<KtElement>
|
||||||
): List<Constraint> {
|
): List<Constraint> {
|
||||||
val constraintsBuilder = ConstraintBuilder(inferenceContext, boundTypeCalculator)
|
val constraintsBuilder = ConstraintBuilder(inferenceContext, boundTypeCalculator, constraintBoundProvider)
|
||||||
for (element in elements) {
|
for (element in elements) {
|
||||||
element.forEachDescendantOfType<KtElement> { innerElement ->
|
element.forEachDescendantOfType<KtElement> { innerElement ->
|
||||||
if (innerElement.getStrictParentOfType<KtImportDirective>() != null) return@forEachDescendantOfType
|
if (innerElement.getStrictParentOfType<KtImportDirective>() != null) return@forEachDescendantOfType
|
||||||
|
|||||||
+36
-22
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
|||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -29,13 +30,13 @@ abstract class ContextCollector(private val resolutionFacade: ResolutionFacade)
|
|||||||
private fun KtTypeReference.classReference(): ClassReference? =
|
private fun KtTypeReference.classReference(): ClassReference? =
|
||||||
analyze()[BindingContext.TYPE, this]?.classReference()
|
analyze()[BindingContext.TYPE, this]?.classReference()
|
||||||
|
|
||||||
private fun KtTypeElement.toData(): TypeElementData {
|
private fun KtTypeElement.toData(): TypeElementData? {
|
||||||
val typeReference = parent as? KtTypeReference ?: return TypeElementDataImpl(this)
|
val typeReference = parent as? KtTypeReference ?: return null
|
||||||
val typeParameterDescriptor = analyze(resolutionFacade)[BindingContext.TYPE, typeReference]
|
val type = analyze(resolutionFacade)[BindingContext.TYPE, typeReference] ?: return null
|
||||||
?.constructor
|
val typeParameterDescriptor = type.constructor
|
||||||
?.declarationDescriptor
|
.declarationDescriptor
|
||||||
?.safeAs<TypeParameterDescriptor>() ?: return TypeElementDataImpl(this)
|
?.safeAs<TypeParameterDescriptor>() ?: return TypeElementDataImpl(this, type)
|
||||||
return TypeParameterElementData(this, typeParameterDescriptor)
|
return TypeParameterElementData(this, type, typeParameterDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun collectTypeVariables(elements: List<KtElement>): InferenceContext {
|
fun collectTypeVariables(elements: List<KtElement>): InferenceContext {
|
||||||
@@ -43,7 +44,7 @@ abstract class ContextCollector(private val resolutionFacade: ResolutionFacade)
|
|||||||
val typeElementToTypeVariable = mutableMapOf<KtTypeElement, TypeVariable>()
|
val typeElementToTypeVariable = mutableMapOf<KtTypeElement, TypeVariable>()
|
||||||
val typeBasedTypeVariables = mutableListOf<TypeBasedTypeVariable>()
|
val typeBasedTypeVariables = mutableListOf<TypeBasedTypeVariable>()
|
||||||
|
|
||||||
fun KtTypeReference.toBoundType(defaultState: State? = null): BoundType? {
|
fun KtTypeReference.toBoundType(owner: TypeVariableOwner, defaultState: State? = null): BoundType? {
|
||||||
val typeElement = typeElement ?: return null
|
val typeElement = typeElement ?: return null
|
||||||
val classReference = classReference() ?: NoClassReference
|
val classReference = classReference() ?: NoClassReference
|
||||||
|
|
||||||
@@ -58,9 +59,7 @@ abstract class ContextCollector(private val resolutionFacade: ResolutionFacade)
|
|||||||
classReference.descriptor.declaredTypeParameters
|
classReference.descriptor.declaredTypeParameters
|
||||||
) { typeArgument, typeParameter ->
|
) { typeArgument, typeParameter ->
|
||||||
TypeParameter(
|
TypeParameter(
|
||||||
if (typeArgument == null) {
|
typeArgument?.toBoundType(owner) ?: BoundType.STAR_PROJECTION,
|
||||||
BoundTypeImpl(StarProjectionLabel, emptyList())
|
|
||||||
} else typeArgument.toBoundType() ?: BoundType.STAR_PROJECTION,
|
|
||||||
typeParameter.variance
|
typeParameter.variance
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -75,7 +74,8 @@ abstract class ContextCollector(private val resolutionFacade: ResolutionFacade)
|
|||||||
val typeVariable = TypeElementBasedTypeVariable(
|
val typeVariable = TypeElementBasedTypeVariable(
|
||||||
classReference,
|
classReference,
|
||||||
typeArguments,
|
typeArguments,
|
||||||
typeElement.toData(),
|
typeElement.toData() ?: return null,
|
||||||
|
owner,
|
||||||
state
|
state
|
||||||
)
|
)
|
||||||
typeElementToTypeVariable[typeElement] = typeVariable
|
typeElementToTypeVariable[typeElement] = typeVariable
|
||||||
@@ -116,6 +116,12 @@ abstract class ContextCollector(private val resolutionFacade: ResolutionFacade)
|
|||||||
|
|
||||||
val substitutors = mutableMapOf<ClassDescriptor, ClassSubstitutor>()
|
val substitutors = mutableMapOf<ClassDescriptor, ClassSubstitutor>()
|
||||||
|
|
||||||
|
fun isOrAsExpression(typeReference: KtTypeReference) {
|
||||||
|
val typeElement = typeReference.typeElement ?: return
|
||||||
|
val typeVariable = typeReference.toBoundType(OtherTarget)?.typeVariable ?: return
|
||||||
|
typeElementToTypeVariable[typeElement] = typeVariable
|
||||||
|
}
|
||||||
|
|
||||||
for (element in elements) {
|
for (element in elements) {
|
||||||
element.forEachDescendantOfType<KtExpression> { expression ->
|
element.forEachDescendantOfType<KtExpression> { expression ->
|
||||||
if (expression is KtCallableDeclaration
|
if (expression is KtCallableDeclaration
|
||||||
@@ -124,24 +130,31 @@ abstract class ContextCollector(private val resolutionFacade: ResolutionFacade)
|
|||||||
|| expression is KtNamedFunction)
|
|| expression is KtNamedFunction)
|
||||||
) run {
|
) run {
|
||||||
val typeReference = expression.typeReference ?: return@run
|
val typeReference = expression.typeReference ?: return@run
|
||||||
val typeVariable = typeReference.toBoundType()?.typeVariable ?: return@run
|
val typeVariable = typeReference.toBoundType(
|
||||||
|
when (expression) {
|
||||||
|
is KtParameter -> expression.getStrictParentOfType<KtFunction>()?.let(::FunctionParameter)
|
||||||
|
is KtFunction -> FunctionReturnType(expression)
|
||||||
|
is KtProperty -> Property(expression)
|
||||||
|
else -> null
|
||||||
|
} ?: OtherTarget
|
||||||
|
)?.typeVariable ?: return@run
|
||||||
declarationToTypeVariable[expression] = typeVariable
|
declarationToTypeVariable[expression] = typeVariable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expression is KtTypeParameterListOwner) {
|
if (expression is KtTypeParameterListOwner) {
|
||||||
for (typeParameter in expression.typeParameters) {
|
for (typeParameter in expression.typeParameters) {
|
||||||
typeParameter.extendsBound?.toBoundType(defaultState = State.UPPER)
|
typeParameter.extendsBound?.toBoundType(OtherTarget, defaultState = State.UPPER)
|
||||||
}
|
}
|
||||||
for (constraint in expression.typeConstraints) {
|
for (constraint in expression.typeConstraints) {
|
||||||
constraint.boundTypeReference?.toBoundType(defaultState = State.UPPER)
|
constraint.boundTypeReference?.toBoundType(OtherTarget, defaultState = State.UPPER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
when (expression) {
|
when (expression) {
|
||||||
is KtClass -> {
|
is KtClassOrObject -> {
|
||||||
for (entry in expression.superTypeListEntries) {
|
for (entry in expression.superTypeListEntries) {
|
||||||
for (argument in entry.typeReference?.typeElement?.typeArgumentsAsTypes ?: continue) {
|
for (argument in entry.typeReference?.typeElement?.typeArgumentsAsTypes ?: continue) {
|
||||||
argument.toBoundType()
|
argument.toBoundType(OtherTarget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val descriptor =
|
val descriptor =
|
||||||
@@ -160,7 +173,7 @@ abstract class ContextCollector(private val resolutionFacade: ResolutionFacade)
|
|||||||
}
|
}
|
||||||
is KtCallExpression ->
|
is KtCallExpression ->
|
||||||
for (typeArgument in expression.typeArguments) {
|
for (typeArgument in expression.typeArguments) {
|
||||||
typeArgument.typeReference?.toBoundType()
|
typeArgument.typeReference?.toBoundType(TypeArgument)
|
||||||
}
|
}
|
||||||
is KtLambdaExpression -> {
|
is KtLambdaExpression -> {
|
||||||
val context = expression.analyze(resolutionFacade)
|
val context = expression.analyze(resolutionFacade)
|
||||||
@@ -169,10 +182,11 @@ abstract class ContextCollector(private val resolutionFacade: ResolutionFacade)
|
|||||||
declarationToTypeVariable[expression.functionLiteral] = typeVariable
|
declarationToTypeVariable[expression.functionLiteral] = typeVariable
|
||||||
}
|
}
|
||||||
is KtBinaryExpressionWithTypeRHS -> {
|
is KtBinaryExpressionWithTypeRHS -> {
|
||||||
val typeReference = expression.right ?: return@forEachDescendantOfType
|
isOrAsExpression(expression.right ?: return@forEachDescendantOfType)
|
||||||
val typeElement = typeReference.typeElement ?: return@forEachDescendantOfType
|
|
||||||
val typeVariable = typeReference.toBoundType()?.typeVariable ?: return@forEachDescendantOfType
|
}
|
||||||
typeElementToTypeVariable[typeElement] = typeVariable
|
is KtIsExpression -> {
|
||||||
|
isOrAsExpression(expression.typeReference ?: return@forEachDescendantOfType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.nj2k.inference.common
|
||||||
|
|
||||||
|
abstract class DefaultStateProvider {
|
||||||
|
abstract fun defaultStateFor(typeVariable: TypeVariable): State
|
||||||
|
}
|
||||||
+2
-1
@@ -14,6 +14,7 @@ class InferenceFacade(
|
|||||||
private val constraintsCollectorAggregator: ConstraintsCollectorAggregator,
|
private val constraintsCollectorAggregator: ConstraintsCollectorAggregator,
|
||||||
private val boundTypeCalculator: BoundTypeCalculator,
|
private val boundTypeCalculator: BoundTypeCalculator,
|
||||||
private val stateUpdater: StateUpdater,
|
private val stateUpdater: StateUpdater,
|
||||||
|
private val defaultStateProvider: DefaultStateProvider,
|
||||||
private val renderDebugTypes: Boolean = false,
|
private val renderDebugTypes: Boolean = false,
|
||||||
private val printDebugConstraints: Boolean = false
|
private val printDebugConstraints: Boolean = false
|
||||||
) {
|
) {
|
||||||
@@ -22,7 +23,7 @@ class InferenceFacade(
|
|||||||
val constraints = constraintsCollectorAggregator.collectConstraints(boundTypeCalculator, inferenceContext, elements)
|
val constraints = constraintsCollectorAggregator.collectConstraints(boundTypeCalculator, inferenceContext, elements)
|
||||||
|
|
||||||
val initialConstraints = if (renderDebugTypes) constraints.map { it.copy() } else null
|
val initialConstraints = if (renderDebugTypes) constraints.map { it.copy() } else null
|
||||||
Solver(inferenceContext, printDebugConstraints).solveConstraints(constraints)
|
Solver(inferenceContext, printDebugConstraints, defaultStateProvider).solveConstraints(constraints)
|
||||||
|
|
||||||
if (renderDebugTypes) {
|
if (renderDebugTypes) {
|
||||||
with(DebugPrinter(inferenceContext)) {
|
with(DebugPrinter(inferenceContext)) {
|
||||||
|
|||||||
@@ -5,15 +5,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.nj2k.inference.common
|
package org.jetbrains.kotlin.nj2k.inference.common
|
||||||
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
|
|
||||||
internal class Solver(
|
internal class Solver(
|
||||||
private val analysisContext: InferenceContext,
|
private val inferenceContext: InferenceContext,
|
||||||
private val printConstraints: Boolean
|
private val printConstraints: Boolean,
|
||||||
|
private val defaultStateProvider: DefaultStateProvider
|
||||||
) {
|
) {
|
||||||
private val printer = DebugPrinter(analysisContext)
|
private val printer = DebugPrinter(inferenceContext)
|
||||||
|
|
||||||
private fun List<Constraint>.printDebugInfo(step: Int) =
|
private fun List<Constraint>.printDebugInfo(step: Int) =
|
||||||
with(printer) {
|
with(printer) {
|
||||||
@@ -24,7 +24,7 @@ internal class Solver(
|
|||||||
}
|
}
|
||||||
println()
|
println()
|
||||||
println("type variables:")
|
println("type variables:")
|
||||||
for (typeVariable in analysisContext.typeVariables) {
|
for (typeVariable in inferenceContext.typeVariables) {
|
||||||
println("${typeVariable.name} := ${typeVariable.state}")
|
println("${typeVariable.name} := ${typeVariable.state}")
|
||||||
}
|
}
|
||||||
println("---------------\n")
|
println("---------------\n")
|
||||||
@@ -55,9 +55,11 @@ internal class Solver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!somethingChanged) {
|
if (!somethingChanged) {
|
||||||
val typeVariable = mutableConstraints.getTypeVariableAsEqualsOrUpperBound()
|
val typeVariable =
|
||||||
|
mutableConstraints.getTypeVariableAsEqualsOrUpperBound()
|
||||||
|
?: inferenceContext.typeVariables.firstOrNull { !it.isFixed }
|
||||||
if (typeVariable != null) {
|
if (typeVariable != null) {
|
||||||
typeVariable.setStateIfNotFixed(State.LOWER)
|
typeVariable.setStateIfNotFixed(defaultStateProvider.defaultStateFor(typeVariable))
|
||||||
somethingChanged = true
|
somethingChanged = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,11 +144,11 @@ internal class Solver(
|
|||||||
val (lower, upper) = constraint
|
val (lower, upper) = constraint
|
||||||
if (lower is TypeVariableBound && lower.typeVariable.isFixed) {
|
if (lower is TypeVariableBound && lower.typeVariable.isFixed) {
|
||||||
somethingChanged = true
|
somethingChanged = true
|
||||||
constraint.subtype = lower.typeVariable.state.constraintBound
|
constraint.subtype = lower.typeVariable.state.constraintBound()
|
||||||
}
|
}
|
||||||
if (upper is TypeVariableBound && upper.typeVariable.isFixed) {
|
if (upper is TypeVariableBound && upper.typeVariable.isFixed) {
|
||||||
somethingChanged = true
|
somethingChanged = true
|
||||||
constraint.supertype = upper.typeVariable.state.constraintBound
|
constraint.supertype = upper.typeVariable.state.constraintBound()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,14 +168,27 @@ internal class Solver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun List<Constraint>.getTypeVariableAsEqualsOrUpperBound(): TypeVariable? =
|
private fun List<Constraint>.getTypeVariableAsEqualsOrUpperBound(): TypeVariable? {
|
||||||
asSequence().filterIsInstance<SubtypeConstraint>()
|
for (constraint in this) {
|
||||||
.map { it.supertype }
|
when (constraint) {
|
||||||
.firstIsInstanceOrNull<TypeVariableBound>()
|
is SubtypeConstraint -> {
|
||||||
?.typeVariable
|
constraint.supertype.safeAs<TypeVariableBound>()
|
||||||
?: asSequence().filterIsInstance<EqualsConstraint>()
|
?.typeVariable
|
||||||
.flatMap { sequenceOf(it.left, it.right) }
|
?.takeIf { defaultStateProvider.defaultStateFor(it) == State.LOWER }
|
||||||
.firstIsInstanceOrNull<TypeVariableBound>()
|
?.let { return it }
|
||||||
?.typeVariable
|
constraint.subtype.safeAs<TypeVariableBound>()
|
||||||
|
?.typeVariable
|
||||||
|
?.takeIf { defaultStateProvider.defaultStateFor(it) == State.UPPER }
|
||||||
|
?.let { return it }
|
||||||
|
}
|
||||||
|
is EqualsConstraint -> {
|
||||||
|
(constraint.left.safeAs<TypeVariableBound>()
|
||||||
|
?: constraint.right.safeAs())
|
||||||
|
?.let { return it.typeVariable }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,23 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.nj2k.inference.common
|
package org.jetbrains.kotlin.nj2k.inference.common
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
|
|
||||||
abstract class StateUpdater {
|
abstract class StateUpdater {
|
||||||
abstract fun updateStates(inferenceContext: InferenceContext)
|
fun updateStates(inferenceContext: InferenceContext) {
|
||||||
|
if (inferenceContext.typeVariables.isEmpty()) return
|
||||||
|
|
||||||
|
val deepComparator = Comparator<TypeElementBasedTypeVariable> { o1, o2 ->
|
||||||
|
if (o1.typeElement.typeElement.isAncestor(o2.typeElement.typeElement)) 1 else -1
|
||||||
|
}
|
||||||
|
for (typeVariable in inferenceContext
|
||||||
|
.typeVariables
|
||||||
|
.filterIsInstance<TypeElementBasedTypeVariable>()
|
||||||
|
.sortedWith(deepComparator)
|
||||||
|
) {
|
||||||
|
typeVariable.updateState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun TypeElementBasedTypeVariable.updateState()
|
||||||
}
|
}
|
||||||
+3
-3
@@ -96,10 +96,10 @@ class CallExpressionConstraintCollector : ConstraintsCollector() {
|
|||||||
BoundTypeImpl(
|
BoundTypeImpl(
|
||||||
GenericLabel(NoClassReference),//not important as it just a primitive type
|
GenericLabel(NoClassReference),//not important as it just a primitive type
|
||||||
emptyList()
|
emptyList()
|
||||||
) else parameterBoundType.typeParameters[0].boundType
|
) else parameterBoundType.typeParameters.getOrNull(0)?.boundType
|
||||||
} else parameterBoundType
|
} else parameterBoundType
|
||||||
arguments.arguments.map { argument ->
|
arguments.arguments.mapNotNull { argument ->
|
||||||
parameterBoundTypeConsideringVararg to argument
|
parameterBoundTypeConsideringVararg?.let { it to argument }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.flatten()
|
}.flatten()
|
||||||
|
|||||||
+27
-47
@@ -6,81 +6,61 @@
|
|||||||
package org.jetbrains.kotlin.nj2k.inference.common
|
package org.jetbrains.kotlin.nj2k.inference.common
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.isAbstract
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.KtFunction
|
||||||
|
import org.jetbrains.kotlin.psi.KtProperty
|
||||||
import org.jetbrains.kotlin.psi.KtTypeElement
|
import org.jetbrains.kotlin.psi.KtTypeElement
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
sealed class TypeVariable {
|
sealed class TypeVariable {
|
||||||
abstract val classReference: ClassReference
|
abstract val classReference: ClassReference
|
||||||
abstract val typeParameters: List<TypeParameter>
|
abstract val typeParameters: List<TypeParameter>
|
||||||
|
abstract val owner: TypeVariableOwner
|
||||||
abstract var state: State
|
abstract var state: State
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class TypeVariableOwner
|
||||||
|
|
||||||
|
class FunctionParameter(val owner: KtFunction) : TypeVariableOwner()
|
||||||
|
class FunctionReturnType(val function: KtFunction) : TypeVariableOwner()
|
||||||
|
class Property(val property: KtProperty) : TypeVariableOwner()
|
||||||
|
object TypeArgument : TypeVariableOwner()
|
||||||
|
object OtherTarget : TypeVariableOwner()
|
||||||
|
|
||||||
|
|
||||||
sealed class TypeElementData {
|
sealed class TypeElementData {
|
||||||
abstract val typeElement: KtTypeElement
|
abstract val typeElement: KtTypeElement
|
||||||
|
abstract val type: KotlinType
|
||||||
}
|
}
|
||||||
|
|
||||||
data class TypeElementDataImpl(override val typeElement: KtTypeElement) : TypeElementData()
|
data class TypeElementDataImpl(
|
||||||
|
override val typeElement: KtTypeElement,
|
||||||
|
override val type: KotlinType
|
||||||
|
) : TypeElementData()
|
||||||
|
|
||||||
data class TypeParameterElementData(
|
data class TypeParameterElementData(
|
||||||
override val typeElement: KtTypeElement,
|
override val typeElement: KtTypeElement,
|
||||||
|
override val type: KotlinType,
|
||||||
val typeParameterDescriptor: TypeParameterDescriptor
|
val typeParameterDescriptor: TypeParameterDescriptor
|
||||||
) : TypeElementData()
|
) : TypeElementData()
|
||||||
|
|
||||||
data class TypeElementBasedTypeVariable(
|
class TypeElementBasedTypeVariable(
|
||||||
override val classReference: ClassReference,
|
override val classReference: ClassReference,
|
||||||
override val typeParameters: List<TypeParameter>,
|
override val typeParameters: List<TypeParameter>,
|
||||||
val typeElement: TypeElementData,
|
val typeElement: TypeElementData,
|
||||||
|
override val owner: TypeVariableOwner,
|
||||||
override var state: State
|
override var state: State
|
||||||
) : TypeVariable() {
|
) : TypeVariable()
|
||||||
|
|
||||||
//ignore state as it is mutable
|
class TypeBasedTypeVariable(
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (javaClass != other?.javaClass) return false
|
|
||||||
|
|
||||||
other as TypeElementBasedTypeVariable
|
|
||||||
|
|
||||||
if (classReference != other.classReference) return false
|
|
||||||
if (typeParameters != other.typeParameters) return false
|
|
||||||
if (typeElement != other.typeElement) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var result = classReference.hashCode()
|
|
||||||
result = 31 * result + typeParameters.hashCode()
|
|
||||||
result = 31 * result + typeElement.hashCode()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class TypeBasedTypeVariable(
|
|
||||||
override val classReference: ClassReference,
|
override val classReference: ClassReference,
|
||||||
override val typeParameters: List<TypeParameter>,
|
override val typeParameters: List<TypeParameter>,
|
||||||
val type: KotlinType,
|
val type: KotlinType,
|
||||||
override var state: State
|
override var state: State
|
||||||
) : TypeVariable() {
|
) : TypeVariable() {
|
||||||
|
override val owner = OtherTarget
|
||||||
//ignore state as it is mutable
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (javaClass != other?.javaClass) return false
|
|
||||||
|
|
||||||
other as TypeBasedTypeVariable
|
|
||||||
|
|
||||||
if (classReference != other.classReference) return false
|
|
||||||
if (typeParameters != other.typeParameters) return false
|
|
||||||
if (type != other.type) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var result = classReference.hashCode()
|
|
||||||
result = 31 * result + typeParameters.hashCode()
|
|
||||||
result = 31 * result + type.hashCode()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val TypeVariable.isFixed: Boolean
|
val TypeVariable.isFixed: Boolean
|
||||||
|
|||||||
@@ -7,11 +7,14 @@ package org.jetbrains.kotlin.nj2k.inference.common
|
|||||||
|
|
||||||
import com.intellij.psi.PsiComment
|
import com.intellij.psi.PsiComment
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.nj2k.JKElementInfo
|
import org.jetbrains.kotlin.idea.refactoring.isInterfaceClass
|
||||||
import org.jetbrains.kotlin.nj2k.JKElementInfoLabel
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.*
|
||||||
import org.jetbrains.kotlin.nj2k.asLabel
|
import org.jetbrains.kotlin.psi.KtFunction
|
||||||
|
import org.jetbrains.kotlin.psi.KtTypeElement
|
||||||
import org.jetbrains.kotlin.psi.KtTypeProjection
|
import org.jetbrains.kotlin.psi.KtTypeProjection
|
||||||
|
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
fun PsiElement.getLabel(): JKElementInfoLabel? =
|
fun PsiElement.getLabel(): JKElementInfoLabel? =
|
||||||
@@ -28,3 +31,14 @@ fun PsiElement.elementInfo(converterContext: NewJ2kConverterContext): List<JKEle
|
|||||||
getLabel()?.let { label ->
|
getLabel()?.let { label ->
|
||||||
converterContext.elementsInfoStorage.getInfoForLabel(label)
|
converterContext.elementsInfoStorage.getInfoForLabel(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun KtTypeReference.hasUnknownLabel(context: NewJ2kConverterContext, unknownLabel: JKElementInfo) =
|
||||||
|
getLabel()?.let { label ->
|
||||||
|
unknownLabel in context.elementsInfoStorage.getInfoForLabel(label).orEmpty()
|
||||||
|
} ?: false
|
||||||
|
|
||||||
|
fun KtTypeElement.hasUnknownLabel(context: NewJ2kConverterContext, unknownLabel: JKElementInfo) =
|
||||||
|
parent
|
||||||
|
?.safeAs<KtTypeReference>()
|
||||||
|
?.hasUnknownLabel(context, unknownLabel) == true
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.nj2k.inference.nullability
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.nj2k.inference.common.*
|
||||||
|
|
||||||
|
class NullabilityConstraintBoundProvider : ConstraintBoundProviderImpl() {
|
||||||
|
override fun BoundTypeLabel.constraintBound(): ConstraintBound? = when (this) {
|
||||||
|
is TypeVariableLabel -> typeVariable.constraintBound()
|
||||||
|
is TypeParameterLabel -> null
|
||||||
|
is GenericLabel -> null
|
||||||
|
StarProjectionLabel -> null
|
||||||
|
NullLiteralLabel -> LiteralBound.UPPER
|
||||||
|
LiteralLabel -> LiteralBound.LOWER
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-2
@@ -17,7 +17,7 @@ class NullabilityConstraintsCollector : ConstraintsCollector() {
|
|||||||
boundTypeCalculator: BoundTypeCalculator,
|
boundTypeCalculator: BoundTypeCalculator,
|
||||||
inferenceContext: InferenceContext,
|
inferenceContext: InferenceContext,
|
||||||
resolutionFacade: ResolutionFacade
|
resolutionFacade: ResolutionFacade
|
||||||
) = with(boundTypeCalculator) {
|
) {
|
||||||
when {
|
when {
|
||||||
element is KtBinaryExpression &&
|
element is KtBinaryExpression &&
|
||||||
(element.left?.isNullExpression() == true
|
(element.left?.isNullExpression() == true
|
||||||
@@ -50,6 +50,5 @@ class NullabilityConstraintsCollector : ConstraintsCollector() {
|
|||||||
element.right?.isTheSameTypeAs(State.LOWER, ConstraintPriority.USE_AS_RECEIVER)
|
element.right?.isTheSameTypeAs(State.LOWER, ConstraintPriority.USE_AS_RECEIVER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unit
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-22
@@ -8,10 +8,7 @@ package org.jetbrains.kotlin.nj2k.inference.nullability
|
|||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||||
import org.jetbrains.kotlin.nj2k.UnknownNullability
|
import org.jetbrains.kotlin.nj2k.UnknownNullability
|
||||||
import org.jetbrains.kotlin.nj2k.inference.common.ClassReference
|
import org.jetbrains.kotlin.nj2k.inference.common.*
|
||||||
import org.jetbrains.kotlin.nj2k.inference.common.ContextCollector
|
|
||||||
import org.jetbrains.kotlin.nj2k.inference.common.State
|
|
||||||
import org.jetbrains.kotlin.nj2k.inference.common.getLabel
|
|
||||||
import org.jetbrains.kotlin.psi.KtNullableType
|
import org.jetbrains.kotlin.psi.KtNullableType
|
||||||
import org.jetbrains.kotlin.psi.KtTypeElement
|
import org.jetbrains.kotlin.psi.KtTypeElement
|
||||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||||
@@ -21,23 +18,10 @@ class NullabilityContextCollector(
|
|||||||
resolutionFacade: ResolutionFacade,
|
resolutionFacade: ResolutionFacade,
|
||||||
private val converterContext: NewJ2kConverterContext
|
private val converterContext: NewJ2kConverterContext
|
||||||
) : ContextCollector(resolutionFacade) {
|
) : ContextCollector(resolutionFacade) {
|
||||||
override fun ClassReference.getState(typeElement: KtTypeElement?): State? {
|
override fun ClassReference.getState(typeElement: KtTypeElement?): State? = when {
|
||||||
val hasUndefinedNullabilityLabel = typeElement
|
typeElement == null -> State.UNKNOWN
|
||||||
?.parent
|
typeElement.hasUnknownLabel(converterContext, UnknownNullability) -> State.UNKNOWN
|
||||||
?.safeAs<KtTypeReference>()
|
typeElement is KtNullableType -> State.UPPER
|
||||||
?.hasUndefinedNullabilityLabel(converterContext)
|
else -> State.LOWER
|
||||||
?: false
|
|
||||||
return when {
|
|
||||||
typeElement == null -> State.UNKNOWN
|
|
||||||
hasUndefinedNullabilityLabel -> State.UNKNOWN
|
|
||||||
typeElement is KtNullableType -> State.UPPER
|
|
||||||
else -> State.LOWER
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun KtTypeReference.hasUndefinedNullabilityLabel(context: NewJ2kConverterContext) =
|
|
||||||
getLabel()?.let { label ->
|
|
||||||
context.elementsInfoStorage.getInfoForLabel(label).orEmpty().contains(UnknownNullability)
|
|
||||||
} ?: false
|
|
||||||
}
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.nj2k.inference.nullability
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.isAbstract
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.nj2k.inference.common.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
|
||||||
|
|
||||||
|
class NullabilityDefaultStateProvider : DefaultStateProvider() {
|
||||||
|
override fun defaultStateFor(typeVariable: TypeVariable): State {
|
||||||
|
if (typeVariable is TypeElementBasedTypeVariable
|
||||||
|
&& typeVariable.typeElement.type.constructor.declarationDescriptor is TypeParameterDescriptor
|
||||||
|
) {
|
||||||
|
return State.LOWER
|
||||||
|
}
|
||||||
|
return when (val owner = typeVariable.owner) {
|
||||||
|
is FunctionParameter -> if (owner.owner.isPrivate()) State.LOWER else State.UPPER
|
||||||
|
is FunctionReturnType ->
|
||||||
|
if (owner.function.isAbstract()
|
||||||
|
|| owner.function.hasModifier(KtTokens.OPEN_KEYWORD)
|
||||||
|
|| owner.function.bodyExpression == null
|
||||||
|
) State.UPPER else State.LOWER
|
||||||
|
is Property -> if (owner.property.isPrivate()
|
||||||
|
|| !owner.property.isVar
|
||||||
|
|| !owner.property.isLocal
|
||||||
|
) State.LOWER else State.UPPER
|
||||||
|
is TypeArgument -> State.LOWER
|
||||||
|
OtherTarget -> State.UPPER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-21
@@ -12,27 +12,14 @@ import org.jetbrains.kotlin.psi.KtTypeElement
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
|
|
||||||
class NullabilityStateUpdater : StateUpdater() {
|
class NullabilityStateUpdater : StateUpdater() {
|
||||||
override fun updateStates(inferenceContext: InferenceContext) {
|
override fun TypeElementBasedTypeVariable.updateState() = when (state) {
|
||||||
if (inferenceContext.typeVariables.isEmpty()) return
|
State.LOWER -> changeState(toNullable = false)
|
||||||
|
State.UPPER -> changeState(toNullable = true)
|
||||||
val deepComparator = Comparator<TypeElementBasedTypeVariable> { o1, o2 ->
|
State.UNKNOWN -> {
|
||||||
if (o1.typeElement.typeElement.isAncestor(o2.typeElement.typeElement)) 1 else -1
|
if (typeElement is TypeParameterElementData) {
|
||||||
}
|
changeState(toNullable = false)
|
||||||
for (typeVariable in inferenceContext
|
} else {
|
||||||
.typeVariables
|
changeState(toNullable = true)
|
||||||
.filterIsInstance<TypeElementBasedTypeVariable>()
|
|
||||||
.sortedWith(deepComparator)
|
|
||||||
) {
|
|
||||||
when (typeVariable.state) {
|
|
||||||
State.LOWER -> typeVariable.changeState(toNullable = false)
|
|
||||||
State.UPPER -> typeVariable.changeState(toNullable = true)
|
|
||||||
State.UNKNOWN -> {
|
|
||||||
if (typeVariable.typeElement is TypeParameterElementData) {
|
|
||||||
typeVariable.changeState(toNullable = false)
|
|
||||||
} else {
|
|
||||||
typeVariable.changeState(toNullable = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,6 +238,13 @@ private val processings: List<NamedPostProcessingGroup> = listOf(
|
|||||||
NamedPostProcessingGroup(
|
NamedPostProcessingGroup(
|
||||||
"Inferring declarations nullability",
|
"Inferring declarations nullability",
|
||||||
listOf(
|
listOf(
|
||||||
|
InspectionLikeProcessingGroup(
|
||||||
|
processings = listOf(
|
||||||
|
VarToValProcessing(),
|
||||||
|
generalInspectionBasedProcessing(CanBeValInspection(ignoreNotUsedVals = false))
|
||||||
|
),
|
||||||
|
runSingleTime = true
|
||||||
|
),
|
||||||
nullabilityProcessing,
|
nullabilityProcessing,
|
||||||
clearUndefinedLabelsProcessing
|
clearUndefinedLabelsProcessing
|
||||||
)
|
)
|
||||||
|
|||||||
+232
-156
@@ -23,7 +23,9 @@ import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
|||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.references.readWriteAccess
|
import org.jetbrains.kotlin.idea.references.readWriteAccess
|
||||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.j2k.getContainingClass
|
||||||
|
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||||
import org.jetbrains.kotlin.nj2k.asGetterName
|
import org.jetbrains.kotlin.nj2k.asGetterName
|
||||||
@@ -35,8 +37,10 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.isError
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
|
||||||
import org.jetbrains.kotlin.util.isJavaDescriptor
|
import org.jetbrains.kotlin.util.isJavaDescriptor
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
@@ -108,7 +112,6 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun KtElement.forAllUsages(action: (KtElement) -> Unit) {
|
private fun KtElement.forAllUsages(action: (KtElement) -> Unit) {
|
||||||
usages().forEach { action(it.element as KtElement) }
|
usages().forEach { action(it.element as KtElement) }
|
||||||
}
|
}
|
||||||
@@ -129,13 +132,12 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
|
|||||||
|
|
||||||
val ktGetter = factory.createGetter(body, getter.modifiersText)
|
val ktGetter = factory.createGetter(body, getter.modifiersText)
|
||||||
ktGetter.filterModifiers()
|
ktGetter.filterModifiers()
|
||||||
return property.add(ktGetter).cast<KtPropertyAccessor>().let {
|
return property.add(ktGetter).cast<KtPropertyAccessor>().also {
|
||||||
if (getter is RealGetter) {
|
if (getter is RealGetter) {
|
||||||
getter.function.forAllUsages { usage ->
|
getter.function.forAllUsages { usage ->
|
||||||
usage.getStrictParentOfType<KtCallExpression>()!!.replace(factory.createExpression(getter.name))
|
usage.getStrictParentOfType<KtCallExpression>()!!.replace(factory.createExpression(getter.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
it
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,9 +272,15 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
|
|||||||
|
|
||||||
|
|
||||||
override fun runProcessing(elements: List<PsiElement>, converterContext: NewJ2kConverterContext) {
|
override fun runProcessing(elements: List<PsiElement>, converterContext: NewJ2kConverterContext) {
|
||||||
val classes = elements.descendantsOfType<KtClassOrObject>().sortedByInheritance()
|
val classes = elements
|
||||||
for (klass in classes) {
|
.descendantsOfType<KtClassOrObject>()
|
||||||
convertClass(klass)
|
.sortedByInheritance()
|
||||||
|
val collectingState = CollectingState()
|
||||||
|
val classesWithPropertiesData = classes.map { klass ->
|
||||||
|
klass to klass.collectPropertiesData(collectingState)
|
||||||
|
}
|
||||||
|
for ((klass, propertiesData) in classesWithPropertiesData) {
|
||||||
|
convertClass(klass, propertiesData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,8 +295,82 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtClassOrObject.collectGettersAndSetters(factory: KtPsiFactory): List<PropertyWithAccessors> {
|
private fun calculatePropertyType(getterType: KotlinType?, setterType: KotlinType?): KotlinType? = when {
|
||||||
val classDescriptor = resolveToDescriptorIfAny() ?: return emptyList()
|
getterType != null && getterType.isMarkedNullable -> getterType
|
||||||
|
setterType != null && setterType.isMarkedNullable -> setterType
|
||||||
|
else -> getterType ?: setterType
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun calculatePropertyType(getter: KtNamedFunction?, setter: KtNamedFunction?): KotlinType? {
|
||||||
|
val getterType = getter?.resolveToDescriptorIfAny()?.returnType
|
||||||
|
val setterType = setter?.resolveToDescriptorIfAny()?.valueParameters?.singleOrNull()?.type
|
||||||
|
return calculatePropertyType(getterType, setterType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun calculatePropertyTypeBasedOnSuperDescriptors(getter: KtNamedFunction?, setter: KtNamedFunction?): KotlinType? {
|
||||||
|
val superGetterType = getter
|
||||||
|
?.resolveToDescriptorIfAny()
|
||||||
|
?.overriddenDescriptors
|
||||||
|
?.firstOrNull()
|
||||||
|
?.returnType
|
||||||
|
val superSetterType = setter
|
||||||
|
?.resolveToDescriptorIfAny()
|
||||||
|
?.overriddenDescriptors
|
||||||
|
?.firstOrNull()
|
||||||
|
?.valueParameters
|
||||||
|
?.singleOrNull()
|
||||||
|
?.type
|
||||||
|
return calculatePropertyType(superGetterType, superSetterType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtClassOrObject.collectPropertiesData(collectingState: CollectingState): List<PropertyData> {
|
||||||
|
return declarations
|
||||||
|
.asSequence()
|
||||||
|
.mapNotNull { it.asPropertyAccessor() }
|
||||||
|
.groupBy { it.name.removePrefix("is").decapitalize() }
|
||||||
|
.values
|
||||||
|
.mapNotNull { group ->
|
||||||
|
val realGetter = group.firstIsInstanceOrNull<RealGetter>()
|
||||||
|
val realSetter = group.firstIsInstanceOrNull<RealSetter>()?.takeIf { setter ->
|
||||||
|
if (realGetter == null) return@takeIf true
|
||||||
|
val setterType = setter.function.valueParameters.first().type()
|
||||||
|
val getterType = realGetter.function.type()
|
||||||
|
if (setterType == null
|
||||||
|
|| getterType == null
|
||||||
|
|| !KotlinTypeChecker.DEFAULT.isSubtypeOf(getterType, setterType)
|
||||||
|
) {
|
||||||
|
if (isInterfaceClass()) return@mapNotNull null
|
||||||
|
false
|
||||||
|
} else true
|
||||||
|
}
|
||||||
|
if (realGetter == null && realSetter == null) return@mapNotNull null
|
||||||
|
val realProperty = group.firstIsInstanceOrNull<RealProperty>()
|
||||||
|
val name = realGetter?.name ?: realSetter?.name!!
|
||||||
|
|
||||||
|
val superDeclarationOwner = (realGetter?.function ?: realSetter?.function)
|
||||||
|
?.resolveToDescriptorIfAny()
|
||||||
|
?.overriddenDescriptors
|
||||||
|
?.firstOrNull()
|
||||||
|
?.findPsi()
|
||||||
|
?.safeAs<KtDeclaration>()
|
||||||
|
?.containingClassOrObject
|
||||||
|
|
||||||
|
collectingState.propertyNameToSuperType[superDeclarationOwner to name]
|
||||||
|
val type = collectingState.propertyNameToSuperType[superDeclarationOwner to name]
|
||||||
|
?: calculatePropertyType(
|
||||||
|
realGetter?.function,
|
||||||
|
realSetter?.function
|
||||||
|
) ?: return@mapNotNull null
|
||||||
|
collectingState.propertyNameToSuperType[this to name] = type
|
||||||
|
PropertyData(realProperty, realGetter, realSetter, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<PropertyData>.filterGettersAndSetters(
|
||||||
|
klass: KtClassOrObject,
|
||||||
|
factory: KtPsiFactory
|
||||||
|
): List<PropertyWithAccessors> {
|
||||||
|
val classDescriptor = klass.resolveToDescriptorIfAny() ?: return emptyList()
|
||||||
|
|
||||||
val variablesDescriptorsMap =
|
val variablesDescriptorsMap =
|
||||||
(listOfNotNull(classDescriptor.getSuperClassNotAny()) + classDescriptor.getSuperInterfaces())
|
(listOfNotNull(classDescriptor.getSuperClassNotAny()) + classDescriptor.getSuperInterfaces())
|
||||||
@@ -301,153 +383,135 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
|
|||||||
.filterIsInstance<VariableDescriptor>()
|
.filterIsInstance<VariableDescriptor>()
|
||||||
.associateBy { it.name.asString() }
|
.associateBy { it.name.asString() }
|
||||||
|
|
||||||
return declarations
|
return mapNotNull { (realProperty, realGetter, realSetter, type) ->
|
||||||
.asSequence()
|
val name = realGetter?.name ?: realSetter!!.name
|
||||||
.mapNotNull { it.asPropertyAccessor() }
|
val typeStringified = type
|
||||||
.groupBy { it.name.removePrefix("is").decapitalize() }
|
.takeUnless { it.isError }
|
||||||
.values
|
?.let {
|
||||||
.mapNotNull { group ->
|
IdeDescriptorRenderers.SOURCE_CODE.renderType(it)
|
||||||
val realGetter = group.firstIsInstanceOrNull<RealGetter>()
|
} ?: realGetter?.function?.typeReference?.text
|
||||||
val realSetter = group.firstIsInstanceOrNull<RealSetter>()?.takeIf { setter ->
|
?: realSetter?.function?.valueParameters?.firstOrNull()?.typeReference?.text!!
|
||||||
if (realGetter == null) return@takeIf true
|
|
||||||
if (setter.function.valueParameters.first().type()?.makeNotNullable() !=
|
|
||||||
realGetter.function.type()?.makeNotNullable()
|
|
||||||
) {
|
|
||||||
if (isInterfaceClass()) return@mapNotNull null
|
|
||||||
false
|
|
||||||
} else true
|
|
||||||
}
|
|
||||||
val realProperty = group.firstIsInstanceOrNull<RealProperty>()
|
|
||||||
if (realGetter == null && realSetter == null) return@mapNotNull null
|
|
||||||
val name = realGetter?.name ?: realSetter!!.name
|
|
||||||
val type =
|
|
||||||
realGetter?.function?.typeReference?.text
|
|
||||||
?: realSetter?.function?.valueParameters?.first()?.typeReference?.text!!
|
|
||||||
|
|
||||||
if (realSetter != null
|
if (realSetter != null
|
||||||
&& realGetter != null
|
&& realGetter != null
|
||||||
&& isInterfaceClass()
|
&& klass.isInterfaceClass()
|
||||||
&& realSetter.function.hasOverrides() != realGetter.function.hasOverrides()
|
&& realSetter.function.hasOverrides() != realGetter.function.hasOverrides()
|
||||||
|
) return@mapNotNull null
|
||||||
|
|
||||||
|
if (realSetter != null
|
||||||
|
&& realGetter != null
|
||||||
|
&& realSetter.function.hasSuperFunction() != realGetter.function.hasSuperFunction()
|
||||||
|
) return@mapNotNull null
|
||||||
|
|
||||||
|
if (realProperty != null
|
||||||
|
&& realGetter?.target != null
|
||||||
|
&& realGetter.target != realProperty.property
|
||||||
|
&& realProperty.property.hasInitializer()
|
||||||
|
) return@mapNotNull null
|
||||||
|
|
||||||
|
if (realGetter?.function?.hasInvalidSuperDescriptors() == true
|
||||||
|
|| realSetter?.function?.hasInvalidSuperDescriptors() == true
|
||||||
|
) return@mapNotNull null
|
||||||
|
|
||||||
|
if (realProperty == null) {
|
||||||
|
if (causesNameConflictInCurrentDeclarationAndItsParents(
|
||||||
|
name,
|
||||||
|
classDescriptor.containingDeclaration
|
||||||
|
)
|
||||||
) return@mapNotNull null
|
) return@mapNotNull null
|
||||||
|
|
||||||
if (realSetter != null
|
|
||||||
&& realGetter != null
|
|
||||||
&& realSetter.function.hasSuperFunction() != realGetter.function.hasSuperFunction()
|
|
||||||
) return@mapNotNull null
|
|
||||||
|
|
||||||
if (realProperty != null
|
|
||||||
&& realGetter?.target != null
|
|
||||||
&& realGetter.target != realProperty.property
|
|
||||||
&& realProperty.property.hasInitializer()
|
|
||||||
) return@mapNotNull null
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (realGetter?.function?.hasInvalidSuperDescriptors() == true
|
|
||||||
|| realSetter?.function?.hasInvalidSuperDescriptors() == true
|
|
||||||
) return@mapNotNull null
|
|
||||||
|
|
||||||
if (realProperty == null) {
|
|
||||||
if (causesNameConflictInCurrentDeclarationAndItsParents(
|
|
||||||
name,
|
|
||||||
classDescriptor.containingDeclaration
|
|
||||||
)
|
|
||||||
) return@mapNotNull null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (realProperty != null && (realGetter != null && realGetter.target == null || realSetter != null && realSetter.target == null)) {
|
|
||||||
if (!realProperty.property.isPrivate()) return@mapNotNull null
|
|
||||||
val hasUsages =
|
|
||||||
realProperty.property.hasUsagesOutsideOf(
|
|
||||||
containingKtFile,
|
|
||||||
listOfNotNull(realGetter?.function, realSetter?.function)
|
|
||||||
)
|
|
||||||
if (hasUsages) return@mapNotNull null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (realSetter != null && realProperty != null) {
|
|
||||||
val assignFieldOfOtherInstance = realProperty.property.usages().any { usage ->
|
|
||||||
val element = usage.safeAs<KtSimpleNameReference>()?.element ?: return@any false
|
|
||||||
if (!element.readWriteAccess(useResolveForReadWrite = true).isWrite) return@any false
|
|
||||||
val parent = element.parent
|
|
||||||
parent is KtQualifiedExpression && !parent.receiverExpression.isReferenceToThis()
|
|
||||||
}
|
|
||||||
if (assignFieldOfOtherInstance) return@mapNotNull null
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (realGetter != null && realProperty != null) {
|
|
||||||
val getFieldOfOtherInstanceInGetter = realProperty.property.usages().any { usage ->
|
|
||||||
val element = usage.safeAs<KtSimpleNameReference>()?.element ?: return@any false
|
|
||||||
val parent = element.parent
|
|
||||||
parent is KtQualifiedExpression
|
|
||||||
&& !parent.receiverExpression.isReferenceToThis()
|
|
||||||
&& realGetter.function.isAncestor(element)
|
|
||||||
}
|
|
||||||
if (getFieldOfOtherInstanceInGetter) return@mapNotNull null
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val getter = realGetter ?: when {
|
|
||||||
realProperty?.property?.resolveToDescriptorIfAny()?.overriddenDescriptors?.any {
|
|
||||||
it.safeAs<VariableDescriptor>()?.isVar == true
|
|
||||||
} == true -> FakeGetter(name, null, "")
|
|
||||||
|
|
||||||
variablesDescriptorsMap[name]?.let { variable ->
|
|
||||||
variable.isVar && variable.containingDeclaration != classDescriptor
|
|
||||||
} == true ->
|
|
||||||
FakeGetter(name, factory.createExpression("super.$name"), "")
|
|
||||||
|
|
||||||
else -> return@mapNotNull null
|
|
||||||
}
|
|
||||||
|
|
||||||
val mergedProperty =
|
|
||||||
if (getter is RealGetter
|
|
||||||
&& getter.target != null
|
|
||||||
&& getter.target!!.name != getter.name
|
|
||||||
&& (realSetter == null || realSetter.target != null)
|
|
||||||
) {
|
|
||||||
MergedProperty(name, type, realSetter != null, getter.target!!)
|
|
||||||
} else null
|
|
||||||
|
|
||||||
val setter = realSetter ?: when {
|
|
||||||
realProperty?.property?.isVar == true ->
|
|
||||||
FakeSetter(name, null, "")
|
|
||||||
|
|
||||||
realProperty?.property?.resolveToDescriptorIfAny()?.overriddenDescriptors?.any {
|
|
||||||
it.safeAs<VariableDescriptor>()?.isVar == true
|
|
||||||
} == true
|
|
||||||
|| variablesDescriptorsMap[name]?.isVar == true ->
|
|
||||||
FakeSetter(
|
|
||||||
name,
|
|
||||||
factory.createBlock("super.$name = $name"),
|
|
||||||
""
|
|
||||||
)
|
|
||||||
|
|
||||||
realGetter != null
|
|
||||||
&& (realProperty != null
|
|
||||||
&& realProperty.property.visibilityModifierTypeOrDefault() != realGetter.function.visibilityModifierTypeOrDefault()
|
|
||||||
&& realProperty.property.isVar
|
|
||||||
|| mergedProperty != null
|
|
||||||
&& mergedProperty.mergeTo.visibilityModifierTypeOrDefault() != realGetter.function.visibilityModifierTypeOrDefault()
|
|
||||||
&& mergedProperty.mergeTo.isVar
|
|
||||||
) ->
|
|
||||||
FakeSetter(name, null, null)
|
|
||||||
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
val isVar = setter != null
|
|
||||||
|
|
||||||
val property = mergedProperty?.copy(isVar = isVar)
|
|
||||||
?: realProperty?.copy(isVar = isVar)
|
|
||||||
?: FakeProperty(name, type, isVar)
|
|
||||||
|
|
||||||
PropertyWithAccessors(
|
|
||||||
property,
|
|
||||||
getter,
|
|
||||||
setter
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (realProperty != null && (realGetter != null && realGetter.target == null || realSetter != null && realSetter.target == null)) {
|
||||||
|
if (!realProperty.property.isPrivate()) return@mapNotNull null
|
||||||
|
val hasUsages =
|
||||||
|
realProperty.property.hasUsagesOutsideOf(
|
||||||
|
klass.containingKtFile,
|
||||||
|
listOfNotNull(realGetter?.function, realSetter?.function)
|
||||||
|
)
|
||||||
|
if (hasUsages) return@mapNotNull null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (realSetter != null && realProperty != null) {
|
||||||
|
val assignFieldOfOtherInstance = realProperty.property.usages().any { usage ->
|
||||||
|
val element = usage.safeAs<KtSimpleNameReference>()?.element ?: return@any false
|
||||||
|
if (!element.readWriteAccess(useResolveForReadWrite = true).isWrite) return@any false
|
||||||
|
val parent = element.parent
|
||||||
|
parent is KtQualifiedExpression && !parent.receiverExpression.isReferenceToThis()
|
||||||
|
}
|
||||||
|
if (assignFieldOfOtherInstance) return@mapNotNull null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (realGetter != null && realProperty != null) {
|
||||||
|
val getFieldOfOtherInstanceInGetter = realProperty.property.usages().any { usage ->
|
||||||
|
val element = usage.safeAs<KtSimpleNameReference>()?.element ?: return@any false
|
||||||
|
val parent = element.parent
|
||||||
|
parent is KtQualifiedExpression
|
||||||
|
&& !parent.receiverExpression.isReferenceToThis()
|
||||||
|
&& realGetter.function.isAncestor(element)
|
||||||
|
}
|
||||||
|
if (getFieldOfOtherInstanceInGetter) return@mapNotNull null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val getter = realGetter ?: when {
|
||||||
|
realProperty?.property?.resolveToDescriptorIfAny()?.overriddenDescriptors?.any {
|
||||||
|
it.safeAs<VariableDescriptor>()?.isVar == true
|
||||||
|
} == true -> FakeGetter(name, null, "")
|
||||||
|
|
||||||
|
variablesDescriptorsMap[name]?.let { variable ->
|
||||||
|
variable.isVar && variable.containingDeclaration != classDescriptor
|
||||||
|
} == true ->
|
||||||
|
FakeGetter(name, factory.createExpression("super.$name"), "")
|
||||||
|
|
||||||
|
else -> return@mapNotNull null
|
||||||
|
}
|
||||||
|
|
||||||
|
val mergedProperty =
|
||||||
|
if (getter is RealGetter
|
||||||
|
&& getter.target != null
|
||||||
|
&& getter.target!!.name != getter.name
|
||||||
|
&& (realSetter == null || realSetter.target != null)
|
||||||
|
) {
|
||||||
|
MergedProperty(name, typeStringified, realSetter != null, getter.target!!)
|
||||||
|
} else null
|
||||||
|
|
||||||
|
val setter = realSetter ?: when {
|
||||||
|
realProperty?.property?.isVar == true ->
|
||||||
|
FakeSetter(name, null, "")
|
||||||
|
|
||||||
|
realProperty?.property?.resolveToDescriptorIfAny()?.overriddenDescriptors?.any {
|
||||||
|
it.safeAs<VariableDescriptor>()?.isVar == true
|
||||||
|
} == true
|
||||||
|
|| variablesDescriptorsMap[name]?.isVar == true ->
|
||||||
|
FakeSetter(
|
||||||
|
name,
|
||||||
|
factory.createBlock("super.$name = $name"),
|
||||||
|
""
|
||||||
|
)
|
||||||
|
|
||||||
|
realGetter != null
|
||||||
|
&& (realProperty != null
|
||||||
|
&& realProperty.property.visibilityModifierTypeOrDefault() != realGetter.function.visibilityModifierTypeOrDefault()
|
||||||
|
&& realProperty.property.isVar
|
||||||
|
|| mergedProperty != null
|
||||||
|
&& mergedProperty.mergeTo.visibilityModifierTypeOrDefault() != realGetter.function.visibilityModifierTypeOrDefault()
|
||||||
|
&& mergedProperty.mergeTo.isVar
|
||||||
|
) ->
|
||||||
|
FakeSetter(name, null, null)
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
val isVar = setter != null
|
||||||
|
val property = mergedProperty?.copy(isVar = isVar)
|
||||||
|
?: realProperty?.copy(isVar = isVar)
|
||||||
|
?: FakeProperty(name, typeStringified, isVar)
|
||||||
|
|
||||||
|
PropertyWithAccessors(
|
||||||
|
property,
|
||||||
|
getter,
|
||||||
|
setter
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtProperty.renameTo(newName: String, factory: KtPsiFactory) {
|
private fun KtProperty.renameTo(newName: String, factory: KtPsiFactory) {
|
||||||
@@ -466,9 +530,10 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
|
|||||||
setName(newName)
|
setName(newName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertClass(klass: KtClassOrObject) {
|
private fun convertClass(klass: KtClassOrObject, propertiesData: List<PropertyData>) {
|
||||||
val factory = KtPsiFactory(klass)
|
val factory = KtPsiFactory(klass)
|
||||||
val accessors = klass.collectGettersAndSetters(factory)
|
val accessors = propertiesData.filterGettersAndSetters(klass, factory)
|
||||||
|
|
||||||
for ((property, getter, setter) in accessors) {
|
for ((property, getter, setter) in accessors) {
|
||||||
val ktProperty = when (property) {
|
val ktProperty = when (property) {
|
||||||
is RealProperty -> {
|
is RealProperty -> {
|
||||||
@@ -537,6 +602,13 @@ private data class PropertyWithAccessors(
|
|||||||
val setter: Setter?
|
val setter: Setter?
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private data class PropertyData(
|
||||||
|
val realProperty: RealProperty?,
|
||||||
|
val realGetter: RealGetter?,
|
||||||
|
val realSetter: RealSetter?,
|
||||||
|
val type: KotlinType
|
||||||
|
)
|
||||||
|
|
||||||
private interface PropertyInfo {
|
private interface PropertyInfo {
|
||||||
val name: String
|
val name: String
|
||||||
}
|
}
|
||||||
@@ -618,6 +690,10 @@ private data class FakeSetter(
|
|||||||
get() = name.fixSetterParameterName()
|
get() = name.fixSetterParameterName()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class CollectingState(
|
||||||
|
val propertyNameToSuperType: MutableMap<Pair<KtClassOrObject, String>, KotlinType> = mutableMapOf()
|
||||||
|
)
|
||||||
|
|
||||||
private fun String.fixSetterParameterName() =
|
private fun String.fixSetterParameterName() =
|
||||||
if (this == KtTokens.FIELD_KEYWORD.value) "value"
|
if (this == KtTokens.FIELD_KEYWORD.value) "value"
|
||||||
else this
|
else this
|
||||||
|
|||||||
+2
-1
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.asAssignment
|
import org.jetbrains.kotlin.psi.psiUtil.asAssignment
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierTypeOrDefault
|
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierTypeOrDefault
|
||||||
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class ConvertToDataClassProcessing : ElementsBasedPostProcessing() {
|
class ConvertToDataClassProcessing : ElementsBasedPostProcessing() {
|
||||||
@@ -64,7 +65,7 @@ class ConvertToDataClassProcessing : ElementsBasedPostProcessing() {
|
|||||||
} ?: return@map null
|
} ?: return@map null
|
||||||
val propertyType = property.type() ?: return@map null
|
val propertyType = property.type() ?: return@map null
|
||||||
val parameterType = parameter.type() ?: return@map null
|
val parameterType = parameter.type() ?: return@map null
|
||||||
if (propertyType != parameterType) return@map null
|
if (!KotlinTypeChecker.DEFAULT.equalTypes(propertyType, parameterType)) return@map null
|
||||||
parametersUsed += parameter
|
parametersUsed += parameter
|
||||||
ConstructorParameterInitialization(property, parameter, assignment)
|
ConstructorParameterInitialization(property, parameter, assignment)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.nj2k.postProcessing.resolve
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.isNullable
|
import org.jetbrains.kotlin.types.isNullable
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -55,8 +56,8 @@ class RemoveExplicitPropertyTypeProcessing : ApplicabilityBasedInspectionLikePro
|
|||||||
val initializer = element.initializer ?: return false
|
val initializer = element.initializer ?: return false
|
||||||
val withoutExpectedType =
|
val withoutExpectedType =
|
||||||
initializer.analyzeInContext(initializer.getResolutionScope()).getType(initializer) ?: return false
|
initializer.analyzeInContext(initializer.getResolutionScope()).getType(initializer) ?: return false
|
||||||
val descriptor = element.resolveToDescriptorIfAny() as? CallableDescriptor ?: return false
|
val typeBeDescriptor = element.resolveToDescriptorIfAny().safeAs<CallableDescriptor>()?.returnType ?: return false
|
||||||
return withoutExpectedType == descriptor.returnType
|
return KotlinTypeChecker.DEFAULT.equalTypes(withoutExpectedType, typeBeDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun apply(element: KtProperty) {
|
override fun apply(element: KtProperty) {
|
||||||
|
|||||||
+3
-1
@@ -54,6 +54,7 @@ val nullabilityProcessing =
|
|||||||
NullabilityContextCollector(resolutionFacade, converterContext),
|
NullabilityContextCollector(resolutionFacade, converterContext),
|
||||||
ConstraintsCollectorAggregator(
|
ConstraintsCollectorAggregator(
|
||||||
resolutionFacade,
|
resolutionFacade,
|
||||||
|
NullabilityConstraintBoundProvider(),
|
||||||
listOf(
|
listOf(
|
||||||
CommonConstraintsCollector(),
|
CommonConstraintsCollector(),
|
||||||
CallExpressionConstraintCollector(),
|
CallExpressionConstraintCollector(),
|
||||||
@@ -62,7 +63,8 @@ val nullabilityProcessing =
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
BoundTypeCalculatorImpl(resolutionFacade, NullabilityBoundTypeEnhancer(resolutionFacade)),
|
BoundTypeCalculatorImpl(resolutionFacade, NullabilityBoundTypeEnhancer(resolutionFacade)),
|
||||||
NullabilityStateUpdater()
|
NullabilityStateUpdater(),
|
||||||
|
NullabilityDefaultStateProvider()
|
||||||
)
|
)
|
||||||
val elements = if (rangeMarker != null) {
|
val elements = if (rangeMarker != null) {
|
||||||
file.elementsInRange(rangeMarker.range ?: return@postProcessing).filterIsInstance<KtElement>()
|
file.elementsInRange(rangeMarker.range ?: return@postProcessing).filterIsInstance<KtElement>()
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ sealed class SuperFunctionInfo
|
|||||||
data class ExternalSuperFunctionInfo(val descriptor: FunctionDescriptor) : SuperFunctionInfo()
|
data class ExternalSuperFunctionInfo(val descriptor: FunctionDescriptor) : SuperFunctionInfo()
|
||||||
data class InternalSuperFunctionInfo(val label: JKElementInfoLabel) : SuperFunctionInfo()
|
data class InternalSuperFunctionInfo(val label: JKElementInfoLabel) : SuperFunctionInfo()
|
||||||
|
|
||||||
data class FunctionInfo(val originalDescriptor: FunctionDescriptor, val superFunctions: List<SuperFunctionInfo>) : JKElementInfo
|
data class FunctionInfo(val superFunctions: List<SuperFunctionInfo>) : JKElementInfo
|
||||||
|
|
||||||
object UnknownNullability : JKElementInfo
|
object UnknownNullability : JKElementInfo
|
||||||
|
object UnknownMutability : JKElementInfo
|
||||||
|
|
||||||
inline class JKElementInfoLabel(val label: String) {
|
inline class JKElementInfoLabel(val label: String) {
|
||||||
fun render(): String = "/*@@$label@@*/"
|
fun render(): String = "/*@@$label@@*/"
|
||||||
|
|||||||
@@ -6,9 +6,14 @@
|
|||||||
package org.jetbrains.kotlin.nj2k.conversions
|
package org.jetbrains.kotlin.nj2k.conversions
|
||||||
|
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
|
import com.intellij.psi.impl.light.LightMethod
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMethodDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMethodDescriptor
|
||||||
import org.jetbrains.kotlin.j2k.ast.Nullability
|
import org.jetbrains.kotlin.j2k.ast.Nullability
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||||
|
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||||
import org.jetbrains.kotlin.nj2k.*
|
import org.jetbrains.kotlin.nj2k.*
|
||||||
import org.jetbrains.kotlin.nj2k.symbols.JKUniverseMethodSymbol
|
import org.jetbrains.kotlin.nj2k.symbols.JKUniverseMethodSymbol
|
||||||
import org.jetbrains.kotlin.nj2k.tree.*
|
import org.jetbrains.kotlin.nj2k.tree.*
|
||||||
@@ -20,7 +25,7 @@ class AddElementsInfoConversion(private val context: NewJ2kConverterContext) : R
|
|||||||
override fun applyToElement(element: JKTreeElement): JKTreeElement {
|
override fun applyToElement(element: JKTreeElement): JKTreeElement {
|
||||||
when (element) {
|
when (element) {
|
||||||
is JKTypeElement -> addInfoForTypeElement(element)
|
is JKTypeElement -> addInfoForTypeElement(element)
|
||||||
is JKKtFunction -> addInfoForFunction(element)
|
is JKMethod -> addInfoForFunction(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
return recurse(element)
|
return recurse(element)
|
||||||
@@ -33,24 +38,36 @@ class AddElementsInfoConversion(private val context: NewJ2kConverterContext) : R
|
|||||||
) {
|
) {
|
||||||
context.elementsInfoStorage.addEntry(type, UnknownNullability)
|
context.elementsInfoStorage.addEntry(type, UnknownNullability)
|
||||||
}
|
}
|
||||||
|
if (type.isCollectionType) {
|
||||||
|
context.elementsInfoStorage.addEntry(type, UnknownMutability)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addInfoForFunction(function: JKKtFunction) {
|
private fun addInfoForFunction(function: JKMethod) {
|
||||||
val psiMethod = function.psi<PsiMethod>() ?: return
|
val superMethods = function.superMethods() ?: return
|
||||||
val descriptor = psiMethod.getJavaMethodDescriptor() ?: return
|
val superDescriptorsInfo = superMethods.map { superDescriptor ->
|
||||||
val superDescriptorsInfo =
|
val superPsi = superDescriptor.original.findPsi()
|
||||||
descriptor.overriddenDescriptors.mapNotNull { superDescriptor ->
|
when (val symbol = context.symbolProvider.symbolsByPsi[superPsi]) {
|
||||||
val superPsi = superDescriptor.original.findPsi()
|
is JKUniverseMethodSymbol ->
|
||||||
when (val symbol = context.symbolProvider.symbolsByPsi[superPsi]) {
|
InternalSuperFunctionInfo(context.elementsInfoStorage.getOrCreateInfoForElement(symbol.target))
|
||||||
is JKUniverseMethodSymbol ->
|
else -> ExternalSuperFunctionInfo(superDescriptor)
|
||||||
InternalSuperFunctionInfo(
|
|
||||||
context.elementsInfoStorage.getOrCreateInfoForElement(symbol.target)
|
|
||||||
)
|
|
||||||
else -> ExternalSuperFunctionInfo(superDescriptor)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
context.elementsInfoStorage.addEntry(function, FunctionInfo(descriptor, superDescriptorsInfo))
|
}
|
||||||
|
context.elementsInfoStorage.addEntry(function, FunctionInfo(superDescriptorsInfo))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JKMethod.superMethods(): Collection<FunctionDescriptor>? {
|
||||||
|
val psiMethod = psi<PsiMethod>() ?: return null
|
||||||
|
psiMethod.getJavaMethodDescriptor()?.let { descriptor ->
|
||||||
|
return descriptor.overriddenDescriptors
|
||||||
|
}
|
||||||
|
return psiMethod.findSuperMethods().mapNotNull { superMethod ->
|
||||||
|
when (superMethod) {
|
||||||
|
is KtLightMethod -> superMethod.kotlinOrigin?.resolveToDescriptorIfAny()?.safeAs()
|
||||||
|
else -> superMethod.getJavaMethodDescriptor()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JKType.forAllInnerTypes(action: (JKType) -> Unit) {
|
private fun JKType.forAllInnerTypes(action: (JKType) -> Unit) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
|
|||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
@@ -47,14 +48,13 @@ class StaticMemberAccessConversion(private val context: NewJ2kConverterContext)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
return recurse(element)
|
return recurse(element)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JKSymbol.isStaticMember(): Boolean {
|
private fun JKSymbol.isStaticMember(): Boolean {
|
||||||
val target = target
|
val target = target
|
||||||
return when (target) {
|
return when (target) {
|
||||||
is PsiModifierListOwner -> target.hasModifier(JvmModifier.STATIC)
|
is PsiModifierListOwner -> target.hasModifier(JvmModifier.STATIC)
|
||||||
is KtElement -> target.parentOfType<KtClassOrObject>()
|
is KtElement -> target.getStrictParentOfType<KtClassOrObject>()
|
||||||
?.safeAs<KtObjectDeclaration>()
|
?.safeAs<KtObjectDeclaration>()
|
||||||
?.isCompanion() == true
|
?.isCompanion() == true
|
||||||
is JKTreeElement ->
|
is JKTreeElement ->
|
||||||
|
|||||||
@@ -22,17 +22,6 @@ import org.jetbrains.kotlin.nj2k.tree.*
|
|||||||
import org.jetbrains.kotlin.nj2k.tree.impl.*
|
import org.jetbrains.kotlin.nj2k.tree.impl.*
|
||||||
|
|
||||||
class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveApplicableConversionBase() {
|
class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveApplicableConversionBase() {
|
||||||
private val typeFlavorCalculator = TypeFlavorCalculator(object : TypeFlavorConverterFacade {
|
|
||||||
override val referenceSearcher: ReferenceSearcher
|
|
||||||
get() = context.converter.converterServices.oldServices.referenceSearcher
|
|
||||||
override val javaDataFlowAnalyzerFacade: JavaDataFlowAnalyzerFacade
|
|
||||||
get() = context.converter.converterServices.oldServices.javaDataFlowAnalyzerFacade
|
|
||||||
override val resolverForConverter: ResolverForConverter
|
|
||||||
get() = context.converter.converterServices.oldServices.resolverForConverter
|
|
||||||
|
|
||||||
override fun inConversionScope(element: PsiElement): Boolean = context.inConversionContext(element)
|
|
||||||
})
|
|
||||||
|
|
||||||
override fun applyToElement(element: JKTreeElement): JKTreeElement {
|
override fun applyToElement(element: JKTreeElement): JKTreeElement {
|
||||||
return when (element) {
|
return when (element) {
|
||||||
is JKTypeElement -> {
|
is JKTypeElement -> {
|
||||||
@@ -62,8 +51,7 @@ class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveAppl
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val typeParametersCount = classSymbol.expectedTypeParametersCount()
|
return when (val typeParametersCount = classSymbol.expectedTypeParametersCount()) {
|
||||||
return when (typeParametersCount) {
|
|
||||||
0 -> this
|
0 -> this
|
||||||
else -> JKTypeArgumentListImpl(List(typeParametersCount) {
|
else -> JKTypeArgumentListImpl(List(typeParametersCount) {
|
||||||
JKTypeElementImpl(
|
JKTypeElementImpl(
|
||||||
@@ -124,7 +112,7 @@ class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveAppl
|
|||||||
|
|
||||||
private fun JKClassSymbol.mapClassSymbol(typeElement: JKTypeElement?): JKClassSymbol {
|
private fun JKClassSymbol.mapClassSymbol(typeElement: JKTypeElement?): JKClassSymbol {
|
||||||
if (this is JKUniverseClassSymbol) return this
|
if (this is JKUniverseClassSymbol) return this
|
||||||
val newFqName = typeElement?.let { kotlinCollectionClassName(it) }
|
val newFqName = kotlinCollectionClassName()
|
||||||
?: kotlinStandardType()
|
?: kotlinStandardType()
|
||||||
?: fqName
|
?: fqName
|
||||||
return context.symbolProvider.provideClassSymbol(newFqName)
|
return context.symbolProvider.provideClassSymbol(newFqName)
|
||||||
@@ -137,12 +125,8 @@ class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveAppl
|
|||||||
nullability
|
nullability
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private fun JKClassSymbol.kotlinCollectionClassName(): String? =
|
||||||
private fun JKClassSymbol.kotlinCollectionClassName(typeElement: JKTypeElement?): String? {
|
toKotlinMutableTypesMap[fqName]
|
||||||
val isStructureMutable = calculateStructureMutability(typeElement)
|
|
||||||
return if (isStructureMutable) toKotlinMutableTypesMap[fqName]
|
|
||||||
else toKotlinTypesMap[fqName]
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun JKClassSymbol.kotlinStandardType(): String? {
|
private fun JKClassSymbol.kotlinStandardType(): String? {
|
||||||
if (isKtFunction(fqName)) return fqName
|
if (isKtFunction(fqName)) return fqName
|
||||||
@@ -157,16 +141,6 @@ class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveAppl
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateStructureMutability(typeElement: JKTypeElement?): Boolean {
|
|
||||||
val parent = typeElement?.parent ?: return false
|
|
||||||
val psi = parent.psi ?: return false
|
|
||||||
return when (parent) {
|
|
||||||
is JKVariable -> typeFlavorCalculator.variableMutability(psi as PsiVariable) == Mutability.Mutable
|
|
||||||
is JKMethod -> typeFlavorCalculator.methodMutability(psi as PsiMethod) == Mutability.Mutable
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val ktFunctionRegex = "kotlin\\.jvm\\.functions\\.Function\\d+".toRegex()
|
private val ktFunctionRegex = "kotlin\\.jvm\\.functions\\.Function\\d+".toRegex()
|
||||||
private fun isKtFunction(fqName: String) =
|
private fun isKtFunction(fqName: String) =
|
||||||
|
|||||||
@@ -357,11 +357,12 @@ fun JKType.arrayFqName(): String =
|
|||||||
else KotlinBuiltIns.FQ_NAMES.array.asString()
|
else KotlinBuiltIns.FQ_NAMES.array.asString()
|
||||||
|
|
||||||
fun JKClassSymbol.isArrayType(): Boolean =
|
fun JKClassSymbol.isArrayType(): Boolean =
|
||||||
fqName in
|
fqName in arrayFqNames
|
||||||
JKJavaPrimitiveTypeImpl.KEYWORD_TO_INSTANCE.values
|
|
||||||
.filterIsInstance<JKJavaPrimitiveType>()
|
private val arrayFqNames = JKJavaPrimitiveTypeImpl.KEYWORD_TO_INSTANCE.values
|
||||||
.map { PrimitiveType.valueOf(it.jvmPrimitiveType.name).arrayTypeFqName.asString() } +
|
.filterIsInstance<JKJavaPrimitiveType>()
|
||||||
KotlinBuiltIns.FQ_NAMES.array.asString()
|
.map { PrimitiveType.valueOf(it.jvmPrimitiveType.name).arrayTypeFqName.asString() } +
|
||||||
|
KotlinBuiltIns.FQ_NAMES.array.asString()
|
||||||
|
|
||||||
fun JKType.isArrayType() =
|
fun JKType.isArrayType() =
|
||||||
when (this) {
|
when (this) {
|
||||||
@@ -370,6 +371,18 @@ fun JKType.isArrayType() =
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val JKType.isCollectionType: Boolean
|
||||||
|
get() = safeAs<JKClassType>()?.classReference?.fqName in collectionFqNames
|
||||||
|
|
||||||
|
private val collectionFqNames = setOf(
|
||||||
|
KotlinBuiltIns.FQ_NAMES.mutableIterator.asString(),
|
||||||
|
KotlinBuiltIns.FQ_NAMES.mutableList.asString(),
|
||||||
|
KotlinBuiltIns.FQ_NAMES.mutableCollection.asString(),
|
||||||
|
KotlinBuiltIns.FQ_NAMES.mutableSet.asString(),
|
||||||
|
KotlinBuiltIns.FQ_NAMES.mutableMap.asString(),
|
||||||
|
KotlinBuiltIns.FQ_NAMES.mutableMapEntry.asString(),
|
||||||
|
KotlinBuiltIns.FQ_NAMES.mutableListIterator.asString()
|
||||||
|
)
|
||||||
|
|
||||||
fun JKType.arrayInnerType(): JKType? =
|
fun JKType.arrayInnerType(): JKType? =
|
||||||
when (this) {
|
when (this) {
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ fun String.asSetterName() =
|
|||||||
?.decapitalize()
|
?.decapitalize()
|
||||||
?.escaped()
|
?.escaped()
|
||||||
|
|
||||||
|
fun String.isPossiblyGetterOrSetterName() =
|
||||||
|
asGetterName() != null || asSetterName() != null
|
||||||
|
|
||||||
|
|
||||||
private val KEYWORDS = KtTokens.KEYWORDS.types.map { (it as KtKeywordToken).value }.toSet()
|
private val KEYWORDS = KtTokens.KEYWORDS.types.map { (it as KtKeywordToken).value }.toSet()
|
||||||
|
|
||||||
fun String.escaped() =
|
fun String.escaped() =
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Test {
|
class Test {
|
||||||
fun foo() {
|
fun foo() {
|
||||||
val ss = Array</*T2@*/Array</*T1@*/String?>>(5/*LIT*/, { arrayOfNulls</*T0@*/String?>(5/*LIT*/)/*Array<T0@String!!U>!!L*/ }/*Function0<Int, T3@Array<T4@String>>!!L*/)
|
val ss = Array</*T2@*/Array</*T1@*/String?>>(5/*LIT*/, { arrayOfNulls</*T0@*/String>(5/*LIT*/)/*Array<T0@String!!U>!!L*/ }/*Function0<Int, T3@Array<T4@String>>!!L*/)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
fun test() {
|
fun test() {
|
||||||
val x: /*T2@*/Array</*T1@*/Int?> = arrayOfNulls</*T0@*/Int?>(10/*LIT*/)/*Array<T0@Int!!U>!!L*/
|
val x: /*T2@*/Array</*T1@*/Int?> = arrayOfNulls</*T0@*/Int>(10/*LIT*/)/*Array<T0@Int!!U>!!L*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//T1 := UPPER due to 'INITIALIZER'
|
//T1 := UPPER due to 'INITIALIZER'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
open class A<T> {
|
open class A<T> {
|
||||||
open fun foo(): /*T3@*/Map</*T0@*/T, /*T2@*/List</*T1@*/T>>? {
|
open fun foo(): /*T3@*/Map</*T0@*/T, /*T2@*/List</*T1@*/T>?>? {
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ open class A<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class B : A</*T10@*/Int>() {
|
class B : A</*T10@*/Int>() {
|
||||||
override fun foo(): /*T8@*/Map</*T5@*/Int, /*T7@*/List</*T6@*/Int>>? {
|
override fun foo(): /*T8@*/Map</*T5@*/Int, /*T7@*/List</*T6@*/Int>?>? {
|
||||||
return null/*NULL!!U*/
|
return null/*NULL!!U*/
|
||||||
}
|
}
|
||||||
override fun bar(): /*T9@*/Int {
|
override fun bar(): /*T9@*/Int {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
fun b(m: /*T2@*/Map</*T0@*/Int, /*T1@*/String>): /*T3@*/String? {
|
fun b(m: /*T2@*/Map</*T0@*/Int?, /*T1@*/String?>): /*T3@*/String? {
|
||||||
return m/*T2@Map<T0@Int, T1@String>*/.get(42/*LIT*/)/*T1@String!!U*/
|
return m/*T2@Map<T0@Int, T1@String>*/.get(42/*LIT*/)/*T1@String!!U*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
fun <T, E, F, S> foo(x: /*T0@*/T, y: /*T2@*/List</*T1@*/E>, z: /*T4@*/List</*T3@*/F>, a: /*T5@*/S) {}
|
fun <T, E, F, S> foo(x: /*T0@*/T, y: /*T2@*/List</*T1@*/E>?, z: /*T4@*/List</*T3@*/F>?, a: /*T5@*/S) {}
|
||||||
|
|
||||||
fun bar() {
|
fun bar() {
|
||||||
val lst: /*T8@*/List</*T7@*/Int?> = listOf</*T6@*/Int?>(null/*NULL!!U*/)/*List<T6@Int>!!L*/
|
val lst: /*T8@*/List</*T7@*/Int?> = listOf</*T6@*/Int?>(null/*NULL!!U*/)/*List<T6@Int>!!L*/
|
||||||
|
|||||||
+5
-5
@@ -1,6 +1,6 @@
|
|||||||
fun notNullParameters(f: /*T3@*/Function2</*T0@*/Int, /*T1@*/Int, /*T2@*/String>) {}
|
fun notNullParameters(f: /*T3@*/Function2</*T0@*/Int, /*T1@*/Int, /*T2@*/String?>?) {}
|
||||||
fun nullableParameter(f: /*T7@*/Function2</*T4@*/Int?, /*T5@*/Int, /*T6@*/String>) {}
|
fun nullableParameter(f: /*T7@*/Function2</*T4@*/Int?, /*T5@*/Int?, /*T6@*/String?>?) {}
|
||||||
fun nullableReturnType(f: /*T11@*/Function2</*T8@*/Int, /*T9@*/Int, /*T10@*/String?>) {}
|
fun nullableReturnType(f: /*T11@*/Function2</*T8@*/Int, /*T9@*/Int?, /*T10@*/String?>?) {}
|
||||||
|
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
@@ -8,11 +8,11 @@ fun test() {
|
|||||||
if (i/*T12@Int*/ < 10/*LIT*//*LIT*/ && j/*T13@Int*/ > 0/*LIT*//*LIT*//*LIT*/) ""/*LIT*/ else ""/*LIT*/
|
if (i/*T12@Int*/ < 10/*LIT*//*LIT*/ && j/*T13@Int*/ > 0/*LIT*//*LIT*//*LIT*/) ""/*LIT*/ else ""/*LIT*/
|
||||||
}/*Function2<T12@Int, T13@Int, T18@String>!!L*/)
|
}/*Function2<T12@Int, T13@Int, T18@String>!!L*/)
|
||||||
|
|
||||||
nullableParameter({ i: /*T14@*/Int?, j: /*T15@*/Int ->
|
nullableParameter({ i: /*T14@*/Int?, j: /*T15@*/Int? ->
|
||||||
if (i/*T14@Int*/ == null/*LIT*/) ""/*LIT*/ else ""/*LIT*/
|
if (i/*T14@Int*/ == null/*LIT*/) ""/*LIT*/ else ""/*LIT*/
|
||||||
}/*Function2<T14@Int, T15@Int, T19@String>!!L*/)
|
}/*Function2<T14@Int, T15@Int, T19@String>!!L*/)
|
||||||
|
|
||||||
nullableReturnType({ i: /*T16@*/Int, j: /*T17@*/Int ->
|
nullableReturnType({ i: /*T16@*/Int, j: /*T17@*/Int? ->
|
||||||
if (i/*T16@Int*/ < 10/*LIT*//*LIT*/) return@nullableReturnType null/*NULL!!U*/
|
if (i/*T16@Int*/ < 10/*LIT*//*LIT*/) return@nullableReturnType null/*NULL!!U*/
|
||||||
return@nullableReturnType "nya"/*LIT*/
|
return@nullableReturnType "nya"/*LIT*/
|
||||||
}/*Function2<T16@Int, T17@Int, T20@String>!!L*/)
|
}/*Function2<T16@Int, T17@Int, T20@String>!!L*/)
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ import java.util.stream.Stream
|
|||||||
fun test(list: /*T1@*/List</*T0@*/String>) {
|
fun test(list: /*T1@*/List</*T0@*/String>) {
|
||||||
val x: /*T9@*/List</*T8@*/String> = list/*T1@List<T0@String>*/.stream()/*Stream<T0@String>!!L*/
|
val x: /*T9@*/List</*T8@*/String> = list/*T1@List<T0@String>*/.stream()/*Stream<T0@String>!!L*/
|
||||||
.map</*T3@*/String>({ x: /*T2@*/String -> x/*T2@String*/ + ""/*LIT*//*LIT*/ }/*Function1<T2@String, T10@String>!!L*/)/*Stream<T3@String>*/
|
.map</*T3@*/String>({ x: /*T2@*/String -> x/*T2@String*/ + ""/*LIT*//*LIT*/ }/*Function1<T2@String, T10@String>!!L*/)/*Stream<T3@String>*/
|
||||||
.collect</*T6@*/List</*T5@*/String>, /*T7@*/Any?>(Collectors/*LIT*/.toList</*T4@*/String>()/*Collector<T4@String, Any, MutableList<T4@String>>*/)/*T6@List<T5@String>*/
|
.collect</*T6@*/List</*T5@*/String>, /*T7@*/Any>(Collectors/*LIT*/.toList</*T4@*/String>()/*Collector<T4@String, Any, MutableList<T4@String>>*/)/*T6@List<T5@String>*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
class Test {
|
class Test {
|
||||||
fun foo1(r: /*T2@*/Function1</*T0@*/Int, /*T1@*/String?>) {}
|
fun foo1(r: /*T2@*/Function1</*T0@*/Int, /*T1@*/String?>?) {}
|
||||||
fun foo() {
|
fun foo() {
|
||||||
foo1({ x: /*T3@*/Int -> ""/*LIT*/ }/*Function1<T3@Int, T5@String>!!L*/)
|
foo1({ x: /*T3@*/Int? -> ""/*LIT*/ }/*Function1<T3@Int, T5@String>!!L*/)
|
||||||
foo1({ i: /*T4@*/Int ->
|
foo1({ i: /*T4@*/Int ->
|
||||||
if (i/*T4@Int*/ > 1/*LIT*//*LIT*/) {
|
if (i/*T4@Int*/ > 1/*LIT*//*LIT*/) {
|
||||||
return@foo1 null/*NULL!!U*/
|
return@foo1 null/*NULL!!U*/
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
fun test(a: /*T1@*/List</*T0@*/Int>) {
|
fun test(a: /*T1@*/List</*T0@*/Int?>) {
|
||||||
for (i: /*T2@*/Int in a/*T1@List<T0@Int>*/) {
|
for (i: /*T2@*/Int? in a/*T1@List<T0@Int>*/) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
fun bar(map: /*T2@*/HashMap</*T0@*/String?, /*T1@*/Int>, list1: /*T4@*/List</*T3@*/Int>, list2: /*T6@*/List</*T5@*/String?>) {
|
fun bar(map: /*T2@*/HashMap</*T0@*/String?, /*T1@*/Int>, list1: /*T4@*/List</*T3@*/Int?>, list2: /*T6@*/List</*T5@*/String?>) {
|
||||||
for (entry: /*T9@*/MutableMap.MutableEntry</*T7@*/String?, /*T8@*/Int> in map/*T2@HashMap<T0@String, T1@Int>*/.entries/*MutableSet<MutableEntry<T0@String, T1@Int>>*/) {
|
for (entry: /*T9@*/MutableMap.MutableEntry</*T7@*/String?, /*T8@*/Int> in map/*T2@HashMap<T0@String, T1@Int>*/.entries/*MutableSet<MutableEntry<T0@String, T1@Int>>*/) {
|
||||||
val value: /*T10@*/Int = entry/*T9@MutableEntry<T7@String, T8@Int>*/.value/*T8@Int*/
|
val value: /*T10@*/Int = entry/*T9@MutableEntry<T7@String, T8@Int>*/.value/*T8@Int*/
|
||||||
if (entry/*T9@MutableEntry<T7@String, T8@Int>*/.key/*T7@String*/ == null/*LIT*/) {
|
if (entry/*T9@MutableEntry<T7@String, T8@Int>*/.key/*T7@String*/ == null/*LIT*/) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
fun a(lst: /*T1@*/List</*T0@*/String>) {
|
fun a(lst: /*T1@*/List</*T0@*/String>) {
|
||||||
val newList: /*T8@*/List</*T7@*/Int> = lst/*T1@List<T0@String>*/
|
val newList: /*T8@*/List</*T7@*/Int> = lst/*T1@List<T0@String>*/
|
||||||
.asSequence</*T2@*/String>()/*Sequence<T2@String>!!L*/
|
.asSequence</*T2@*/String>()/*Sequence<T2@String>!!L*/
|
||||||
.map</*T4@*/String, /*T5@*/Int>({ x: /*T3@*/String -> 1/*LIT*/ }/*Function1<T3@String, T9@Int>!!L*/)/*Sequence<T5@Int>!!L*/
|
.map</*T4@*/String, /*T5@*/Int>({ x: /*T3@*/String? -> 1/*LIT*/ }/*Function1<T3@String, T9@Int>!!L*/)/*Sequence<T5@Int>!!L*/
|
||||||
.toList</*T6@*/Int>()/*List<T6@Int>!!L*/
|
.toList</*T6@*/Int>()/*List<T6@Int>!!L*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
open class A<T> {
|
open class A<T> {
|
||||||
open fun foo(): /*T3@*/Map</*T0@*/T, /*T2@*/List</*T1@*/T>> {
|
open fun foo(): /*T3@*/Map</*T0@*/T, /*T2@*/List</*T1@*/T>?>? {
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ open class A<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class B : A</*T9@*/Int>() {
|
class B : A</*T9@*/Int>() {
|
||||||
override fun foo(): /*T8@*/Map</*T5@*/Int, /*T7@*/List</*T6@*/Int>> {
|
override fun foo(): /*T8@*/Map</*T5@*/Int, /*T7@*/List</*T6@*/Int>?>? {
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
open class A<T> {
|
open class A<T> {
|
||||||
open fun foo(x: /*T1@*/List</*T0@*/T>, y: /*T2@*/Boolean, z: /*T3@*/T) {
|
open fun foo(x: /*T1@*/List</*T0@*/T>?, y: /*T2@*/Boolean?, z: /*T3@*/T) {
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class B : A</*T8@*/Int>() {
|
class B : A</*T8@*/Int?>() {
|
||||||
override fun foo(x: /*T5@*/List</*T4@*/Int>, y: /*T6@*/Boolean, z: /*T7@*/Int) {
|
override fun foo(x: /*T5@*/List</*T4@*/Int?>?, y: /*T6@*/Boolean?, z: /*T7@*/Int?) {
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ class Test2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Handler {
|
class Handler {
|
||||||
fun postDelayed(r: Runnable, time: Long) {}
|
fun postDelayed(r: Runnable?, time: Long) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Test3 {
|
class Test3 {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
val a = arrayOfNulls<Any?>(10)
|
val a = arrayOfNulls<Any>(10)
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
val d2 = arrayOfNulls<IntArray?>(5)
|
val d2 = arrayOfNulls<IntArray>(5)
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
val d3 = Array(5) { arrayOfNulls<IntArray?>(5) }
|
val d3 = Array(5) { arrayOfNulls<IntArray>(5) }
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
val ss = Array(5) { arrayOfNulls<String?>(5) }
|
val ss = Array(5) { arrayOfNulls<String>(5) }
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
val sss = Array(5) { Array(5) { arrayOfNulls<String?>(5) } }
|
val sss = Array(5) { Array(5) { arrayOfNulls<String>(5) } }
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
internal class Test {
|
internal class Test {
|
||||||
fun test() {
|
fun test() {
|
||||||
val i: Int? = Integer.valueOf(100)
|
val i = Integer.valueOf(100)
|
||||||
val s: Short = 3
|
val s: Short = 3
|
||||||
val ss = s
|
val ss = s
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
class Integer(s: String) {
|
class Integer(s: String?) {
|
||||||
companion object {
|
companion object {
|
||||||
fun valueOf(value: String): Integer {
|
fun valueOf(value: String?): Integer {
|
||||||
return Integer(value)
|
return Integer(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
internal class T {
|
internal class T {
|
||||||
fun main() {}
|
fun main() {}
|
||||||
fun i(): Int {}
|
fun i(): Int {}
|
||||||
fun s(): String? {}
|
fun s(): String {}
|
||||||
}
|
}
|
||||||
Vendored
+1
-1
@@ -4,7 +4,7 @@ import java.util.HashMap
|
|||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
constructor(s: String) {}
|
constructor(s: String?) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class User {
|
internal class User {
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
internal open class Base(o: Any, l: Int)
|
internal open class Base(o: Any?, l: Int)
|
||||||
internal class C(private val string: String) : Base(string, string.length)
|
internal class C(private val string: String) : Base(string, string.length)
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)) {
|
internal class A @JvmOverloads constructor(nested: Nested? = Nested(Nested.FIELD)) {
|
||||||
|
|
||||||
internal class Nested(p: Int) {
|
internal class Nested(p: Int) {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val FIELD = 0
|
const val FIELD = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import A.Nested
|
import A.Nested
|
||||||
|
|
||||||
internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)) {
|
internal class A @JvmOverloads constructor(nested: Nested? = Nested(Nested.FIELD)) {
|
||||||
internal class Nested(p: Int) {
|
internal class Nested(p: Int) {
|
||||||
companion object {
|
companion object {
|
||||||
const val FIELD = 0
|
const val FIELD = 0
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package pack
|
|||||||
|
|
||||||
import pack.A.Nested
|
import pack.A.Nested
|
||||||
|
|
||||||
internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)) {
|
internal class A @JvmOverloads constructor(nested: Nested? = Nested(Nested.FIELD)) {
|
||||||
internal class Nested(p: Int) {
|
internal class Nested(p: Int) {
|
||||||
companion object {
|
companion object {
|
||||||
const val FIELD = 0
|
const val FIELD = 0
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package pack
|
|||||||
|
|
||||||
import pack.A.Nested
|
import pack.A.Nested
|
||||||
|
|
||||||
internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)) {
|
internal class A @JvmOverloads constructor(nested: Nested? = Nested(Nested.FIELD)) {
|
||||||
internal class Nested(p: Int) {
|
internal class Nested(p: Int) {
|
||||||
companion object {
|
companion object {
|
||||||
const val FIELD = 0
|
const val FIELD = 0
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
internal open class Base(nested: Nested) {
|
internal open class Base(nested: Nested?) {
|
||||||
internal class Nested(p: Int) {
|
internal class Nested(p: Int) {
|
||||||
companion object {
|
companion object {
|
||||||
const val FIELD = 0
|
const val FIELD = 0
|
||||||
|
|||||||
@@ -10,14 +10,12 @@ class Test {
|
|||||||
protected var g = 0.toChar()
|
protected var g = 0.toChar()
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
constructor(name: String?) {
|
||||||
constructor(name: String) {
|
|
||||||
myName = foo(name)
|
myName = foo(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
internal fun foo(n: String?): String {
|
||||||
internal fun foo(n: String): String {
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
internal class C {
|
internal class C {
|
||||||
fun equals(c: C): Boolean {
|
fun equals(c: C?): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo(c1: C, c2: C): Boolean {
|
fun foo(c1: C, c2: C?): Boolean {
|
||||||
return c1.equals(c2)
|
return c1.equals(c2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,13 +1,13 @@
|
|||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
internal class C {
|
internal class C {
|
||||||
fun foo1(list: MutableList<String>) {
|
fun foo1(list: MutableList<String?>) {
|
||||||
for (i in list.indices) {
|
for (i in list.indices) {
|
||||||
list[i] = "a"
|
list[i] = "a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo2(list: ArrayList<String>) {
|
fun foo2(list: ArrayList<String?>) {
|
||||||
for (i in list.indices) {
|
for (i in list.indices) {
|
||||||
list[i] = "a"
|
list[i] = "a"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
internal class C {
|
internal class C {
|
||||||
fun foo(list: MutableList<String>) {
|
fun foo(list: MutableList<String?>) {
|
||||||
for (i in list.indices) {
|
for (i in list.indices) {
|
||||||
list[i] = "a"
|
list[i] = "a"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
internal class A {
|
internal class A {
|
||||||
var list: List<String>? = null
|
var list: List<String?>? = null
|
||||||
fun foo() {
|
fun foo() {
|
||||||
for (e in list!!) {
|
for (e in list!!) {
|
||||||
println(e)
|
println(e)
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
val t: T?
|
val t: T
|
||||||
get() {}
|
get() {}
|
||||||
@@ -11,6 +11,6 @@ internal class Test {
|
|||||||
fun nya(): Double {
|
fun nya(): Double {
|
||||||
//TODO explicitlly call apply here
|
//TODO explicitlly call apply here
|
||||||
|
|
||||||
return foo(1, FunctionalI<Int?, Double?> { x: Int -> this.toDouble(x) })
|
return foo(1, FunctionalI<Int, Double> { x: Int -> this.toDouble(x) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,6 @@ internal class Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun nya(): Double {
|
fun nya(): Double {
|
||||||
return foo(1, FunctionalI<Int?, Double?> { x: A -> this.toDouble(x) })
|
return foo(1, FunctionalI<Int, Double> { x: A -> this.toDouble(x) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+9
-9
@@ -1,7 +1,7 @@
|
|||||||
class Java8Class {
|
class Java8Class {
|
||||||
fun foo0(r: Function0<String>) {}
|
fun foo0(r: Function0<String?>?) {}
|
||||||
fun foo1(r: Function1<Int, String?>) {}
|
fun foo1(r: Function1<Int, String?>?) {}
|
||||||
fun foo2(r: Function2<Int, Int, String>) {}
|
fun foo2(r: Function2<Int?, Int?, String?>?) {}
|
||||||
fun helper() {}
|
fun helper() {}
|
||||||
fun foo() {
|
fun foo() {
|
||||||
foo0 { "42" }
|
foo0 { "42" }
|
||||||
@@ -10,8 +10,8 @@ class Java8Class {
|
|||||||
helper()
|
helper()
|
||||||
"42"
|
"42"
|
||||||
}
|
}
|
||||||
foo1 { i: Int -> "42" }
|
foo1 { i: Int? -> "42" }
|
||||||
foo1 { i: Int -> "42" }
|
foo1 { i: Int? -> "42" }
|
||||||
foo1 { i: Int ->
|
foo1 { i: Int ->
|
||||||
helper()
|
helper()
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
@@ -19,12 +19,12 @@ class Java8Class {
|
|||||||
}
|
}
|
||||||
"43"
|
"43"
|
||||||
}
|
}
|
||||||
foo2 { i: Int, j: Int -> "42" }
|
foo2 { i: Int?, j: Int? -> "42" }
|
||||||
foo2 { i: Int, j: Int ->
|
foo2 { i: Int?, j: Int? ->
|
||||||
helper()
|
helper()
|
||||||
"42"
|
"42"
|
||||||
}
|
}
|
||||||
val f = label@{ i: Int, k: Int ->
|
val f: Function2<Int, Int, String> = label@{ i: Int, k: Int? ->
|
||||||
helper()
|
helper()
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
return@label "42"
|
return@label "42"
|
||||||
@@ -32,7 +32,7 @@ class Java8Class {
|
|||||||
"43"
|
"43"
|
||||||
}
|
}
|
||||||
val f1 = label@{ i1: Int, k1: Int ->
|
val f1 = label@{ i1: Int, k1: Int ->
|
||||||
val f2 = label@{ i2: Int, k2: Int ->
|
val f2: Function2<Int, Int, String> = label@{ i2: Int, k2: Int? ->
|
||||||
helper()
|
helper()
|
||||||
if (i2 > 1) {
|
if (i2 > 1) {
|
||||||
return@label "42"
|
return@label "42"
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
fun main(): String? {}
|
fun main(): String {}
|
||||||
+3
-3
@@ -4,7 +4,7 @@ import java.util.stream.Collectors
|
|||||||
object TestLambda {
|
object TestLambda {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val names: List<String> = Arrays.asList("A", "B")
|
val names = Arrays.asList("A", "B")
|
||||||
val people: List<Person?> = names.stream().map { name: String -> Person(name) }.collect(Collectors.toList())
|
val people = names.stream().map { name: String? -> Person(name) }.collect(Collectors.toList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
package demo
|
package demo
|
||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun test(vararg args: Any) {
|
fun test(vararg args: Any?) {
|
||||||
var args = args
|
var args = args
|
||||||
args = arrayOf(1, 2, 3)
|
args = arrayOf<Int?>(1, 2, 3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
internal open class Base(name: String)
|
internal open class Base(name: String?)
|
||||||
internal class One(name: String, second: String?) : Base(name)
|
internal class One(name: String?, second: String?) : Base(name)
|
||||||
+2
-2
@@ -1,2 +1,2 @@
|
|||||||
internal open class Base(name: String)
|
internal open class Base(name: String?)
|
||||||
internal class One(name: String, private val mySecond: String) : Base(name)
|
internal class One(name: String?, private val mySecond: String) : Base(name)
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
class TestReturnsArray {
|
class TestReturnsArray {
|
||||||
fun strings(n: Int): Array<String?> {
|
fun strings(n: Int): Array<String?> {
|
||||||
val result = arrayOfNulls<String?>(n)
|
val result = arrayOfNulls<String>(n)
|
||||||
for (i in 0 until n) {
|
for (i in 0 until n) {
|
||||||
result[i] = Integer.toString(i)
|
result[i] = Integer.toString(i)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ class TestMutltipleCtorsWithJavadoc
|
|||||||
/**
|
/**
|
||||||
* Javadoc for 1st ctor
|
* Javadoc for 1st ctor
|
||||||
* @param x
|
* @param x
|
||||||
*/(private val x: String) {
|
*/(private val x: String?) {
|
||||||
private var y: String? = null
|
private var y: String? = null
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
@@ -14,7 +14,7 @@ class TestMutltipleCtorsWithJavadoc
|
|||||||
* @param x
|
* @param x
|
||||||
* @param y
|
* @param y
|
||||||
*/
|
*/
|
||||||
constructor(x: String, y: String?) : this(x) {
|
constructor(x: String?, y: String?) : this(x) {
|
||||||
this.y = y
|
this.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ package test
|
|||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
|
||||||
class TestPrimitiveFromMap {
|
class TestPrimitiveFromMap {
|
||||||
fun foo(map: HashMap<String, Int>): Int {
|
fun foo(map: HashMap<String?, Int?>): Int {
|
||||||
return map["zzz"]!!
|
return map["zzz"]!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
class TestMapGetAsReceiver {
|
class TestMapGetAsReceiver {
|
||||||
fun foo(map: Map<String, String>): Int {
|
fun foo(map: Map<String?, String>): Int {
|
||||||
return map["zzz"]!!.length
|
return map["zzz"]!!.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
class TestValReassign(private val s1: String) {
|
class TestValReassign(private val s1: String?) {
|
||||||
private var s2: String? = null
|
private var s2: String? = null
|
||||||
|
|
||||||
constructor(s1: String, s2: String?) : this(s1) {
|
constructor(s1: String?, s2: String?) : this(s1) {
|
||||||
this.s2 = s2
|
this.s2 = s2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -3,13 +3,13 @@ class TestToStringReturnsNullable {
|
|||||||
var string: String? = null
|
var string: String? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
open class Ctor(string: String) : Base() {
|
open class Ctor(string: String?) : Base() {
|
||||||
init {
|
init {
|
||||||
this.string = string
|
this.string = string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Derived(string: String) : Ctor(string) {
|
class Derived(string: String?) : Ctor(string) {
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return string!!
|
return string!!
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ class TestJavaExpectedTypeInference {
|
|||||||
fun test(node: DefaultMutableTreeNode) {
|
fun test(node: DefaultMutableTreeNode) {
|
||||||
val e: Enumeration<DefaultMutableTreeNode> = node.children()
|
val e: Enumeration<DefaultMutableTreeNode> = node.children()
|
||||||
while (e.hasMoreElements()) {
|
while (e.hasMoreElements()) {
|
||||||
val child: DefaultMutableTreeNode = e.nextElement()
|
val child = e.nextElement()
|
||||||
val name = child.userObject as String
|
val name = child.userObject as String
|
||||||
println(name)
|
println(name)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
internal interface FooInterface {
|
internal interface FooInterface {
|
||||||
fun foo(): ArrayList<out Foo.SomeClass>?
|
fun foo(): ArrayList<out Foo.SomeClass?>?
|
||||||
}
|
}
|
||||||
|
|
||||||
class Foo : FooInterface {
|
class Foo : FooInterface {
|
||||||
override fun foo(): ArrayList<SomeClass>? {
|
override fun foo(): ArrayList<SomeClass?>? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -5,6 +5,6 @@ internal class Test {
|
|||||||
fun context() {
|
fun context() {
|
||||||
val items: MutableList<Double> = ArrayList()
|
val items: MutableList<Double> = ArrayList()
|
||||||
items.add(1.0)
|
items.add(1.0)
|
||||||
items.forEach(Consumer { o: Double -> println(o) })
|
items.forEach(Consumer { o: Double? -> println(o) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
internal class X(private val list: List<Y>) {
|
internal class X(private val list: MutableList<Y>) {
|
||||||
|
|
||||||
internal inner class Y
|
internal inner class Y
|
||||||
}
|
}
|
||||||
+1
-3
@@ -1,12 +1,10 @@
|
|||||||
package demo
|
package demo
|
||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun putInt(i: Int) {}
|
fun putInt(i: Int?) {}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val b: Byte = 10
|
val b: Byte = 10
|
||||||
putInt(b.toInt())
|
putInt(b.toInt())
|
||||||
|
|
||||||
val b2: Byte = 10
|
val b2: Byte = 10
|
||||||
putInt(b2.toInt())
|
putInt(b2.toInt())
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -1,8 +1,7 @@
|
|||||||
package demo
|
package demo
|
||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun putInt(i: Int) {}
|
fun putInt(i: Int?) {}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val i = 10
|
val i = 10
|
||||||
putInt(i)
|
putInt(i)
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package demo
|
package demo
|
||||||
|
|
||||||
internal class Test(i: Int) {
|
internal class Test(i: Int?) {
|
||||||
fun test() {
|
fun test() {
|
||||||
val i = 10
|
val i = 10
|
||||||
Test(i)
|
Test(i)
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ internal object FileRead {
|
|||||||
val fstream = FileInputStream(File("file.txt"))
|
val fstream = FileInputStream(File("file.txt"))
|
||||||
val `in` = DataInputStream(fstream)
|
val `in` = DataInputStream(fstream)
|
||||||
val br = BufferedReader(InputStreamReader(`in`))
|
val br = BufferedReader(InputStreamReader(`in`))
|
||||||
var strLine: String
|
var strLine: String?
|
||||||
while (br.readLine().also { strLine = it } != null) {
|
while (br.readLine().also { strLine = it } != null) {
|
||||||
println(strLine)
|
println(strLine)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -8,9 +8,9 @@ internal object One {
|
|||||||
var myContainer = Container()
|
var myContainer = Container()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class StringContainer(s: String)
|
internal class StringContainer(s: String?)
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun putString(s: String) {}
|
fun putString(s: String?) {}
|
||||||
fun test() {
|
fun test() {
|
||||||
putString(One.myContainer.myString)
|
putString(One.myContainer.myString)
|
||||||
StringContainer(One.myContainer.myString)
|
StringContainer(One.myContainer.myString)
|
||||||
|
|||||||
+3
-3
@@ -2,12 +2,12 @@ object ArrayNullable {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val notNull = 0
|
val notNull = 0
|
||||||
val a1 = arrayOfNulls<Int?>(2)
|
val a1 = arrayOfNulls<Int>(2)
|
||||||
a1[0] = null
|
a1[0] = null
|
||||||
a1[1] = notNull
|
a1[1] = notNull
|
||||||
println(a1[0])
|
println(a1[0])
|
||||||
println(a1[1])
|
println(a1[1])
|
||||||
val a2 = arrayOfNulls<Int?>(2)
|
val a2 = arrayOfNulls<Int>(2)
|
||||||
a2[0] = nullable()
|
a2[0] = nullable()
|
||||||
a2[1] = notNull
|
a2[1] = notNull
|
||||||
println(a2[0])
|
println(a2[0])
|
||||||
@@ -21,4 +21,4 @@ object ArrayNullable {
|
|||||||
fun nullable(): Int? {
|
fun nullable(): Int? {
|
||||||
return if (System.getProperty("user.home").length > 20) null else 1
|
return if (System.getProperty("user.home").length > 20) null else 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -2,12 +2,12 @@ import java.util.stream.Collectors
|
|||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun main(lst: List<String>) {
|
fun main(lst: List<String>) {
|
||||||
val toList: List<String> = lst.stream().collect(Collectors.toList())
|
val toList = lst.stream().collect(Collectors.toList())
|
||||||
val toSet: Set<String> = lst.stream().collect(Collectors.toSet())
|
val toSet = lst.stream().collect(Collectors.toSet())
|
||||||
val count = lst.stream().count()
|
val count = lst.stream().count()
|
||||||
val anyMatch = lst.stream().anyMatch { v: String -> v.isEmpty() }
|
val anyMatch = lst.stream().anyMatch { v: String -> v.isEmpty() }
|
||||||
val allMatch = lst.stream().allMatch { v: String -> v.isEmpty() }
|
val allMatch = lst.stream().allMatch { v: String -> v.isEmpty() }
|
||||||
val noneMatch = lst.stream().noneMatch { v: String -> v.isEmpty() }
|
val noneMatch = lst.stream().noneMatch { v: String -> v.isEmpty() }
|
||||||
lst.stream().forEach { v: String -> println(v) }
|
lst.stream().forEach { v: String? -> println(v) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-6
@@ -4,23 +4,23 @@ import java.util.stream.Stream
|
|||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun main(lst: List<String>) {
|
fun main(lst: List<String>) {
|
||||||
val streamOfList: List<String> = lst.stream()
|
val streamOfList = lst.stream()
|
||||||
.map { x: String -> x + "e" }
|
.map { x: String -> x + "e" }
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
val streamOfElements: List<Int> = Stream.of(1, 2, 3)
|
val streamOfElements = Stream.of(1, 2, 3)
|
||||||
.map { x: Int -> x + 1 }
|
.map { x: Int -> x + 1 }
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
val array = arrayOf(1, 2, 3)
|
val array = arrayOf(1, 2, 3)
|
||||||
val streamOfArray: List<Int> = Arrays.stream(array)
|
val streamOfArray = Arrays.stream(array)
|
||||||
.map { x: Int -> x + 1 }
|
.map { x: Int -> x + 1 }
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
val streamOfArray2: List<Int> = Stream.of(*array)
|
val streamOfArray2 = Stream.of(*array)
|
||||||
.map { x: Int -> x + 1 }
|
.map { x: Int -> x + 1 }
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
val streamIterate: List<Int> = Stream.iterate(2, { v: Int -> v * 2 })
|
val streamIterate = Stream.iterate(2, { v: Int -> v * 2 })
|
||||||
.map { x: Int -> x + 1 }
|
.map { x: Int -> x + 1 }
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
val streamGenerate: List<Int> = Stream.generate { 42 }
|
val streamGenerate = Stream.generate { 42 }
|
||||||
.map { x: Int -> x + 1 }
|
.map { x: Int -> x + 1 }
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import java.util.stream.Stream
|
|||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun main(lst: List<String?>?) {
|
fun main(lst: List<String?>?) {
|
||||||
val stream: Stream<Int> = Stream.of(1)
|
val stream = Stream.of(1)
|
||||||
val list: List<Int> = stream.collect(Collectors.toList())
|
val list = stream.collect(Collectors.toList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -3,11 +3,11 @@ import java.util.stream.Collectors
|
|||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun main(lst: List<Int>) {
|
fun main(lst: List<Int>) {
|
||||||
val newLst: List<Int> = /*before list*/lst/*after list*/.stream/*before stream*/()/* after stream*/
|
val newLst = /*before list*/lst/*after list*/.stream/*before stream*/()/* after stream*/
|
||||||
.filter { x: Int -> x > 10 }
|
.filter { x: Int -> x > 10 }
|
||||||
.map { x: Int -> x + 2 }/*some comment*/.distinct/*another comment*/()/* one more comment */.sorted()/*another one comment*/
|
.map { x: Int -> x + 2 }/*some comment*/.distinct/*another comment*/()/* one more comment */.sorted()/*another one comment*/
|
||||||
.sorted(Comparator.naturalOrder())
|
.sorted(Comparator.naturalOrder())
|
||||||
.peek { x: Int -> println(x) }.limit(1)
|
.peek { x: Int? -> println(x) }.limit(1)
|
||||||
.skip(42)/*skipped*/
|
.skip(42)/*skipped*/
|
||||||
/*collecting one*/.collect/*collecting two */(Collectors.toList())/* cool */
|
/*collecting one*/.collect/*collecting two */(Collectors.toList())/* cool */
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,14 +3,14 @@ import java.util.stream.Stream
|
|||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun main() {
|
fun main() {
|
||||||
val activities: List<String> = Stream.of("12")
|
val activities = Stream.of("12")
|
||||||
.map { v: String -> v + "nya" }
|
.map { v: String -> v + "nya" }
|
||||||
.filter { v: String? -> v != null }
|
.filter { v: String? -> v != null }
|
||||||
.flatMap { v: String ->
|
.flatMap { v: String ->
|
||||||
Stream.of(v)
|
Stream.of(v)
|
||||||
.flatMap { s: String -> Stream.of(s) }
|
.flatMap { s: String -> Stream.of(s) }
|
||||||
}.filter { v: String ->
|
}.filter { v: String ->
|
||||||
val name: String = v.javaClass.name
|
val name = v.javaClass.name
|
||||||
if (name == "name") {
|
if (name == "name") {
|
||||||
return@filter false
|
return@filter false
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,13 +3,13 @@ import java.util.stream.Collectors
|
|||||||
|
|
||||||
internal class Test {
|
internal class Test {
|
||||||
fun main(lst: List<Int>) {
|
fun main(lst: List<Int>) {
|
||||||
val newLst: List<Int> = lst.stream()
|
val newLst = lst.stream()
|
||||||
.filter { x: Int -> x > 10 }
|
.filter { x: Int -> x > 10 }
|
||||||
.map { x: Int -> x + 2 }
|
.map { x: Int -> x + 2 }
|
||||||
.distinct()
|
.distinct()
|
||||||
.sorted()
|
.sorted()
|
||||||
.sorted(Comparator.naturalOrder())
|
.sorted(Comparator.naturalOrder())
|
||||||
.peek { x: Int -> println(x) }
|
.peek { x: Int? -> println(x) }
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.skip(42)
|
.skip(42)
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
|
|||||||
Vendored
+1
-1
@@ -4,7 +4,7 @@ import java.util.ArrayList
|
|||||||
class ForEach {
|
class ForEach {
|
||||||
fun test() {
|
fun test() {
|
||||||
val xs = ArrayList<Any>()
|
val xs = ArrayList<Any>()
|
||||||
val ys: MutableList<Any> = LinkedList<Any?>()
|
val ys: MutableList<Any> = LinkedList<Any>()
|
||||||
for (x in xs) {
|
for (x in xs) {
|
||||||
ys.add(x)
|
ys.add(x)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -4,7 +4,7 @@ import java.util.ArrayList
|
|||||||
class Lists {
|
class Lists {
|
||||||
fun test() {
|
fun test() {
|
||||||
val xs: MutableList<Any?> = ArrayList()
|
val xs: MutableList<Any?> = ArrayList()
|
||||||
val ys: MutableList<Any?> = LinkedList<Any?>()
|
val ys: MutableList<Any?> = LinkedList<Any>()
|
||||||
val zs = ArrayList<Any?>()
|
val zs = ArrayList<Any?>()
|
||||||
xs.add(null)
|
xs.add(null)
|
||||||
ys.add(null)
|
ys.add(null)
|
||||||
|
|||||||
+1
-3
@@ -9,10 +9,8 @@ internal class A {
|
|||||||
private val d8 = 1.0
|
private val d8 = 1.0
|
||||||
private val d9 = 1.0
|
private val d9 = 1.0
|
||||||
private val x = 1 / (1.0 + 0)
|
private val x = 1 / (1.0 + 0)
|
||||||
|
|
||||||
fun foo1(d: Double) {}
|
fun foo1(d: Double) {}
|
||||||
fun foo2(d: Double) {}
|
fun foo2(d: Double?) {}
|
||||||
|
|
||||||
fun bar() {
|
fun bar() {
|
||||||
foo1(1.0)
|
foo1(1.0)
|
||||||
foo1(1.0)
|
foo1(1.0)
|
||||||
|
|||||||
+1
-3
@@ -9,10 +9,8 @@ internal class A {
|
|||||||
private val f8 = +1f
|
private val f8 = +1f
|
||||||
private val f9 = 1f
|
private val f9 = 1f
|
||||||
private val f10 = 1f
|
private val f10 = 1f
|
||||||
|
|
||||||
fun foo1(f: Float) {}
|
fun foo1(f: Float) {}
|
||||||
fun foo2(f: Float) {}
|
fun foo2(f: Float?) {}
|
||||||
|
|
||||||
fun bar() {
|
fun bar() {
|
||||||
foo1(1f)
|
foo1(1f)
|
||||||
foo2(1f)
|
foo2(1f)
|
||||||
|
|||||||
+1
-3
@@ -7,10 +7,8 @@ internal class A {
|
|||||||
private val l6 = -123456789101112
|
private val l6 = -123456789101112
|
||||||
private val l7: Long = +1
|
private val l7: Long = +1
|
||||||
private val l8 = +1L
|
private val l8 = +1L
|
||||||
|
|
||||||
fun foo1(l: Long) {}
|
fun foo1(l: Long) {}
|
||||||
fun foo2(l: Long) {}
|
fun foo2(l: Long?) {}
|
||||||
|
|
||||||
fun bar() {
|
fun bar() {
|
||||||
foo1(1)
|
foo1(1)
|
||||||
foo1(1L)
|
foo1(1L)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user