From 2bd5a1f1960940d43ae723cda0c28fb916eda67f Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 25 Jul 2019 00:31:50 +0300 Subject: [PATCH] New J2K: separate nullability inference from common one & nullability bug fixes It will be needed for structure mutability inference #KT-21467 fixed #KT-32609 fixed #KT-32572 fixed #KT-24677 fixed --- .../kotlin/generators/tests/GenerateTests.kt | 27 +- .../generators/tests/GenerateTests.kt.183 | 12 +- .../generators/tests/GenerateTests.kt.as33 | 12 +- .../generators/tests/GenerateTests.kt.as34 | 12 +- .../generators/tests/GenerateTests.kt.as35 | 12 +- .../jetbrains/kotlin/idea/test/testUtils.kt | 22 +- ...ractJavaToKotlinConverterSingleFileTest.kt | 19 +- .../inference/common/BoundTypeCalculator.kt | 259 +++++++++++++++ .../inference/common/BoundTypeEnhancer.kt | 39 +++ .../nj2k/inference/common/ClassSubstitutor.kt | 38 +++ .../nj2k/inference/common/Constraint.kt | 81 +++++ .../inference/common/ConstraintBuilder.kt | 136 ++++++++ .../common/ConstraintsCollectorAggregator.kt | 42 +++ .../nj2k/inference/common/ContextCollector.kt | 196 +++++++++++ .../nj2k/inference/common/DebugPrinter.kt | 81 +++++ .../nj2k/inference/common/InferenceContext.kt | 32 ++ .../nj2k/inference/common/InferenceFacade.kt | 52 +++ .../solver.kt => inference/common/Solver.kt} | 93 +++--- .../kotlin/nj2k/inference/common/State.kt | 12 + .../nj2k/inference/common/StateUpdater.kt | 10 + .../common/SuperFunctionsProvider.kt | 58 ++++ .../nj2k/inference/common/boundTypes.kt | 79 +++++ .../CallExpressionConstraintCollector.kt | 112 +++++++ .../collectors/CommonConstraintsCollector.kt | 135 ++++++++ .../common/collectors/ConstraintsCollector.kt | 21 ++ .../FunctionConstraintsCollector.kt | 105 ++++++ .../nj2k/inference/common/typeVariables.kt | 94 ++++++ .../kotlin/nj2k/inference/common/utils.kt | 30 ++ .../NullabilityBoundTypeEnhancer.kt | 117 +++++++ .../NullabilityConstraintsCollector.kt | 55 ++++ .../NullabilityContextCollector.kt | 43 +++ .../nullability/NullabilityStateUpdater.kt | 56 ++++ .../nullabilityAnalysis/BoundTypeStorage.kt | 203 ------------ .../nullabilityAnalysis/ConstraintBuilder.kt | 63 ---- .../nj2k/nullabilityAnalysis/constraints.kt | 253 -------------- .../constraintsCollector.kt | 310 ------------------ .../nj2k/nullabilityAnalysis/context.kt | 159 --------- .../nullabilityAnalysis.kt | 133 -------- .../nj2k/nullabilityAnalysis/printing.kt | 85 ----- .../kotlin/nj2k/nullabilityAnalysis/utils.kt | 73 ----- .../nj2k/postProcessing/J2kPostProcessor.kt | 6 +- .../processings/inspeҁtionLikeProcessings.kt | 25 +- .../postProcessing/processings/processings.kt | 73 ++++- .../jetbrains/kotlin/nj2k/NewCodeBuilder.kt | 29 +- .../conversions/AddElementsInfoConversion.kt | 8 +- .../SeveralMethodsSample.expected.kt | 6 +- .../AsExpression.expected.kt | 2 +- .../AsExpressionBody.expected.kt | 2 +- .../ImportFromTarget.expected.kt | 2 +- .../ImportResolve.expected.kt | 8 +- .../copyPastePlainText/KT13529_1.expected.kt | 2 +- .../PostProcessing.expected.kt | 2 +- .../inference/common/arrayAssignment.kt | 8 + .../inference/common/arrayOfArrays.kt | 16 + ...callFunctionWithTypeParamFromOuterScope.kt | 12 + .../inference/common/callWithTypeParams.kt | 9 + .../inference/common/constructorCall.kt | 15 + .../common/delegationConstructorCall.kt | 5 + .../common/elementOfArrayAssignment.kt | 14 + .../common/elementOfListAssignment.kt | 14 + nj2k/testData/inference/common/forLoop.kt | 10 + .../testData/inference/common/functionCall.kt | 10 + .../inference/common/functionReturn.kt | 7 + .../common/functionWithTypeParamCall.kt | 11 + .../inference/common/lambdaAsParameter.kt | 11 + .../testData/inference/common/lambdaAssign.kt | 8 + .../inference/common/lambdaImplicitReturn.kt | 12 + .../testData/inference/common/lambdaReturn.kt | 21 ++ .../inference/common/listAssignment.kt | 8 + .../inference/common/listGenerator.kt | 7 + nj2k/testData/inference/common/listOfLists.kt | 12 + .../inference/common/listOfListsGenerator.kt | 16 + nj2k/testData/inference/common/memberCall.kt | 16 + .../inference/common/returnFromLambda.kt | 16 + .../inference/common/sequenceOfCalls.kt | 9 + .../common/sequenceOfCallsWIthLambda.kt | 14 + .../inference/common/simpleAssignment.kt | 9 + nj2k/testData/inference/common/superCall.kt | 14 + .../inference/common/superConstuctorCall.kt | 7 + ...perFunctionReturnTypeWithTypeParameters.kt | 15 + ...eturnTypeWithTypeParametersSubstitution.kt | 13 + .../inference/common/superFunctionType.kt | 13 + .../inference/common/typeParamsBounds.kt | 5 + .../inference/common/varargsInCall.kt | 14 + .../nullability/arrayOfArraysOfNull.kt | 10 + .../inference/nullability/arrayOfNulls.kt | 6 + .../nullability/binaryExpressionOperand.kt | 7 + .../callExternallyAnnotatedJavaFunction.kt | 11 + .../nullability/classTypeParameters.kt | 27 ++ .../inference/nullability/compareWithNull.kt | 19 ++ .../nullability/forcedNullability.kt | 9 + .../functionTypeParameterNullability.kt | 20 ++ .../inference/nullability/functions.kt | 40 +++ .../inference/nullability/ifCondition.kt | 5 + .../inference/nullability/javaStream.kt | 25 ++ .../inference/nullability/lambdaReturnNull.kt | 23 ++ .../nullability/listOfWithNullLiteral.kt | 9 + .../inference/nullability/loopIterator.kt | 8 + nj2k/testData/inference/nullability/loops.kt | 31 ++ .../nullability/notNullCallSequence.kt | 16 + .../inference/nullability/nullAsAssignment.kt | 18 + .../nullability/nullAsInitializer.kt | 5 + .../inference/nullability/nullLiteral.kt | 5 + .../inference/nullability/returnNull.kt | 5 + .../nullability/sequenceOfCallsWIthLambda.kt | 16 + .../inference/nullability/smartCast.kt | 7 + .../inference/nullability/spreadExpression.kt | 9 + .../inference/nullability/superMethod.kt | 18 + .../inference/nullability/typeCast.kt | 18 + .../inference/nullability/typeParameters.kt | 20 ++ .../nullability/typeParametersReturnType.kt | 20 ++ .../nullability/typeParametersValueParams.kt | 16 + .../inference/nullability/useAsReceiver.kt | 9 + .../inference/nullability/whileCondition.kt | 5 + .../arrayAccessExpression/expressionIndex.kt | 2 +- .../newJ2k/arrayAccessExpression/intIndex.kt | 2 +- .../arrayAccessExpression/variableIndex.kt | 2 +- .../objectArrayWithLength.kt | 2 +- ...rayInitializationStatementWithDimension.kt | 2 +- ...yInitializationStatementWithDimension3d.kt | 2 +- .../newJ2k/arrayType/d2StringEmptyArray.kt | 2 +- .../newJ2k/arrayType/d3StringEmptyArray.kt | 2 +- nj2k/testData/newJ2k/boxedType/kt-671.kt | 2 +- nj2k/testData/newJ2k/class/ClassShadowing.kt | 2 +- nj2k/testData/newJ2k/class/kt-639.kt | 5 +- .../fieldsInitializedFromParams8.kt | 5 +- .../newJ2k/constructors/genericIdentifier.kt | 7 +- .../nestedClassNameInSuperParameters.kt | 2 +- .../OverridesOfExternalCode.kt | 4 +- .../function/externalKtFunctionalInterface.kt | 2 +- .../function/internalFunctionalInterface.kt | 5 +- .../newJ2k/function/ownGenericParam.kt | 2 +- .../function/ownSeveralGenericParams.kt | 2 +- .../inheritance/classOneExtendsBaseGeneric.kt | 5 +- .../classOneExtendsBaseWithOneParam.kt | 5 +- ...dsBaseWithZeroParamsNonEmptyConstructor.kt | 5 +- nj2k/testData/newJ2k/issues/kt-1048.kt | 2 +- nj2k/testData/newJ2k/issues/kt-19327.kt | 9 +- nj2k/testData/newJ2k/issues/kt-19336.kt | 2 +- nj2k/testData/newJ2k/issues/kt-19346.kt | 2 +- nj2k/testData/newJ2k/issues/kt-19348.kt | 2 +- nj2k/testData/newJ2k/issues/kt-19382.kt | 2 +- nj2k/testData/newJ2k/issues/kt-19383.kt | 2 +- nj2k/testData/newJ2k/issues/kt-19396.kt | 2 +- nj2k/testData/newJ2k/issues/kt-19550.kt | 6 +- nj2k/testData/newJ2k/issues/kt-19639.kt | 10 +- nj2k/testData/newJ2k/issues/kt-24677.java | 16 + nj2k/testData/newJ2k/issues/kt-24677.kt | 13 + nj2k/testData/newJ2k/issues/kt-32572.java | 7 + nj2k/testData/newJ2k/issues/kt-32572.kt | 5 + nj2k/testData/newJ2k/issues/kt-32609.java | 8 + nj2k/testData/newJ2k/issues/kt-32609.kt | 5 + nj2k/testData/newJ2k/issues/kt-638.kt | 7 +- nj2k/testData/newJ2k/issues/kt-792-mixed.kt | 3 +- nj2k/testData/newJ2k/issues/kt-807.kt | 2 +- nj2k/testData/newJ2k/issues/kt-809-string.kt | 3 +- nj2k/testData/newJ2k/issues/kt-8170.kt | 4 +- .../newJ2k/javaStreamsApi/collectStream.java | 17 + .../newJ2k/javaStreamsApi/collectStream.kt | 13 + .../newJ2k/javaStreamsApi/createStream.java | 36 ++ .../newJ2k/javaStreamsApi/createStream.kt | 27 ++ .../dontCollectOnExistingStreams.java | 13 + .../dontCollectOnExistingStreams.kt | 9 + .../newJ2k/javaStreamsApi/formatting.java | 17 + .../newJ2k/javaStreamsApi/formatting.kt | 14 + .../newJ2k/javaStreamsApi/kt-21467.java | 23 ++ .../newJ2k/javaStreamsApi/kt-21467.kt | 21 ++ .../javaStreamsApi/streamOperations.java | 21 ++ .../newJ2k/javaStreamsApi/streamOperations.kt | 17 + nj2k/testData/newJ2k/list/ForEach.kt | 2 +- nj2k/testData/newJ2k/list/Lists.kt | 2 +- .../methodCallExpression/genericMethod.kt | 4 +- .../specialBuiltinMembers.kt | 6 +- .../methodCallExpression/stringMethods.kt | 6 +- .../newJ2k/methodCallExpression/vararg1.kt | 2 +- .../mutableCollections/FunctionParameters.kt | 6 +- .../MethodResultInitializesNullableField.kt | 5 +- nj2k/testData/newJ2k/nullability/kt-12050.kt | 2 +- nj2k/testData/newJ2k/objectLiteral/MyFrame.kt | 23 +- nj2k/testData/newJ2k/overloads/Override.kt | 2 - .../newJ2k/postProcessing/GetOperator.kt | 4 +- .../newJ2k/postProcessing/IfToElvis.kt | 4 +- .../postProcessing/RedundantTypeCast.kt | 2 +- .../RedunduntTypeCastAndProhibitedInline.kt | 10 +- .../rawGenerics/kt-540-rawGenericClass.kt | 6 +- .../newJ2k/rawGenerics/rawGenericMethod.kt | 6 +- nj2k/testData/newJ2k/toArray/toArray.kt | 2 +- .../toKotlinClasses/LibraryFunctions.kt | 2 +- .../typeCastExpression/extendsWildcardCast.kt | 2 +- .../newJ2k/typeCastExpression/fooCast.kt | 2 +- .../typeCastExpression/simpleGenericCast.kt | 2 +- .../newJ2k/typeCastExpression/stringCast.kt | 2 +- .../typeCastExpression/superWildcardCast.kt | 2 +- .../newJ2k/typeCastExpression/wildcardCast.kt | 2 +- ...rametrizationWithTwoBoundsWithExtending.kt | 2 +- .../classParametrizationWithTwoBounds.kt | 2 +- ...rametrizationWithTwoBoundsWithExtending.kt | 3 +- ...ethodDoubleParametrizationWithTwoBounds.kt | 2 +- ...rametrizationWithTwoBoundsWithExtending.kt | 3 +- nj2k/testData/newJ2k/typeParameters/where.kt | 2 +- .../nullabilityAnalysis/compareWithNull.kt | 13 - .../compareWithNull.kt.after | 13 - .../nullabilityAnalysis/forcedNullability.kt | 11 - .../forcedNullability.kt.after | 11 - .../functionTypeParameterNullability.kt | 6 - .../functionTypeParameterNullability.kt.after | 6 - .../testData/nullabilityAnalysis/functions.kt | 19 -- .../nullabilityAnalysis/functions.kt.after | 19 -- nj2k/testData/nullabilityAnalysis/loops.kt | 16 - .../nullabilityAnalysis/loops.kt.after | 16 - .../nullabilityAnalysis/nullAsAssignment.kt | 11 - .../nullAsAssignment.kt.after | 11 - .../nullabilityAnalysis/nullAsInitializer.kt | 2 - .../nullAsInitializer.kt.after | 2 - .../testData/nullabilityAnalysis/smartCast.kt | 4 - .../nullabilityAnalysis/smartCast.kt.after | 4 - .../nullabilityAnalysis/spreadExpression.kt | 5 - .../spreadExpression.kt.after | 5 - .../nullabilityAnalysis/superMethod.kt | 12 - .../nullabilityAnalysis/superMethod.kt.after | 12 - nj2k/testData/nullabilityAnalysis/typeCast.kt | 7 - .../nullabilityAnalysis/typeCast.kt.after | 7 - .../nullabilityAnalysis/typeParameters.kt | 13 - .../typeParameters.kt.after | 13 - ...tNewJavaToKotlinConverterSingleFileTest.kt | 45 +-- .../nj2k/AbstractNullabilityAnalysisTest.kt | 38 --- ...otlinConverterSingleFileTestGenerated.java | 58 ++++ .../NullabilityAnalysisTestGenerated.java | 91 ----- .../AbstractConstraintCollectorTest.kt | 51 +++ .../AbstractCommonConstraintCollectorTest.kt | 36 ++ ...ommonConstraintCollectorTestGenerated.java | 191 +++++++++++ .../AbstractNullabilityInferenceTest.kt | 72 ++++ .../NullabilityInferenceTestGenerated.java | 181 ++++++++++ .../org/jetbrains/kotlin/nj2k/testUtils.kt | 47 +++ 234 files changed, 3940 insertions(+), 1983 deletions(-) create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/BoundTypeCalculator.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/BoundTypeEnhancer.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ClassSubstitutor.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Constraint.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintBuilder.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintsCollectorAggregator.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ContextCollector.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/DebugPrinter.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/InferenceContext.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/InferenceFacade.kt rename nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/{nullabilityAnalysis/solver.kt => inference/common/Solver.kt} (63%) create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/State.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/StateUpdater.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/SuperFunctionsProvider.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/boundTypes.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/CallExpressionConstraintCollector.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/CommonConstraintsCollector.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/ConstraintsCollector.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/FunctionConstraintsCollector.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/typeVariables.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/utils.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityBoundTypeEnhancer.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityConstraintsCollector.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityContextCollector.kt create mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityStateUpdater.kt delete mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/BoundTypeStorage.kt delete mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/ConstraintBuilder.kt delete mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/constraints.kt delete mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/constraintsCollector.kt delete mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/context.kt delete mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/nullabilityAnalysis.kt delete mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/printing.kt delete mode 100644 nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/utils.kt create mode 100644 nj2k/testData/inference/common/arrayAssignment.kt create mode 100644 nj2k/testData/inference/common/arrayOfArrays.kt create mode 100644 nj2k/testData/inference/common/callFunctionWithTypeParamFromOuterScope.kt create mode 100644 nj2k/testData/inference/common/callWithTypeParams.kt create mode 100644 nj2k/testData/inference/common/constructorCall.kt create mode 100644 nj2k/testData/inference/common/delegationConstructorCall.kt create mode 100644 nj2k/testData/inference/common/elementOfArrayAssignment.kt create mode 100644 nj2k/testData/inference/common/elementOfListAssignment.kt create mode 100644 nj2k/testData/inference/common/forLoop.kt create mode 100644 nj2k/testData/inference/common/functionCall.kt create mode 100644 nj2k/testData/inference/common/functionReturn.kt create mode 100644 nj2k/testData/inference/common/functionWithTypeParamCall.kt create mode 100644 nj2k/testData/inference/common/lambdaAsParameter.kt create mode 100644 nj2k/testData/inference/common/lambdaAssign.kt create mode 100644 nj2k/testData/inference/common/lambdaImplicitReturn.kt create mode 100644 nj2k/testData/inference/common/lambdaReturn.kt create mode 100644 nj2k/testData/inference/common/listAssignment.kt create mode 100644 nj2k/testData/inference/common/listGenerator.kt create mode 100644 nj2k/testData/inference/common/listOfLists.kt create mode 100644 nj2k/testData/inference/common/listOfListsGenerator.kt create mode 100644 nj2k/testData/inference/common/memberCall.kt create mode 100644 nj2k/testData/inference/common/returnFromLambda.kt create mode 100644 nj2k/testData/inference/common/sequenceOfCalls.kt create mode 100644 nj2k/testData/inference/common/sequenceOfCallsWIthLambda.kt create mode 100644 nj2k/testData/inference/common/simpleAssignment.kt create mode 100644 nj2k/testData/inference/common/superCall.kt create mode 100644 nj2k/testData/inference/common/superConstuctorCall.kt create mode 100644 nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParameters.kt create mode 100644 nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParametersSubstitution.kt create mode 100644 nj2k/testData/inference/common/superFunctionType.kt create mode 100644 nj2k/testData/inference/common/typeParamsBounds.kt create mode 100644 nj2k/testData/inference/common/varargsInCall.kt create mode 100644 nj2k/testData/inference/nullability/arrayOfArraysOfNull.kt create mode 100644 nj2k/testData/inference/nullability/arrayOfNulls.kt create mode 100644 nj2k/testData/inference/nullability/binaryExpressionOperand.kt create mode 100644 nj2k/testData/inference/nullability/callExternallyAnnotatedJavaFunction.kt create mode 100644 nj2k/testData/inference/nullability/classTypeParameters.kt create mode 100644 nj2k/testData/inference/nullability/compareWithNull.kt create mode 100644 nj2k/testData/inference/nullability/forcedNullability.kt create mode 100644 nj2k/testData/inference/nullability/functionTypeParameterNullability.kt create mode 100644 nj2k/testData/inference/nullability/functions.kt create mode 100644 nj2k/testData/inference/nullability/ifCondition.kt create mode 100644 nj2k/testData/inference/nullability/javaStream.kt create mode 100644 nj2k/testData/inference/nullability/lambdaReturnNull.kt create mode 100644 nj2k/testData/inference/nullability/listOfWithNullLiteral.kt create mode 100644 nj2k/testData/inference/nullability/loopIterator.kt create mode 100644 nj2k/testData/inference/nullability/loops.kt create mode 100644 nj2k/testData/inference/nullability/notNullCallSequence.kt create mode 100644 nj2k/testData/inference/nullability/nullAsAssignment.kt create mode 100644 nj2k/testData/inference/nullability/nullAsInitializer.kt create mode 100644 nj2k/testData/inference/nullability/nullLiteral.kt create mode 100644 nj2k/testData/inference/nullability/returnNull.kt create mode 100644 nj2k/testData/inference/nullability/sequenceOfCallsWIthLambda.kt create mode 100644 nj2k/testData/inference/nullability/smartCast.kt create mode 100644 nj2k/testData/inference/nullability/spreadExpression.kt create mode 100644 nj2k/testData/inference/nullability/superMethod.kt create mode 100644 nj2k/testData/inference/nullability/typeCast.kt create mode 100644 nj2k/testData/inference/nullability/typeParameters.kt create mode 100644 nj2k/testData/inference/nullability/typeParametersReturnType.kt create mode 100644 nj2k/testData/inference/nullability/typeParametersValueParams.kt create mode 100644 nj2k/testData/inference/nullability/useAsReceiver.kt create mode 100644 nj2k/testData/inference/nullability/whileCondition.kt create mode 100644 nj2k/testData/newJ2k/issues/kt-24677.java create mode 100644 nj2k/testData/newJ2k/issues/kt-24677.kt create mode 100644 nj2k/testData/newJ2k/issues/kt-32572.java create mode 100644 nj2k/testData/newJ2k/issues/kt-32572.kt create mode 100644 nj2k/testData/newJ2k/issues/kt-32609.java create mode 100644 nj2k/testData/newJ2k/issues/kt-32609.kt create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/collectStream.java create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/collectStream.kt create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/createStream.java create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/createStream.kt create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/dontCollectOnExistingStreams.java create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/dontCollectOnExistingStreams.kt create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/formatting.java create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/formatting.kt create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/kt-21467.java create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/kt-21467.kt create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/streamOperations.java create mode 100644 nj2k/testData/newJ2k/javaStreamsApi/streamOperations.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/compareWithNull.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/compareWithNull.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/forcedNullability.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/forcedNullability.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/functionTypeParameterNullability.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/functionTypeParameterNullability.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/functions.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/functions.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/loops.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/loops.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/nullAsAssignment.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/nullAsAssignment.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/nullAsInitializer.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/nullAsInitializer.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/smartCast.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/smartCast.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/spreadExpression.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/spreadExpression.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/superMethod.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/superMethod.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/typeCast.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/typeCast.kt.after delete mode 100644 nj2k/testData/nullabilityAnalysis/typeParameters.kt delete mode 100644 nj2k/testData/nullabilityAnalysis/typeParameters.kt.after delete mode 100644 nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNullabilityAnalysisTest.kt delete mode 100644 nj2k/tests/org/jetbrains/kotlin/nj2k/NullabilityAnalysisTestGenerated.java create mode 100644 nj2k/tests/org/jetbrains/kotlin/nj2k/inference/AbstractConstraintCollectorTest.kt create mode 100644 nj2k/tests/org/jetbrains/kotlin/nj2k/inference/common/AbstractCommonConstraintCollectorTest.kt create mode 100644 nj2k/tests/org/jetbrains/kotlin/nj2k/inference/common/CommonConstraintCollectorTestGenerated.java create mode 100644 nj2k/tests/org/jetbrains/kotlin/nj2k/inference/nullability/AbstractNullabilityInferenceTest.kt create mode 100644 nj2k/tests/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityInferenceTestGenerated.java create mode 100644 nj2k/tests/org/jetbrains/kotlin/nj2k/testUtils.kt diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 17e700ad65e..62e12184916 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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.generators.tests @@ -154,8 +143,9 @@ import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTes import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinConverterSingleFileTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinCopyPasteConversionTest -import org.jetbrains.kotlin.nj2k.AbstractNullabilityAnalysisTest import org.jetbrains.kotlin.nj2k.AbstractTextNewJavaToKotlinCopyPasteConversionTest +import org.jetbrains.kotlin.nj2k.inference.common.AbstractCommonConstraintCollectorTest +import org.jetbrains.kotlin.nj2k.inference.nullability.AbstractNullabilityInferenceTest import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg import org.jetbrains.kotlin.noarg.AbstractBytecodeListingTestForNoArg import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest @@ -987,15 +977,18 @@ fun main(args: Array) { testClass { model("newJ2k", pattern = """^([^\.]+)\.java$""") } + testClass { + model("inference/common") + } + testClass { + model("inference/nullability") + } testClass { model("copyPaste", pattern = """^([^\.]+)\.java$""") } testClass { model("copyPastePlainText", pattern = """^([^\.]+)\.txt$""") } - testClass { - model("nullabilityAnalysis") - } } testGroup("jps-plugin/jps-tests/test", "jps-plugin/testData") { diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.183 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.183 index e152441438c..23f2650fe5a 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.183 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.183 @@ -159,8 +159,9 @@ import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTes import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinConverterSingleFileTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinCopyPasteConversionTest -import org.jetbrains.kotlin.nj2k.AbstractNullabilityAnalysisTest import org.jetbrains.kotlin.nj2k.AbstractTextNewJavaToKotlinCopyPasteConversionTest +import org.jetbrains.kotlin.nj2k.inference.common.AbstractCommonConstraintCollectorTest +import org.jetbrains.kotlin.nj2k.inference.nullability.AbstractNullabilityInferenceTest import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg import org.jetbrains.kotlin.noarg.AbstractBytecodeListingTestForNoArg import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest @@ -992,15 +993,18 @@ fun main(args: Array) { testClass { model("newJ2k", pattern = """^([^\.]+)\.java$""") } + testClass { + model("inference/common") + } + testClass { + model("inference/nullability") + } testClass { model("copyPaste", pattern = """^([^\.]+)\.java$""") } testClass { model("copyPastePlainText", pattern = """^([^\.]+)\.txt$""") } - testClass { - model("nullabilityAnalysis") - } } testGroup("jps-plugin/jps-tests/test", "jps-plugin/testData") { diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as33 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as33 index 0acc4874c07..ff5b65cb0b8 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as33 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as33 @@ -143,8 +143,9 @@ import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTes import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinConverterSingleFileTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinCopyPasteConversionTest -import org.jetbrains.kotlin.nj2k.AbstractNullabilityAnalysisTest import org.jetbrains.kotlin.nj2k.AbstractTextNewJavaToKotlinCopyPasteConversionTest +import org.jetbrains.kotlin.nj2k.inference.common.AbstractCommonConstraintCollectorTest +import org.jetbrains.kotlin.nj2k.inference.nullability.AbstractNullabilityInferenceTest import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg import org.jetbrains.kotlin.noarg.AbstractBytecodeListingTestForNoArg import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest @@ -952,15 +953,18 @@ fun main(args: Array) { testClass { model("newJ2k", pattern = """^([^\.]+)\.java$""") } + testClass { + model("inference/common") + } + testClass { + model("inference/nullability") + } testClass { model("copyPaste", pattern = """^([^\.]+)\.java$""") } testClass { model("copyPastePlainText", pattern = """^([^\.]+)\.txt$""") } - testClass { - model("nullabilityAnalysis") - } } /* There is no jps in AS diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as34 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as34 index 239d62cdfd6..e4f1b74a49e 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as34 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as34 @@ -143,8 +143,9 @@ import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTes import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinConverterSingleFileTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinCopyPasteConversionTest -import org.jetbrains.kotlin.nj2k.AbstractNullabilityAnalysisTest import org.jetbrains.kotlin.nj2k.AbstractTextNewJavaToKotlinCopyPasteConversionTest +import org.jetbrains.kotlin.nj2k.inference.common.AbstractCommonConstraintCollectorTest +import org.jetbrains.kotlin.nj2k.inference.nullability.AbstractNullabilityInferenceTest import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg import org.jetbrains.kotlin.noarg.AbstractBytecodeListingTestForNoArg import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest @@ -956,15 +957,18 @@ fun main(args: Array) { testClass { model("newJ2k", pattern = """^([^\.]+)\.java$""") } + testClass { + model("inference/common") + } + testClass { + model("inference/nullability") + } testClass { model("copyPaste", pattern = """^([^\.]+)\.java$""") } testClass { model("copyPastePlainText", pattern = """^([^\.]+)\.txt$""") } - testClass { - model("nullabilityAnalysis") - } } /* There is no jps in AS diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as35 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as35 index 0acc4874c07..ff5b65cb0b8 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as35 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as35 @@ -143,8 +143,9 @@ import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTes import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinConverterSingleFileTest import org.jetbrains.kotlin.nj2k.AbstractNewJavaToKotlinCopyPasteConversionTest -import org.jetbrains.kotlin.nj2k.AbstractNullabilityAnalysisTest import org.jetbrains.kotlin.nj2k.AbstractTextNewJavaToKotlinCopyPasteConversionTest +import org.jetbrains.kotlin.nj2k.inference.common.AbstractCommonConstraintCollectorTest +import org.jetbrains.kotlin.nj2k.inference.nullability.AbstractNullabilityInferenceTest import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg import org.jetbrains.kotlin.noarg.AbstractBytecodeListingTestForNoArg import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest @@ -952,15 +953,18 @@ fun main(args: Array) { testClass { model("newJ2k", pattern = """^([^\.]+)\.java$""") } + testClass { + model("inference/common") + } + testClass { + model("inference/nullability") + } testClass { model("copyPaste", pattern = """^([^\.]+)\.java$""") } testClass { model("copyPastePlainText", pattern = """^([^\.]+)\.txt$""") } - testClass { - model("nullabilityAnalysis") - } } /* There is no jps in AS diff --git a/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/testUtils.kt b/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/testUtils.kt index 6b81ac8e219..1d302defc54 100644 --- a/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/testUtils.kt +++ b/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/testUtils.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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.idea.test @@ -20,6 +9,7 @@ import com.intellij.openapi.editor.Document import com.intellij.openapi.project.Project import com.intellij.psi.PsiDocumentManager import com.intellij.testFramework.LightPlatformTestCase +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.idea.caches.project.LibraryModificationTracker @@ -29,11 +19,13 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.InTextDirectivesUtils import java.util.* -fun KtFile.dumpTextWithErrors(): String { +fun KtFile.dumpTextWithErrors(ignoreErrors: Set> = emptySet()): String { val text = text if (InTextDirectivesUtils.isDirectiveDefined(text, "// DISABLE-ERRORS")) return text val diagnostics = analyzeWithContent().diagnostics - val errors = diagnostics.filter { it.severity == Severity.ERROR } + val errors = diagnostics.filter { diagnostic -> + diagnostic.severity == Severity.ERROR && diagnostic.factory !in ignoreErrors + } if (errors.isEmpty()) return text val header = errors.joinToString("\n", postfix = "\n") { "// ERROR: " + DefaultErrorMessages.render(it).replace('\n', ' ') } return header + text diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt index 74d87be6922..8945d840e11 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt +++ b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterSingleFileTest.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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.j2k @@ -27,6 +16,7 @@ import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.test.dumpTextWithErrors import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.test.KotlinTestUtils import java.io.File import java.util.regex.Pattern @@ -73,7 +63,8 @@ abstract class AbstractJavaToKotlinConverterSingleFileTest : AbstractJavaToKotli var actual = reformat(rawConverted, project, reformatInFun) if (prefix == "file") { - actual = createKotlinFile(actual).dumpTextWithErrors() + actual = createKotlinFile(actual) + .dumpTextWithErrors(setOf(element = ErrorsJvm.INTERFACE_STATIC_METHOD_CALL_FROM_JAVA6_TARGET_ERROR)) } diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/BoundTypeCalculator.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/BoundTypeCalculator.kt new file mode 100644 index 00000000000..45bb13fb1bb --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/BoundTypeCalculator.kt @@ -0,0 +1,259 @@ +/* + * 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 + +import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny +import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.callUtil.getType +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.typeUtil.builtIns +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +interface BoundTypeCalculator { + fun expressionsWithBoundType(): List> + + fun KtExpression.boundType(inferenceContext: InferenceContext): BoundType + + fun KotlinType.boundType( + typeVariable: TypeVariable? = null, + contextBoundType: BoundType? = null, + call: ResolvedCall<*>? = null, + isImplicitReceiver: Boolean = false, + forceEnhance: Boolean = false, + inferenceContext: InferenceContext + ): BoundType +} + +class BoundTypeCalculatorImpl( + private val resolutionFacade: ResolutionFacade, + private val enhancer: BoundTypeEnhancer +) : BoundTypeCalculator { + private val cache = mutableMapOf() + + override fun expressionsWithBoundType() = cache.toList() + + override fun KtExpression.boundType(inferenceContext: InferenceContext): BoundType = cache.getOrPut(this) { + calculateBoundType(inferenceContext, this) + } + + private fun calculateBoundType(inferenceContext: InferenceContext, expression: KtExpression): BoundType = when { + expression.isNullExpression() -> BoundType.NULL + expression is KtParenthesizedExpression -> expression.expression?.boundType(inferenceContext) + expression is KtConstantExpression + || expression is KtStringTemplateExpression + || expression.node?.elementType == KtNodeTypes.BOOLEAN_CONSTANT + || expression is KtBinaryExpression -> + BoundType.LITERAL + expression is KtQualifiedExpression -> expression.toBoundTypeAsQualifiedExpression(inferenceContext) + expression is KtBinaryExpressionWithTypeRHS -> expression.toBoundTypeAsCastExpression(inferenceContext) + expression is KtNameReferenceExpression -> expression.toBoundTypeAsReferenceExpression(inferenceContext) + expression is KtCallExpression -> expression.toBoundTypeAsCallableExpression(null, inferenceContext) + expression is KtLambdaExpression -> expression.toBoundTypeAsLambdaExpression(inferenceContext) + expression is KtLabeledExpression -> expression.baseExpression?.boundType(inferenceContext) + expression is KtIfExpression -> expression.toBoundTypeAsIfExpression(inferenceContext) + else -> null + }?.let { boundType -> + enhancer.enhance(expression, boundType, inferenceContext) + } ?: BoundType.LITERAL + + private fun KtIfExpression.toBoundTypeAsIfExpression(inferenceContext: InferenceContext): BoundType? { + val isNullLiteralPossible = then?.isNullExpression() == true || `else`?.isNullExpression() == true + if (isNullLiteralPossible) { + return BoundType.NULL + } + return (then ?: `else`)?.boundType(inferenceContext) //TODO handle both cases separatelly + } + + private fun KtLambdaExpression.toBoundTypeAsLambdaExpression(inferenceContext: InferenceContext): BoundType? { + val descriptor = functionLiteral.resolveToDescriptorIfAny(resolutionFacade).safeAs() ?: return null + val builtIns = getType(analyze())?.builtIns ?: return null + val prototypeDescriptor = builtIns.getFunction(valueParameters.size) + val parameterBoundTypes = if (descriptor.valueParameters.size == valueParameters.size) { + valueParameters.map { parameter -> + parameter.typeReference?.typeElement?.let { typeElement -> + inferenceContext.typeElementToTypeVariable[typeElement] + }?.let { typeVariable -> + typeVariable.asBoundType() + } ?: return null + } + } else { + descriptor.valueParameters.map { parameter -> + parameter.type.boundType(inferenceContext = inferenceContext) + } + } + val returnTypeTypeVariable = inferenceContext.declarationToTypeVariable[functionLiteral] ?: return null + val returnTypeParameter = + TypeParameter( + BoundTypeImpl( + TypeVariableLabel(returnTypeTypeVariable), + returnTypeTypeVariable.typeParameters + ), + Variance.OUT_VARIANCE + ) + return BoundTypeImpl( + GenericLabel(prototypeDescriptor.classReference), + parameterBoundTypes.map { TypeParameter(it, Variance.IN_VARIANCE) } + returnTypeParameter + ) + } + + private fun KtNameReferenceExpression.toBoundTypeAsReferenceExpression(inferenceContext: InferenceContext): BoundType? = + mainReference + .resolve() + ?.safeAs() + ?.let { declaration -> + val boundType = inferenceContext.declarationToTypeVariable[declaration]?.asBoundType() + ?: return@let null + if (declaration.safeAs()?.isVarArg == true) { + val arrayClassReference = + declaration.resolveToDescriptorIfAny(resolutionFacade) + ?.safeAs() + ?.returnType + ?.constructor + ?.declarationDescriptor + ?.safeAs() + ?.classReference ?: NoClassReference + BoundTypeImpl( + GenericLabel(arrayClassReference), + listOf(TypeParameter(boundType, Variance.INVARIANT)) + ) + } else boundType + } + + + private fun KtBinaryExpressionWithTypeRHS.toBoundTypeAsCastExpression(inferenceContext: InferenceContext): BoundType? = + right?.typeElement + ?.let { inferenceContext.typeElementToTypeVariable[it]?.asBoundType() } + + + private fun KtExpression.toBoundTypeAsCallableExpression( + contextBoundType: BoundType?, + inferenceContext: InferenceContext + ): BoundType? { + val call = getResolvedCall(analyze(resolutionFacade)) ?: return null + val returnType = call.candidateDescriptor.original.returnType ?: return null + val callDescriptor = call.candidateDescriptor.original + val returnTypeVariable = inferenceContext.declarationDescriptorToTypeVariable[callDescriptor] + val withImplicitContextBoundType = contextBoundType + ?: call.dispatchReceiver + ?.type + ?.boundType(inferenceContext = inferenceContext) + + return returnType.boundType( + returnTypeVariable, + withImplicitContextBoundType, + call, + withImplicitContextBoundType != contextBoundType, + false, + inferenceContext + ) + } + + private fun KtQualifiedExpression.toBoundTypeAsQualifiedExpression(inferenceContext: InferenceContext): BoundType? { + val receiverBoundType = receiverExpression.boundType(inferenceContext) + val selectorExpression = selectorExpression ?: return null + return selectorExpression.toBoundTypeAsCallableExpression(receiverBoundType, inferenceContext) + } + + override fun KotlinType.boundType( + typeVariable: TypeVariable?, + contextBoundType: BoundType?, + call: ResolvedCall<*>?, + isImplicitReceiver: Boolean, + forceEnhance: Boolean, + inferenceContext: InferenceContext + ) = boundTypeUnenhanced( + typeVariable, + contextBoundType, + call, + isImplicitReceiver, + inferenceContext + )?.let { boundType -> + val needEnhance = run { + if (forceEnhance) return@run true + !inferenceContext.isInConversionScope( + call?.call?.calleeExpression?.mainReference?.resolve() ?: return@run false + ) + } + if (needEnhance) enhancer.enhanceKotlinType(this, boundType, forceEnhance, inferenceContext) + else boundType + } ?: BoundType.LITERAL + + private fun KotlinType.boundTypeUnenhanced( + typeVariable: TypeVariable?, + contextBoundType: BoundType?, + call: ResolvedCall<*>?, + isImplicitReceiver: Boolean, + inferenceContext: InferenceContext + ): BoundType? { + return when (val target = constructor.declarationDescriptor) { + is ClassDescriptor -> + BoundTypeImpl( + typeVariable?.let { TypeVariableLabel(it) } ?: GenericLabel(target.classReference), + arguments.mapIndexed { i, argument -> + TypeParameter( + argument.type.boundTypeUnenhanced( + typeVariable?.typeParameters?.get(i)?.boundType?.label?.safeAs()?.typeVariable, + contextBoundType, + call, + isImplicitReceiver, + inferenceContext + ) ?: return null, + constructor.parameters[i].variance + ) + } + ) + + is TypeParameterDescriptor -> { + val containingDeclaration = target.containingDeclaration + when { + containingDeclaration == call?.candidateDescriptor?.original -> { + val returnTypeVariable = inferenceContext.typeElementToTypeVariable[ + call.call.typeArguments.getOrNull(target.index)?.typeReference?.typeElement ?: return null + ] ?: return null + BoundTypeImpl( + TypeVariableLabel(returnTypeVariable), + returnTypeVariable.typeParameters + ) + } + typeVariable != null && isImplicitReceiver -> + BoundTypeImpl( + TypeVariableLabel(typeVariable), + emptyList() + ) + contextBoundType?.isReferenceToClass == true -> + contextBoundType.typeParameters.getOrNull(target.index)?.boundType + + // `this` or `super` call case + containingDeclaration == call?.candidateDescriptor.safeAs()?.constructedClass -> { + val returnTypeVariable = inferenceContext.typeElementToTypeVariable[ + call?.call?.typeArguments?.getOrNull(target.index)?.typeReference?.typeElement ?: return null + ] ?: return null + BoundTypeImpl( + TypeVariableLabel(returnTypeVariable), + returnTypeVariable.typeParameters + ) + } + else -> BoundTypeImpl( + TypeParameterLabel(target), + emptyList() + ) + } + } + else -> null + } + } +} + + diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/BoundTypeEnhancer.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/BoundTypeEnhancer.kt new file mode 100644 index 00000000000..d0e36ed940e --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/BoundTypeEnhancer.kt @@ -0,0 +1,39 @@ +/* + * 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 + +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.types.KotlinType + +abstract class BoundTypeEnhancer { + abstract fun enhance( + expression: KtExpression, + boundType: BoundType, + inferenceContext: InferenceContext + ): BoundType + + abstract fun enhanceKotlinType( + type: KotlinType, + boundType: BoundType, + allowLowerEnhancement: Boolean, + inferenceContext: InferenceContext + ): BoundType + + object ID : BoundTypeEnhancer() { + override fun enhance( + expression: KtExpression, + boundType: BoundType, + inferenceContext: InferenceContext + ): BoundType = boundType + + override fun enhanceKotlinType( + type: KotlinType, + boundType: BoundType, + allowLowerEnhancement: Boolean, + inferenceContext: InferenceContext + ): BoundType = boundType + } +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ClassSubstitutor.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ClassSubstitutor.kt new file mode 100644 index 00000000000..13083b0de25 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ClassSubstitutor.kt @@ -0,0 +1,38 @@ +/* + * 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 + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtTypeElement +import org.jetbrains.kotlin.resolve.BindingContext + +class ClassSubstitutor(private val superTypes: Map>) { + operator fun get(klass: ClassDescriptor, typeParameter: TypeParameterDescriptor): KtTypeElement? = + superTypes[klass]?.get(typeParameter) + + companion object { + fun createFromKtClass(klass: KtClassOrObject, resolutionFacade: ResolutionFacade): ClassSubstitutor? { + val superTypes = + klass.superTypeListEntries.map { superType -> + val typeReference = superType.typeReference ?: return null + val type = typeReference.analyze(resolutionFacade)[BindingContext.TYPE, typeReference] ?: return null + val declarationDescriptor = type.constructor.declarationDescriptor ?: return null + declarationDescriptor to type.constructor.parameters.zip( + typeReference.typeElement?.typeArgumentsAsTypes ?: return null + ) { parameter, argument -> + parameter to (argument.typeElement ?: return null) + }.toMap() + }.toMap() + return ClassSubstitutor(superTypes) + } + } +} + diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Constraint.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Constraint.kt new file mode 100644 index 00000000000..a553087fc9c --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Constraint.kt @@ -0,0 +1,81 @@ +/* + * 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 + +enum class ConstraintPriority { + /* order of entries here used when solving system of constraints */ + SUPER_DECLARATION, + INITIALIZER, + RETURN, + ASSIGNMENT, + PARAMETER, + RECEIVER_PARAMETER, + COMPARE_WITH_NULL, + USE_AS_RECEIVER, +} + +sealed class Constraint { + abstract val priority: ConstraintPriority +} + +class SubtypeConstraint( + var subtype: ConstraintBound, + var supertype: ConstraintBound, + override val priority: ConstraintPriority +) : Constraint() { + operator fun component1() = subtype + operator fun component2() = supertype +} + +class EqualsConstraint( + var left: ConstraintBound, + var right: ConstraintBound, + override val priority: ConstraintPriority +) : Constraint() { + operator fun component1() = left + operator fun component2() = right +} + +fun Constraint.copy() = when (this) { + is SubtypeConstraint -> SubtypeConstraint(subtype, supertype, priority) + is EqualsConstraint -> EqualsConstraint(left, right, priority) +} + +sealed class ConstraintBound +class TypeVariableBound(val typeVariable: TypeVariable) : ConstraintBound() +class LiteralBound private constructor(val state: State) : ConstraintBound() { + companion object { + val UPPER = LiteralBound(State.UPPER) + val LOWER = LiteralBound(State.LOWER) + val UNKNOWN = LiteralBound(State.UNKNOWN) + } +} + +val TypeVariable.constraintBound: TypeVariableBound + get() = TypeVariableBound(this) + +val State.constraintBound: LiteralBound + 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 + } \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintBuilder.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintBuilder.kt new file mode 100644 index 00000000000..ba16ae896be --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintBuilder.kt @@ -0,0 +1,136 @@ +/* + * 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 + +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtTypeElement +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +@Suppress("unused") +class ConstraintBuilder( + private val inferenceContext: InferenceContext, + private val boundTypeCalculator: BoundTypeCalculator +) : BoundTypeCalculator by boundTypeCalculator { + private val constraints = mutableListOf() + + fun TypeVariable.isSubtypeOf(supertype: BoundType, priority: ConstraintPriority) { + asBoundType().isSubtypeOf(supertype, priority) + } + + fun TypeVariable.isSubtypeOf(supertype: TypeVariable, priority: ConstraintPriority) { + asBoundType().isSubtypeOf(supertype.asBoundType(), priority) + } + + fun KtExpression.isSubtypeOf(supertype: KtExpression, priority: ConstraintPriority) { + boundType().isSubtypeOf(supertype.boundType(), priority) + } + + fun KtExpression.isSubtypeOf(supertype: TypeVariable, priority: ConstraintPriority) { + boundType().isSubtypeOf(supertype.asBoundType(), priority) + } + + fun KtExpression.isSubtypeOf(supertype: BoundType, priority: ConstraintPriority) { + boundType().isSubtypeOf(supertype, priority) + } + + fun KtExpression.isTheSameTypeAs(other: State, priority: ConstraintPriority) { + boundType().label.safeAs()?.typeVariable?.let { typeVariable -> + constraints += EqualsConstraint(typeVariable.constraintBound, other.constraintBound, priority) + } + } + + fun TypeVariable.isTheSameTypeAs(other: BoundType, priority: ConstraintPriority) { + asBoundType().isTheSameTypeAs(other, priority) + } + + fun TypeVariable.isTheSameTypeAs( + other: TypeVariable, + priority: ConstraintPriority, + ignoreTypeVariables: Set = emptySet() + ) { + asBoundType().isTheSameTypeAs(other.asBoundType(), priority, ignoreTypeVariables) + } + + fun KtTypeElement.isTheSameTypeAs( + other: KtTypeElement, + priority: ConstraintPriority, + ignoreTypeVariables: Set = emptySet() + ) { + inferenceContext.typeElementToTypeVariable[this] + ?.asBoundType() + ?.isTheSameTypeAs( + inferenceContext.typeElementToTypeVariable[other]?.asBoundType() ?: return, + priority, + ignoreTypeVariables + ) + } + + fun TypeVariable.isTheSameTypeAs( + other: KtTypeElement, + priority: ConstraintPriority, + ignoreTypeVariables: Set = emptySet() + ) { + asBoundType().isTheSameTypeAs( + inferenceContext.typeElementToTypeVariable[other]?.asBoundType() ?: return, + priority, + ignoreTypeVariables + ) + } + + fun BoundType.isTheSameTypeAs( + other: KtTypeElement, + priority: ConstraintPriority, + ignoreTypeVariables: Set = emptySet() + ) { + isTheSameTypeAs( + inferenceContext.typeElementToTypeVariable[other]?.asBoundType() ?: return, + priority, + ignoreTypeVariables + ) + } + + fun BoundType.isTheSameTypeAs( + other: BoundType, + priority: ConstraintPriority, + ignoreTypeVariables: Set = emptySet() + ) { + (typeParameters zip other.typeParameters).forEach { (left, right) -> + left.boundType.isTheSameTypeAs(right.boundType, priority, ignoreTypeVariables) + } + + if (typeVariable !in ignoreTypeVariables && other.typeVariable !in ignoreTypeVariables) { + constraints += EqualsConstraint( + constraintBound ?: return, + other.constraintBound ?: return, + priority + ) + } + } + + fun BoundType.isSubtypeOf(supertype: BoundType, priority: ConstraintPriority) { + (typeParameters zip supertype.typeParameters).forEach { (left, right) -> + when (left.variance) { + Variance.OUT_VARIANCE -> left.boundType.isSubtypeOf(right.boundType, priority) + Variance.IN_VARIANCE -> right.boundType.isSubtypeOf(left.boundType, priority) + Variance.INVARIANT -> right.boundType.isTheSameTypeAs(left.boundType, priority) + } + } + + constraints += SubtypeConstraint( + constraintBound ?: return, + supertype.constraintBound ?: return, + priority + ) + } + + fun KtExpression.boundType() = with(boundTypeCalculator) { + this@boundType.boundType(inferenceContext) + } + + val collectedConstraints: List + get() = constraints +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintsCollectorAggregator.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintsCollectorAggregator.kt new file mode 100644 index 00000000000..98009dab033 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ConstraintsCollectorAggregator.kt @@ -0,0 +1,42 @@ +/* + * 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 + +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.nj2k.inference.common.collectors.ConstraintsCollector +import org.jetbrains.kotlin.nj2k.parentOfType +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtImportDirective +import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType + +class ConstraintsCollectorAggregator( + private val resolutionFacade: ResolutionFacade, + private val collectors: List +) { + fun collectConstraints( + boundTypeCalculator: BoundTypeCalculator, + inferenceContext: InferenceContext, + elements: List + ): List { + val constraintsBuilder = ConstraintBuilder(inferenceContext, boundTypeCalculator) + for (element in elements) { + element.forEachDescendantOfType { innerElement -> + if (innerElement.parentOfType() != null) return@forEachDescendantOfType + for (collector in collectors) { + with(collector) { + constraintsBuilder.collectConstraints( + innerElement, + boundTypeCalculator, + inferenceContext, + resolutionFacade + ) + } + } + } + } + return constraintsBuilder.collectedConstraints + } +} diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ContextCollector.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ContextCollector.kt new file mode 100644 index 00000000000..13117b8fbe8 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/ContextCollector.kt @@ -0,0 +1,196 @@ +/* + * 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 + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callUtil.getType +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.typeUtil.isUnit +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +abstract class ContextCollector(private val resolutionFacade: ResolutionFacade) { + private fun KotlinType.classReference(): ClassReference? = + when (val descriptor = constructor.declarationDescriptor) { + is ClassDescriptor -> descriptor.classReference + is TypeParameterDescriptor -> TypeParameterReference(descriptor) + else -> null + } + + private fun KtTypeReference.classReference(): ClassReference? = + analyze()[BindingContext.TYPE, this]?.classReference() + + private fun KtTypeElement.toData(): TypeElementData { + val typeReference = parent as? KtTypeReference ?: return TypeElementDataImpl(this) + val typeParameterDescriptor = analyze(resolutionFacade)[BindingContext.TYPE, typeReference] + ?.constructor + ?.declarationDescriptor + ?.safeAs() ?: return TypeElementDataImpl(this) + return TypeParameterElementData(this, typeParameterDescriptor) + } + + fun collectTypeVariables(elements: List): InferenceContext { + val declarationToTypeVariable = mutableMapOf() + val typeElementToTypeVariable = mutableMapOf() + val typeBasedTypeVariables = mutableListOf() + + fun KtTypeReference.toBoundType(defaultState: State? = null): BoundType? { + val typeElement = typeElement ?: return null + val classReference = classReference() ?: NoClassReference + + val state = when { + classReference.descriptor?.defaultType?.isUnit() == true -> State.LOWER + defaultState != null -> defaultState + else -> classReference.getState(typeElement) + } + val typeArguments = + if (classReference is DescriptorClassReference) { + typeElement.typeArgumentsAsTypes.zip( + classReference.descriptor.declaredTypeParameters + ) { typeArgument, typeParameter -> + TypeParameter( + if (typeArgument == null) { + BoundTypeImpl(StarProjectionLabel, emptyList()) + } else typeArgument.toBoundType() ?: BoundType.STAR_PROJECTION, + typeParameter.variance + ) + } + } else emptyList() + + return if (state == null) { + BoundTypeImpl( + GenericLabel(classReference), + typeArguments + ) + } else { + val typeVariable = TypeElementBasedTypeVariable( + classReference, + typeArguments, + typeElement.toData(), + state + ) + typeElementToTypeVariable[typeElement] = typeVariable + typeVariable.asBoundType() + } + } + + fun KotlinType.toBoundType(): BoundType? { + val classReference = classReference() ?: NoClassReference + val state = classReference.getState(typeElement = null) + + val typeArguments = + if (classReference is DescriptorClassReference) { + arguments.zip(classReference.descriptor.declaredTypeParameters) { typeArgument, typeParameter -> + TypeParameter( + typeArgument.type.toBoundType() ?: BoundType.STAR_PROJECTION, + typeParameter.variance + ) + } + } else emptyList() + + return if (state == null) { + BoundTypeImpl( + GenericLabel(classReference), + typeArguments + ) + } else { + val typeVariable = TypeBasedTypeVariable( + classReference, + typeArguments, + this, + state + ) + typeBasedTypeVariables += typeVariable + typeVariable.asBoundType() + } + } + + val substitutors = mutableMapOf() + + for (element in elements) { + element.forEachDescendantOfType { expression -> + if (expression is KtCallableDeclaration + && (expression is KtParameter + || expression is KtProperty + || expression is KtNamedFunction) + ) run { + val typeReference = expression.typeReference ?: return@run + val typeVariable = typeReference.toBoundType()?.typeVariable ?: return@run + declarationToTypeVariable[expression] = typeVariable + } + + if (expression is KtTypeParameterListOwner) { + for (typeParameter in expression.typeParameters) { + typeParameter.extendsBound?.toBoundType(defaultState = State.UPPER) + } + for (constraint in expression.typeConstraints) { + constraint.boundTypeReference?.toBoundType(defaultState = State.UPPER) + } + } + + when (expression) { + is KtClass -> { + for (entry in expression.superTypeListEntries) { + for (argument in entry.typeReference?.typeElement?.typeArgumentsAsTypes ?: continue) { + argument.toBoundType() + } + } + val descriptor = + expression.resolveToDescriptorIfAny(resolutionFacade) ?: return@forEachDescendantOfType + substitutors[descriptor] = + ClassSubstitutor.createFromKtClass(expression, resolutionFacade) ?: return@forEachDescendantOfType + for (typeParameter in expression.typeParameters) { + val typeVariable = typeParameter.resolveToDescriptorIfAny(resolutionFacade) + ?.safeAs() + ?.defaultType + ?.toBoundType() + ?.typeVariable + ?: continue + declarationToTypeVariable[typeParameter] = typeVariable + } + } + is KtCallExpression -> + for (typeArgument in expression.typeArguments) { + typeArgument.typeReference?.toBoundType() + } + is KtLambdaExpression -> { + val context = expression.analyze(resolutionFacade) + val returnType = expression.getType(context)?.arguments?.lastOrNull()?.type ?: return@forEachDescendantOfType + val typeVariable = returnType.toBoundType()?.typeVariable ?: return@forEachDescendantOfType + declarationToTypeVariable[expression.functionLiteral] = typeVariable + } + is KtBinaryExpressionWithTypeRHS -> { + val typeReference = expression.right ?: return@forEachDescendantOfType + val typeElement = typeReference.typeElement ?: return@forEachDescendantOfType + val typeVariable = typeReference.toBoundType()?.typeVariable ?: return@forEachDescendantOfType + typeElementToTypeVariable[typeElement] = typeVariable + } + } + } + } + + val typeVariables = + (typeElementToTypeVariable.values + declarationToTypeVariable.values + typeBasedTypeVariables).distinct() + return InferenceContext( + elements, + typeVariables, + typeElementToTypeVariable, + declarationToTypeVariable, + declarationToTypeVariable.mapNotNull { (key, value) -> + key.resolveToDescriptorIfAny(resolutionFacade)?.let { it to value } + }.toMap(), + substitutors + ) + } + + abstract fun ClassReference.getState(typeElement: KtTypeElement?): State? +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/DebugPrinter.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/DebugPrinter.kt new file mode 100644 index 00000000000..156dad087e5 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/DebugPrinter.kt @@ -0,0 +1,81 @@ +/* + * 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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.KtTypeElement +import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType + +class DebugPrinter(private val inferenceContext: InferenceContext) { + private val namer = Namer(inferenceContext) + + val TypeVariable.name: String + get() = namer.name(this) + + private fun ClassReference.asString() = when (this) { + is DescriptorClassReference -> descriptor.name.toString() + is TypeParameterReference -> descriptor.name.toString() + is NoClassReference -> "NoClassRef" + } + + fun BoundTypeLabel.asString(): String = when (this) { + is TypeVariableLabel -> typeVariable.name + "@" + typeVariable.classReference.asString() + is TypeParameterLabel -> typeParameter.name.asString() + is GenericLabel -> classReference.asString() + StarProjectionLabel -> "*" + NullLiteralLabel -> "NULL" + LiteralLabel -> "LIT" + } + + fun State.asString() = when (this) { + State.LOWER -> "L" + State.UPPER -> "U" + State.UNKNOWN -> "?" + } + + fun BoundType.asString(): String = buildString { + append(label.asString()) + if (typeParameters.isNotEmpty()) { + typeParameters.joinTo(this, ", ", "<", ">") { it.boundType.asString() } + } + if (this@asString is WithForcedStateBoundType) { + append("!!") + append(forcedState.asString()) + } + } + + fun Constraint.asString() = when (this) { + is EqualsConstraint -> "${left.asString()} := ${right.asString()}" + is SubtypeConstraint -> "${subtype.asString()} <: ${supertype.asString()}" + } + " due to '$priority'" + + + private fun ConstraintBound.asString(): String = when (this) { + is LiteralBound -> state.toString() + is TypeVariableBound -> typeVariable.name + } + + fun PsiElement.addTypeVariablesNames() { + val factory = KtPsiFactory(this) + for (typeElement in collectDescendantsOfType()) { + val typeVariableName = this@DebugPrinter.inferenceContext.typeElementToTypeVariable[typeElement]?.name ?: continue + val comment = factory.createComment("/*$typeVariableName@*/") + typeElement.parent.addBefore(comment, typeElement) + } + } +} + + +private class Namer(inferenceContext: InferenceContext) { + val names = inferenceContext.typeVariables.mapIndexed { index, typeVariable -> + typeVariable to "T$index" + }.toMap() + + + fun name(typeVariable: TypeVariable): String = + names.getValue(typeVariable) +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/InferenceContext.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/InferenceContext.kt new file mode 100644 index 00000000000..a2b715a1077 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/InferenceContext.kt @@ -0,0 +1,32 @@ +/* + * 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 + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.idea.core.util.range +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtNamedDeclaration +import org.jetbrains.kotlin.psi.KtTypeElement + +data class InferenceContext( + val elements: List, + val typeVariables: List, + val typeElementToTypeVariable: Map, + val declarationToTypeVariable: Map, + val declarationDescriptorToTypeVariable: Map, + val classSubstitutions: Map + +) { + fun isInConversionScope(childCandidate: PsiElement) = when (childCandidate) { + is KtElement -> elements.any { element -> + element.containingKtFile == childCandidate.containingKtFile + && element.range.contains(childCandidate.range) + } + else -> false + } +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/InferenceFacade.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/InferenceFacade.kt new file mode 100644 index 00000000000..3379cc6e9a9 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/InferenceFacade.kt @@ -0,0 +1,52 @@ +/* + * 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 + +import org.jetbrains.kotlin.idea.util.application.runWriteAction +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtPsiFactory + +class InferenceFacade( + private val typeVariablesCollector: ContextCollector, + private val constraintsCollectorAggregator: ConstraintsCollectorAggregator, + private val boundTypeCalculator: BoundTypeCalculator, + private val stateUpdater: StateUpdater, + private val renderDebugTypes: Boolean = false, + private val printDebugConstraints: Boolean = false +) { + fun runOn(elements: List) { + val inferenceContext = typeVariablesCollector.collectTypeVariables(elements) + val constraints = constraintsCollectorAggregator.collectConstraints(boundTypeCalculator, inferenceContext, elements) + + val initialConstraints = if (renderDebugTypes) constraints.map { it.copy() } else null + Solver(inferenceContext, printDebugConstraints).solveConstraints(constraints) + + if (renderDebugTypes) { + with(DebugPrinter(inferenceContext)) { + runWriteAction { + for ((expression, boundType) in boundTypeCalculator.expressionsWithBoundType()) { + val comment = KtPsiFactory(expression.project).createComment("/*${boundType.asString()}*/") + expression.parent.addAfter(comment, expression) + } + for (element in elements) { + element.addTypeVariablesNames() + } + for (element in elements) { + val factory = KtPsiFactory(element) + element.add(factory.createNewLine(lineBreaks = 2)) + for (constraint in initialConstraints!!) { + element.add(factory.createComment("//${constraint.asString()}")) + element.add(factory.createNewLine(lineBreaks = 1)) + } + } + } + } + } + runWriteAction { + stateUpdater.updateStates(inferenceContext) + } + } +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/solver.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Solver.kt similarity index 63% rename from nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/solver.kt rename to nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Solver.kt index dc5229a3429..b9b603f4a74 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/solver.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Solver.kt @@ -3,27 +3,29 @@ * 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.nullabilityAnalysis +package org.jetbrains.kotlin.nj2k.inference.common import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal class Solver( - private val analysisContext: AnalysisContext, + private val analysisContext: InferenceContext, private val printConstraints: Boolean ) { - private val printer = Printer(analysisContext) + private val printer = DebugPrinter(analysisContext) private fun List.printDebugInfo(step: Int) = with(printer) { if (printConstraints) { println("Step $step:") - println(listConstrains()) + for (constraint in this@printDebugInfo) { + println(constraint.asString()) + } println() println("type variables:") - for (typeVariable in analysisContext.typeElementToTypeVariable.values) { - println("${typeVariable.name} := ${typeVariable.nullability}") + for (typeVariable in analysisContext.typeVariables) { + println("${typeVariable.name} := ${typeVariable.state}") } println("---------------\n") } @@ -31,7 +33,7 @@ internal class Solver( fun solveConstraints(constraints: List) { val mutableConstraints = constraints.toMutableList() - var currentStep = ConstraintCameFrom.values().first() + var currentStep = ConstraintPriority.values().first() var i = 0 do { @@ -40,22 +42,22 @@ internal class Solver( printDebugInfo(i) somethingChanged = handleConstraintsWithNullableLowerBound(currentStep) || somethingChanged somethingChanged = handleConstraintsWithNotNullUpperBound(currentStep) || somethingChanged - somethingChanged = handleEqualConstraints(currentStep) || somethingChanged + somethingChanged = handleEqualsConstraints(currentStep) || somethingChanged somethingChanged = substituteConstraints() || somethingChanged cleanConstraints() } if (!somethingChanged) { - if (currentStep.ordinal < ConstraintCameFrom.values().lastIndex) { - currentStep = ConstraintCameFrom.values()[currentStep.ordinal + 1] + if (currentStep.ordinal < ConstraintPriority.values().lastIndex) { + currentStep = ConstraintPriority.values()[currentStep.ordinal + 1] somethingChanged = true } } if (!somethingChanged) { val typeVariable = mutableConstraints.getTypeVariableAsEqualsOrUpperBound() if (typeVariable != null) { - typeVariable.setNullabilityIfNotFixed(Nullability.NOT_NULL) + typeVariable.setStateIfNotFixed(State.LOWER) somethingChanged = true } } @@ -65,21 +67,14 @@ internal class Solver( private fun MutableList.cleanConstraints() { - val newConstraints = - distinct() - .filterNot { constraint -> - constraint is SubtypeConstraint - && constraint.lowerBound is LiteralBound - && constraint.upperBound is LiteralBound - } - - if (newConstraints.size < size) { - clear() - addAll(newConstraints) + removeIf { constraint -> + constraint is SubtypeConstraint + && constraint.subtype is LiteralBound + && constraint.supertype is LiteralBound } } - private fun MutableList.handleConstraintsWithNullableLowerBound(step: ConstraintCameFrom): Boolean { + private fun MutableList.handleConstraintsWithNullableLowerBound(step: ConstraintPriority): Boolean { var somethingChanged = false val nullableConstraints = getConstraintsWithNullableLowerBound(step) if (nullableConstraints.isNotEmpty()) { @@ -87,14 +82,14 @@ internal class Solver( for ((_, upperBound) in nullableConstraints) { if (upperBound is TypeVariableBound) { somethingChanged = true - upperBound.typeVariable.setNullabilityIfNotFixed(Nullability.NULLABLE) + upperBound.typeVariable.setStateIfNotFixed(State.UPPER) } } } return somethingChanged } - private fun MutableList.handleConstraintsWithNotNullUpperBound(step: ConstraintCameFrom): Boolean { + private fun MutableList.handleConstraintsWithNotNullUpperBound(step: ConstraintPriority): Boolean { var somethingChanged = false val nullableConstraints = getConstraintsWithNotNullUpperBound(step) if (nullableConstraints.isNotEmpty()) { @@ -102,37 +97,36 @@ internal class Solver( for ((lowerBound, _) in nullableConstraints) { if (lowerBound is TypeVariableBound) { somethingChanged = true - lowerBound.typeVariable.setNullabilityIfNotFixed(Nullability.NOT_NULL) + lowerBound.typeVariable.setStateIfNotFixed(State.LOWER) } } } return somethingChanged } - private fun ConstraintBound.fixedNullability(): Nullability? = - when { - this is LiteralBound -> nullability - this is TypeVariableBound && typeVariable.isFixed -> typeVariable.nullability - else -> null - } + private fun ConstraintBound.fixedState(): State? = when { + this is LiteralBound -> state + this is TypeVariableBound && typeVariable.isFixed -> typeVariable.state + else -> null + } - private fun MutableList.handleEqualConstraints(step: ConstraintCameFrom): Boolean { + private fun MutableList.handleEqualsConstraints(step: ConstraintPriority): Boolean { var somethingChanged = false - val equalsConstraints = filterIsInstance().filter { it.cameFrom <= step } + val equalsConstraints = filterIsInstance().filter { it.priority <= step } if (equalsConstraints.isNotEmpty()) { for (constraint in equalsConstraints) { val (leftBound, rightBound) = constraint when { - leftBound is TypeVariableBound && rightBound.fixedNullability() != null -> { + leftBound is TypeVariableBound && rightBound.fixedState() != null -> { this -= constraint somethingChanged = true - leftBound.typeVariable.setNullabilityIfNotFixed(rightBound.fixedNullability()!!) + leftBound.typeVariable.setStateIfNotFixed(rightBound.fixedState()!!) } - rightBound is TypeVariableBound && leftBound.fixedNullability() != null -> { + rightBound is TypeVariableBound && leftBound.fixedState() != null -> { this -= constraint somethingChanged = true - rightBound.typeVariable.setNullabilityIfNotFixed(leftBound.fixedNullability()!!) + rightBound.typeVariable.setStateIfNotFixed(leftBound.fixedState()!!) } } } @@ -148,39 +142,38 @@ internal class Solver( val (lower, upper) = constraint if (lower is TypeVariableBound && lower.typeVariable.isFixed) { somethingChanged = true - constraint.lowerBound = LiteralBound(lower.typeVariable.nullability) + constraint.subtype = lower.typeVariable.state.constraintBound } if (upper is TypeVariableBound && upper.typeVariable.isFixed) { somethingChanged = true - constraint.upperBound = LiteralBound(upper.typeVariable.nullability) + constraint.supertype = upper.typeVariable.state.constraintBound } } } return somethingChanged } - private fun List.getConstraintsWithNullableLowerBound(cameFrom: ConstraintCameFrom) = + private fun List.getConstraintsWithNullableLowerBound(priority: ConstraintPriority) = filterIsInstance().filter { constraint -> - constraint.cameFrom <= cameFrom - && constraint.lowerBound.safeAs()?.nullability == Nullability.NULLABLE + constraint.priority <= priority + && constraint.subtype.safeAs()?.state == State.UPPER } - private fun List.getConstraintsWithNotNullUpperBound(cameFrom: ConstraintCameFrom) = + private fun List.getConstraintsWithNotNullUpperBound(priority: ConstraintPriority) = filterIsInstance().filter { constraint -> - constraint.cameFrom <= cameFrom - && constraint.upperBound.safeAs()?.nullability == Nullability.NOT_NULL + constraint.priority <= priority + && constraint.supertype.safeAs()?.state == State.LOWER } private fun List.getTypeVariableAsEqualsOrUpperBound(): TypeVariable? = asSequence().filterIsInstance() - .map { it.upperBound } + .map { it.supertype } .firstIsInstanceOrNull() ?.typeVariable - ?: asSequence().filterIsInstance() - .flatMap { sequenceOf(it.leftBound, it.rightBound) } + ?: asSequence().filterIsInstance() + .flatMap { sequenceOf(it.left, it.right) } .firstIsInstanceOrNull() ?.typeVariable - } diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/State.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/State.kt new file mode 100644 index 00000000000..c9aa2906c18 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/State.kt @@ -0,0 +1,12 @@ +/* + * 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 + +enum class State { + LOWER, + UPPER, + UNKNOWN +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/StateUpdater.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/StateUpdater.kt new file mode 100644 index 00000000000..5aa0546f742 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/StateUpdater.kt @@ -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 StateUpdater { + abstract fun updateStates(inferenceContext: InferenceContext) +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/SuperFunctionsProvider.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/SuperFunctionsProvider.kt new file mode 100644 index 00000000000..f8b72c925be --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/SuperFunctionsProvider.kt @@ -0,0 +1,58 @@ +/* + * 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 + +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.nj2k.* +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +abstract class SuperFunctionsProvider { + abstract fun provideSuperFunctionDescriptors(function: KtFunction): List? + lateinit var inferenceContext: InferenceContext +} + +class ResolveSuperFunctionsProvider(private val resolutionFacade: ResolutionFacade) : SuperFunctionsProvider() { + override fun provideSuperFunctionDescriptors(function: KtFunction): List? = + function.resolveToDescriptorIfAny(resolutionFacade) + ?.safeAs() + ?.original + ?.overriddenDescriptors + ?.toList() +} + +class ByInfoSuperFunctionsProvider( + private val resolutionFacade: ResolutionFacade, + private val converterContext: NewJ2kConverterContext +) : SuperFunctionsProvider() { + + private val labelToFunction by lazy(LazyThreadSafetyMode.NONE) { + val functions = mutableMapOf() + for (element in inferenceContext.elements) { + element.forEachDescendantOfType { function -> + val label = function.nameIdentifier?.getLabel() ?: return@forEachDescendantOfType + functions += label to function + } + } + functions + } + + override fun provideSuperFunctionDescriptors(function: KtFunction): List? = + function.nameIdentifier?.elementInfo(converterContext)?.firstIsInstanceOrNull() + ?.superFunctions + ?.mapNotNull { superFunction -> + when (superFunction) { + is ExternalSuperFunctionInfo -> superFunction.descriptor + is InternalSuperFunctionInfo -> + labelToFunction[superFunction.label]?.resolveToDescriptorIfAny(resolutionFacade) + } + } +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/boundTypes.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/boundTypes.kt new file mode 100644 index 00000000000..367f26d02f2 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/boundTypes.kt @@ -0,0 +1,79 @@ +/* + * 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 + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +sealed class ClassReference +class DescriptorClassReference(val descriptor: ClassDescriptor) : ClassReference() +class TypeParameterReference(val descriptor: TypeParameterDescriptor) : ClassReference() +object NoClassReference : ClassReference() + +val ClassDescriptor.classReference: DescriptorClassReference + get() = DescriptorClassReference(this) + +val ClassReference.descriptor: ClassDescriptor? + get() = safeAs()?.descriptor + +class TypeParameter(val boundType: BoundType, val variance: Variance) + +sealed class BoundType { + abstract val label: BoundTypeLabel + abstract val typeParameters: List + + companion object { + val LITERAL = BoundTypeImpl(LiteralLabel, emptyList()) + val STAR_PROJECTION = BoundTypeImpl(StarProjectionLabel, emptyList()) + val NULL = BoundTypeImpl(NullLiteralLabel, emptyList()) + } +} + +class BoundTypeImpl( + override val label: BoundTypeLabel, + override val typeParameters: List +) : BoundType() + + +class WithForcedStateBoundType( + val original: BoundType, + val forcedState: State +) : BoundType() { + override val label: BoundTypeLabel + get() = original.label + override val typeParameters: List + get() = original.typeParameters +} + +fun BoundType.withEnhancementFrom(from: BoundType) = when (from) { + is BoundTypeImpl -> this + is WithForcedStateBoundType -> WithForcedStateBoundType(this, from.forcedState) +} + +fun BoundType.enhanceWith(state: State?) = + if (state != null) WithForcedStateBoundType(this, state) + else this + +sealed class BoundTypeLabel + +class TypeVariableLabel(val typeVariable: TypeVariable) : BoundTypeLabel() +class TypeParameterLabel(val typeParameter: TypeParameterDescriptor) : BoundTypeLabel() +class GenericLabel(val classReference: ClassReference) : BoundTypeLabel() +object NullLiteralLabel : BoundTypeLabel() +object LiteralLabel : BoundTypeLabel() +object StarProjectionLabel : BoundTypeLabel() + + +fun TypeVariable.asBoundType(): BoundType = + BoundTypeImpl(TypeVariableLabel(this), typeParameters) + +val BoundType.typeVariable: TypeVariable? + get() = label.safeAs()?.typeVariable + +val BoundType.isReferenceToClass: Boolean + get() = label is TypeVariableLabel || label is GenericLabel \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/CallExpressionConstraintCollector.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/CallExpressionConstraintCollector.kt new file mode 100644 index 00000000000..96e4b375f21 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/CallExpressionConstraintCollector.kt @@ -0,0 +1,112 @@ +/* + * 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.collectors + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ParameterDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.nj2k.inference.common.* +import org.jetbrains.kotlin.psi.KtCallElement +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector +import org.jetbrains.kotlin.resolve.calls.components.isVararg +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +class CallExpressionConstraintCollector : ConstraintsCollector() { + override fun ConstraintBuilder.collectConstraints( + element: KtElement, + boundTypeCalculator: BoundTypeCalculator, + inferenceContext: InferenceContext, + resolutionFacade: ResolutionFacade + ) { + if (element !is KtCallElement) return + val call = element.resolveToCall(resolutionFacade) ?: return + val originalDescriptor = call.candidateDescriptor.safeAs()?.original ?: return + val valueArguments = call.valueArgumentsByIndex.orEmpty() + val typeParameterBindings = + call.candidateDescriptor.typeParameters.zip(call.call.typeArguments) { typeParameter, typeArgument -> + typeArgument.typeReference?.typeElement?.let { + inferenceContext.typeElementToTypeVariable[it] + }?.let { typeVariable -> + typeParameter?.let { it to typeVariable } + } + }.filterNotNull().toMap() + + val receiverExpressionBoundType = element.getQualifiedExpressionForSelector() + ?.receiverExpression + ?.boundType(inferenceContext) + + fun KotlinType.contextBoundType() = boundType( + contextBoundType = receiverExpressionBoundType, + call = call, + inferenceContext = inferenceContext + ) + + fun BoundType.substituteTypeParameters(): BoundType = + BoundTypeImpl( + when (label) { + is TypeVariableLabel -> (label as TypeVariableLabel) + .typeVariable + .safeAs() + ?.typeElement + ?.safeAs() + ?.let { typeParameterData -> + typeParameterBindings[typeParameterData.typeParameterDescriptor] + }?.let { typeVariable -> + TypeVariableLabel(typeVariable) + } ?: label + else -> label + }, + typeParameters.map { typeParameter -> + TypeParameter( + typeParameter.boundType.substituteTypeParameters(), + typeParameter.variance + ) + } + ).withEnhancementFrom(this) + + fun ParameterDescriptor.boundType() = + inferenceContext.declarationDescriptorToTypeVariable[this] + ?.asBoundType() + ?.substituteTypeParameters() + ?: original.type.contextBoundType() + + + if (receiverExpressionBoundType != null) run { + val receiverBoundType = + (originalDescriptor.extensionReceiverParameter ?: originalDescriptor.dispatchReceiverParameter)?.boundType() + ?: return@run + receiverExpressionBoundType.isSubtypeOf(receiverBoundType, ConstraintPriority.RECEIVER_PARAMETER) + } + + val parameterToArgument = call.candidateDescriptor.valueParameters.let { parameters -> + valueArguments.mapIndexed { i, arguments -> + val parameter = parameters[i] + val parameterBoundType = parameter.boundType() + + val parameterBoundTypeConsideringVararg = + if (parameter.isVararg && KotlinBuiltIns.isArrayOrPrimitiveArray(parameter.type)) { + if (KotlinBuiltIns.isPrimitiveArray(parameter.type)) + BoundTypeImpl( + GenericLabel(NoClassReference),//not important as it just a primitive type + emptyList() + ) else parameterBoundType.typeParameters[0].boundType + } else parameterBoundType + arguments.arguments.map { argument -> + parameterBoundTypeConsideringVararg to argument + } + } + }.flatten() + + for ((parameter, argument) in parameterToArgument) { + val argumentExpression = argument.getArgumentExpression() ?: continue + argumentExpression.isSubtypeOf(parameter, ConstraintPriority.PARAMETER) + } + } +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/CommonConstraintsCollector.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/CommonConstraintsCollector.kt new file mode 100644 index 00000000000..5614f8ca3a7 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/CommonConstraintsCollector.kt @@ -0,0 +1,135 @@ +/* + * 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.collectors + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.nj2k.inference.common.BoundTypeCalculator +import org.jetbrains.kotlin.nj2k.inference.common.ConstraintBuilder +import org.jetbrains.kotlin.nj2k.inference.common.ConstraintPriority +import org.jetbrains.kotlin.nj2k.inference.common.InferenceContext +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.asAssignment +import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunction +import org.jetbrains.kotlin.resolve.calls.callUtil.getType +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +class CommonConstraintsCollector : ConstraintsCollector() { + override fun ConstraintBuilder.collectConstraints( + element: KtElement, + boundTypeCalculator: BoundTypeCalculator, + inferenceContext: InferenceContext, + resolutionFacade: ResolutionFacade + ) = with(boundTypeCalculator) { + when { + element is KtBinaryExpressionWithTypeRHS && KtPsiUtil.isUnsafeCast(element) -> { + element.right?.typeElement?.let { inferenceContext.typeElementToTypeVariable[it] }?.also { typeVariable -> + element.left.isSubtypeOf(typeVariable, ConstraintPriority.ASSIGNMENT) + } + } + + element is KtBinaryExpression && element.asAssignment() != null -> { + element.right?.isSubtypeOf(element.left ?: return, ConstraintPriority.ASSIGNMENT) + } + + + element is KtVariableDeclaration -> { + inferenceContext.declarationToTypeVariable[element]?.also { typeVariable -> + element.initializer?.isSubtypeOf(typeVariable, ConstraintPriority.INITIALIZER) + } + } + + element is KtParameter -> { + inferenceContext.declarationToTypeVariable[element]?.also { typeVariable -> + element.defaultValue?.isSubtypeOf( + typeVariable, + ConstraintPriority.INITIALIZER + ) + } + } + + element is KtReturnExpression -> { + val functionTypeVariable = element.getTargetFunction(element.analyze(resolutionFacade)) + ?.resolveToDescriptorIfAny(resolutionFacade) + ?.let { functionDescriptor -> + inferenceContext.declarationDescriptorToTypeVariable[functionDescriptor] + } ?: return + element.returnedExpression?.isSubtypeOf( + functionTypeVariable, + ConstraintPriority.RETURN + ) + } + + element is KtReturnExpression -> { + val targetTypeVariable = + element.getTargetFunction(element.analyze(resolutionFacade))?.let { function -> + inferenceContext.declarationToTypeVariable[function] + } + if (targetTypeVariable != null) { + element.returnedExpression?.isSubtypeOf( + targetTypeVariable, + ConstraintPriority.RETURN + ) + } + } + + element is KtLambdaExpression -> { + val targetTypeVariable = + inferenceContext.declarationToTypeVariable[element.functionLiteral] ?: return + element.functionLiteral.bodyExpression?.statements?.lastOrNull() + ?.takeIf { it !is KtReturnExpression } + ?.also { implicitReturn -> + implicitReturn.isSubtypeOf( + targetTypeVariable, + ConstraintPriority.RETURN + ) + } + } + + element is KtForExpression -> { + val loopParameterTypeVariable = + element.loopParameter?.typeReference?.typeElement?.let { typeElement -> + inferenceContext.typeElementToTypeVariable[typeElement] + } + if (loopParameterTypeVariable != null) { + val loopRangeBoundType = element.loopRange?.boundType(inferenceContext) ?: return + val boundType = + element.loopRangeElementType(resolutionFacade) + ?.boundType( + contextBoundType = loopRangeBoundType, + inferenceContext = inferenceContext + ) ?: return + loopParameterTypeVariable.isSubtypeOf( + boundType.typeParameters.firstOrNull()?.boundType ?: return, + ConstraintPriority.ASSIGNMENT + ) + } + } + } + Unit + } + + private fun KtForExpression.loopRangeElementType(resolutionFacade: ResolutionFacade): KotlinType? { + val loopRangeType = loopRange?.getType(analyze(resolutionFacade)) ?: return null + return loopRangeType + .constructor + .declarationDescriptor + ?.safeAs() + ?.getMemberScope(loopRangeType.arguments) + ?.getDescriptorsFiltered(DescriptorKindFilter.FUNCTIONS) { + it.asString() == "iterator" + }?.filterIsInstance() + ?.firstOrNull { it.valueParameters.isEmpty() } + ?.original + ?.returnType + } +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/ConstraintsCollector.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/ConstraintsCollector.kt new file mode 100644 index 00000000000..a4493f10282 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/ConstraintsCollector.kt @@ -0,0 +1,21 @@ +/* + * 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.collectors + +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.nj2k.inference.common.BoundTypeCalculator +import org.jetbrains.kotlin.nj2k.inference.common.ConstraintBuilder +import org.jetbrains.kotlin.nj2k.inference.common.InferenceContext +import org.jetbrains.kotlin.psi.KtElement + +abstract class ConstraintsCollector { + abstract fun ConstraintBuilder.collectConstraints( + element: KtElement, + boundTypeCalculator: BoundTypeCalculator, + inferenceContext: InferenceContext, + resolutionFacade: ResolutionFacade + ) +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/FunctionConstraintsCollector.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/FunctionConstraintsCollector.kt new file mode 100644 index 00000000000..e86636ea4b0 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/collectors/FunctionConstraintsCollector.kt @@ -0,0 +1,105 @@ +/* + * 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.collectors + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi +import org.jetbrains.kotlin.nj2k.inference.common.* +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtTypeElement +import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +class FunctionConstraintsCollector( + private val superFunctionsProvider: SuperFunctionsProvider +) : ConstraintsCollector() { + override fun ConstraintBuilder.collectConstraints( + element: KtElement, + boundTypeCalculator: BoundTypeCalculator, + inferenceContext: InferenceContext, + resolutionFacade: ResolutionFacade + ) { + if (element !is KtFunction) return + superFunctionsProvider.inferenceContext = inferenceContext + val ktClass = element.containingClassOrObject ?: return + val classDescriptor = ktClass.resolveToDescriptorIfAny(resolutionFacade) ?: return + + val superFunctions = superFunctionsProvider.provideSuperFunctionDescriptors(element) ?: return + val substitutor = inferenceContext.classSubstitutions[classDescriptor] ?: return + + for (superFunction in superFunctions) { + val superClass = superFunction.containingDeclaration as? ClassDescriptor ?: continue + val superFunctionPsi = superFunction.original.findPsi() as? KtNamedFunction + + run { + collectTypeConstraints( + element.typeReference?.typeElement ?: return@run, + superFunction.original.returnType ?: return@run, + superFunctionPsi?.typeReference?.typeElement, + substitutor, + superClass, + inferenceContext + ) + } + + for (parameterIndex in element.valueParameters.indices) { + collectTypeConstraints( + element.valueParameters.getOrNull(parameterIndex)?.typeReference?.typeElement ?: continue, + superFunction.valueParameters.getOrNull(parameterIndex)?.original?.type ?: continue, + superFunctionPsi?.valueParameters?.getOrNull(parameterIndex)?.typeReference?.typeElement, + substitutor, + superClass, + inferenceContext + ) + } + } + } + + private fun ConstraintBuilder.collectTypeConstraints( + typeElement: KtTypeElement, + superType: KotlinType, + superTypeElement: KtTypeElement?, + substitutor: ClassSubstitutor, + superClass: ClassDescriptor, + inferenceContext: InferenceContext + ) { + val usedTypeVariables = hashSetOf() + val substitutions = calculateTypeSubstitutions(typeElement, superType) ?: return + for ((innerTypeElement, innerTypeParameter) in substitutions) { + val superEntryTypeElement = substitutor[superClass, innerTypeParameter] ?: continue + innerTypeElement.isTheSameTypeAs(superEntryTypeElement, ConstraintPriority.SUPER_DECLARATION) + + inferenceContext.typeElementToTypeVariable[innerTypeElement]?.also { usedTypeVariables += it } + } + val superTypeVariable = superTypeElement?.let { inferenceContext.typeElementToTypeVariable[it] } + if (superTypeVariable != null) { + superTypeVariable.isTheSameTypeAs(typeElement, ConstraintPriority.SUPER_DECLARATION, usedTypeVariables) + } else { + superType.boundType(forceEnhance = true, inferenceContext = inferenceContext) + .isTheSameTypeAs(typeElement, ConstraintPriority.SUPER_DECLARATION, usedTypeVariables) + } + + } + + private fun calculateTypeSubstitutions( + typeElement: KtTypeElement, + superType: KotlinType + ): List>? { + val substitution = superType.constructor.declarationDescriptor + ?.safeAs()?.let { typeElement to it } + return typeElement.typeArgumentsAsTypes.zip(superType.arguments) + .flatMap { (argumentTypeElement, argumentType) -> + calculateTypeSubstitutions(argumentTypeElement?.typeElement ?: return null, argumentType.type) ?: return null + } + listOfNotNull(substitution) + } + +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/typeVariables.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/typeVariables.kt new file mode 100644 index 00000000000..b64da3f6eaa --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/typeVariables.kt @@ -0,0 +1,94 @@ +/* + * 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 + +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.psi.KtTypeElement +import org.jetbrains.kotlin.types.KotlinType + +sealed class TypeVariable { + abstract val classReference: ClassReference + abstract val typeParameters: List + abstract var state: State +} + +sealed class TypeElementData { + abstract val typeElement: KtTypeElement +} + +data class TypeElementDataImpl(override val typeElement: KtTypeElement) : TypeElementData() +data class TypeParameterElementData( + override val typeElement: KtTypeElement, + val typeParameterDescriptor: TypeParameterDescriptor +) : TypeElementData() + +data class TypeElementBasedTypeVariable( + override val classReference: ClassReference, + override val typeParameters: List, + val typeElement: TypeElementData, + override var state: State +) : TypeVariable() { + + //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 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 typeParameters: List, + val type: KotlinType, + override var state: State +) : TypeVariable() { + + //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 + get() = state != State.UNKNOWN + +fun TypeVariable.setStateIfNotFixed(newState: State) { + if (!isFixed) { + state = newState + } +} + diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/utils.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/utils.kt new file mode 100644 index 00000000000..25d9d2eb1e6 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/utils.kt @@ -0,0 +1,30 @@ +/* + * 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 + +import com.intellij.psi.PsiComment +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.nj2k.JKElementInfo +import org.jetbrains.kotlin.nj2k.JKElementInfoLabel +import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext +import org.jetbrains.kotlin.nj2k.asLabel +import org.jetbrains.kotlin.psi.KtTypeProjection +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +fun PsiElement.getLabel(): JKElementInfoLabel? = + prevSibling + ?.safeAs() + ?.text + ?.asLabel() + ?: parent + ?.safeAs() + ?.getLabel() + + +fun PsiElement.elementInfo(converterContext: NewJ2kConverterContext): List? = + getLabel()?.let { label -> + converterContext.elementsInfoStorage.getInfoForLabel(label) + } diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityBoundTypeEnhancer.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityBoundTypeEnhancer.kt new file mode 100644 index 00000000000..c80ddf041cf --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityBoundTypeEnhancer.kt @@ -0,0 +1,117 @@ +/* + * 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.ConstructorDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall +import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.resolve.frontendService +import org.jetbrains.kotlin.nj2k.inference.common.* +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callUtil.getType +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue +import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory +import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability +import org.jetbrains.kotlin.resolve.jvm.checkers.mustNotBeNull +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.isNullable +import org.jetbrains.kotlin.util.javaslang.getOrNull + +class NullabilityBoundTypeEnhancer(private val resolutionFacade: ResolutionFacade) : BoundTypeEnhancer() { + override fun enhance( + expression: KtExpression, + boundType: BoundType, + inferenceContext: InferenceContext + ): BoundType { + return when { + expression.isNullExpression() -> + WithForcedStateBoundType(boundType, State.UPPER) + expression is KtCallExpression -> enhanceCallExpression(expression, boundType, inferenceContext) + expression is KtQualifiedExpression && expression.selectorExpression is KtCallExpression -> + enhanceCallExpression(expression.selectorExpression as KtCallExpression, boundType, inferenceContext) + expression is KtNameReferenceExpression -> + boundType.enhanceWith(expression.smartCastEnhancement()) + expression is KtLambdaExpression -> + WithForcedStateBoundType(boundType, State.LOWER) + else -> boundType + } + } + + private fun enhanceCallExpression( + expression: KtCallExpression, + boundType: BoundType, + inferenceContext: InferenceContext + ): BoundType { + if (expression.resolveToCall(resolutionFacade)?.candidateDescriptor is ConstructorDescriptor) { + return WithForcedStateBoundType(boundType, State.LOWER) + } + + val resolved = expression.calleeExpression?.mainReference?.resolve() ?: return boundType + if (inferenceContext.isInConversionScope(resolved)) return boundType + return boundType.enhanceWith(expression.getExternallyAnnotatedForcedState()) + } + + override fun enhanceKotlinType( + type: KotlinType, + boundType: BoundType, + allowLowerEnhancement: Boolean, + inferenceContext: InferenceContext + ): BoundType { + if (type.arguments.size != boundType.typeParameters.size) return boundType + val inner = BoundTypeImpl( + boundType.label, + boundType.typeParameters.zip(type.arguments) { typeParameter, typeArgument -> + TypeParameter( + enhanceKotlinType( + typeArgument.type, + typeParameter.boundType, + allowLowerEnhancement, + inferenceContext + ), + typeParameter.variance + ) + } + ) + val enhancement = when { + type.isMarkedNullable -> State.UPPER + allowLowerEnhancement -> State.LOWER + else -> null + } + return inner.enhanceWith(enhancement) + } + + private fun KtReferenceExpression.smartCastEnhancement() = analyzeExpressionUponTheTypeInfo { dataFlowValue, dataFlowInfo, _ -> + if (dataFlowInfo.completeNullabilityInfo.get(dataFlowValue)?.getOrNull() == Nullability.NOT_NULL) State.LOWER + else null + } + + private inline fun KtExpression.analyzeExpressionUponTheTypeInfo(analyzer: (DataFlowValue, DataFlowInfo, KotlinType) -> State?): State? { + val bindingContext = analyze(resolutionFacade) + val type = getType(bindingContext) ?: return null + + val dataFlowValue = resolutionFacade.frontendService() + .createDataFlowValue(this, type, bindingContext, resolutionFacade.moduleDescriptor) + val dataFlowInfo = bindingContext[BindingContext.EXPRESSION_TYPE_INFO, this]?.dataFlowInfo ?: return null + return analyzer(dataFlowValue, dataFlowInfo, type) + } + + private fun KtExpression.getExternallyAnnotatedForcedState() = analyzeExpressionUponTheTypeInfo { dataFlowValue, dataFlowInfo, type -> + if (!type.isNullable()) return@analyzeExpressionUponTheTypeInfo State.LOWER + when { + dataFlowInfo.completeNullabilityInfo.get(dataFlowValue)?.getOrNull() == Nullability.NOT_NULL -> State.LOWER + type.isExternallyAnnotatedNotNull(dataFlowInfo, dataFlowValue) -> State.LOWER + else -> null + } + } + + private fun KotlinType.isExternallyAnnotatedNotNull(dataFlowInfo: DataFlowInfo, dataFlowValue: DataFlowValue): Boolean = + mustNotBeNull()?.isFromJava == true && dataFlowInfo.getStableNullability(dataFlowValue).canBeNull() +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityConstraintsCollector.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityConstraintsCollector.kt new file mode 100644 index 00000000000..3876666ddd4 --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityConstraintsCollector.kt @@ -0,0 +1,55 @@ +/* + * 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.idea.intentions.branchedTransformations.isNullExpression +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.nj2k.inference.common.* +import org.jetbrains.kotlin.nj2k.inference.common.collectors.ConstraintsCollector +import org.jetbrains.kotlin.psi.* + +class NullabilityConstraintsCollector : ConstraintsCollector() { + override fun ConstraintBuilder.collectConstraints( + element: KtElement, + boundTypeCalculator: BoundTypeCalculator, + inferenceContext: InferenceContext, + resolutionFacade: ResolutionFacade + ) = with(boundTypeCalculator) { + when { + element is KtBinaryExpression && + (element.left?.isNullExpression() == true + || element.right?.isNullExpression() == true) -> { + val notNullOperand = + if (element.left?.isNullExpression() == true) element.right + else element.left + notNullOperand?.isTheSameTypeAs(State.UPPER, ConstraintPriority.COMPARE_WITH_NULL) + } + element is KtQualifiedExpression -> { + element.receiverExpression.isTheSameTypeAs(State.LOWER, ConstraintPriority.USE_AS_RECEIVER) + } + + element is KtForExpression -> { + element.loopRange?.isTheSameTypeAs(State.LOWER, ConstraintPriority.USE_AS_RECEIVER) + } + + element is KtWhileExpressionBase -> { + element.condition?.isTheSameTypeAs(State.LOWER, ConstraintPriority.USE_AS_RECEIVER) + } + + element is KtIfExpression -> { + element.condition?.isTheSameTypeAs(State.LOWER, ConstraintPriority.USE_AS_RECEIVER) + } + element is KtValueArgument && element.isSpread -> { + element.getArgumentExpression()?.isTheSameTypeAs(State.LOWER, ConstraintPriority.USE_AS_RECEIVER) + } + element is KtBinaryExpression && !KtPsiUtil.isAssignment(element) -> { + element.left?.isTheSameTypeAs(State.LOWER, ConstraintPriority.USE_AS_RECEIVER) + element.right?.isTheSameTypeAs(State.LOWER, ConstraintPriority.USE_AS_RECEIVER) + } + } + Unit + } +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityContextCollector.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityContextCollector.kt new file mode 100644 index 00000000000..3a28d106f3c --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityContextCollector.kt @@ -0,0 +1,43 @@ +/* + * 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.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext +import org.jetbrains.kotlin.nj2k.UnknownNullability +import org.jetbrains.kotlin.nj2k.inference.common.ClassReference +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.KtTypeElement +import org.jetbrains.kotlin.psi.KtTypeReference +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +class NullabilityContextCollector( + resolutionFacade: ResolutionFacade, + private val converterContext: NewJ2kConverterContext +) : ContextCollector(resolutionFacade) { + override fun ClassReference.getState(typeElement: KtTypeElement?): State? { + val hasUndefinedNullabilityLabel = typeElement + ?.parent + ?.safeAs() + ?.hasUndefinedNullabilityLabel(converterContext) + ?: 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 +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityStateUpdater.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityStateUpdater.kt new file mode 100644 index 00000000000..e02913a234f --- /dev/null +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityStateUpdater.kt @@ -0,0 +1,56 @@ +/* + * 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.* +import org.jetbrains.kotlin.psi.KtNullableType +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.KtTypeElement +import org.jetbrains.kotlin.psi.psiUtil.isAncestor + +class NullabilityStateUpdater : StateUpdater() { + override fun updateStates(inferenceContext: InferenceContext) { + if (inferenceContext.typeVariables.isEmpty()) return + + val deepComparator = Comparator { o1, o2 -> + if (o1.typeElement.typeElement.isAncestor(o2.typeElement.typeElement)) 1 else -1 + } + for (typeVariable in inferenceContext + .typeVariables + .filterIsInstance() + .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) + } + } + } + } + } + + private fun TypeElementBasedTypeVariable.changeState(toNullable: Boolean) { + changeState(typeElement.typeElement, toNullable) + } + + companion object { + fun changeState(typeElement: KtTypeElement, toNullable: Boolean) { + val factory = KtPsiFactory(typeElement) + if (typeElement is KtNullableType && !toNullable) { + typeElement.replace(factory.createType(typeElement.innerType?.text ?: return).typeElement ?: return) + } + if (typeElement !is KtNullableType && toNullable) { + typeElement.replace(factory.createType("${typeElement.text}?").typeElement ?: return) + } + } + } + +} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/BoundTypeStorage.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/BoundTypeStorage.kt deleted file mode 100644 index 9a40f2724e2..00000000000 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/BoundTypeStorage.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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.nullabilityAnalysis - -import com.intellij.psi.PsiComment -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.references.mainReference -import org.jetbrains.kotlin.nj2k.postProcessing.resolve -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespace -import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector -import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.callUtil.getType -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.isNullable -import org.jetbrains.kotlin.types.typeUtil.builtIns -import org.jetbrains.kotlin.utils.addToStdlib.safeAs - -internal class BoundTypeStorage(private val analysisAnalysisContext: AnalysisContext, private val printConstraints: Boolean) { - private val cache = mutableMapOf() - private val printer = Printer(analysisAnalysisContext) - - fun boundTypeFor(expression: KtExpression): BoundType = - cache.getOrPut(expression) { - val boundType = - when (expression) { - is KtParenthesizedExpression -> expression.expression?.let { boundTypeFor(it) } - is KtQualifiedExpression -> - expression.selectorExpression?.toBoundType( - boundTypeFor(expression.receiverExpression) - ) - is KtLabeledExpression -> expression.baseExpression?.let { boundTypeFor(it) } - is KtLambdaExpression -> lambdaBoundType(expression) - else -> expression.getQualifiedExpressionForSelector()?.let { boundTypeFor(it) } - } ?: expression.toBoundType(null) - ?: LiteralBoundType(expression.isNullable()) - - if (printConstraints) { - if (expression.getNextSiblingIgnoringWhitespace() !is PsiComment) { - val comment = with(printer) { - KtPsiFactory(expression.project).createComment("/*${boundType.asString()}*/") - } - expression.parent.addAfter(comment, expression) - } - } - boundType.withForcedNullability(expression.getForcedNullability()) - } - - private fun lambdaBoundType(lambda: KtLambdaExpression): BoundType? { - val builtIns = lambda.getType(lambda.analyze())?.builtIns ?: return null - - val descriptor = builtIns.getFunction(lambda.valueParameters.size) - val parameterBoundTypes = lambda.valueParameters.map { parameter -> - parameter.typeReference?.typeElement?.let { typeElement -> - analysisAnalysisContext.typeElementToTypeVariable[typeElement] - }?.let { - BoundTypeTypeParameter(TypeVariableBoundType(it), Variance.IN_VARIANCE) - } ?: return null - } - val returnBoundType = - BoundTypeTypeParameter( - TypeVariableBoundType( - analysisAnalysisContext.declarationToTypeVariable[lambda.functionLiteral] ?: return null - ), - Variance.OUT_VARIANCE - ) - return GenericBoundType( - DescriptorClassReference(descriptor), - parameterBoundTypes + returnBoundType, - forcedNullabilityTo = null, - isNull = false - ) - } - - - fun boundTypeForType( - type: KotlinType, - contextBoundType: BoundType?, - typeParameterDescriptors: Map - ): BoundType? = - type.toBoundType(contextBoundType, typeParameterDescriptors) - - private fun KtExpression.resolveToTypeVariable(): TypeVariable? = - getCalleeExpressionIfAny() - ?.safeAs() - ?.resolve() - ?.safeAs() - ?.let { - analysisAnalysisContext.declarationToTypeVariable[it] - } ?: KtPsiUtil.deparenthesize(this)?.let { analysisAnalysisContext.declarationToTypeVariable[it] } - - private fun KtExpression.toBoundTypeAsTypeVariable(): BoundType? { - val typeVariableBoundType = resolveToTypeVariable()?.let { - TypeVariableBoundType(it, null) - } ?: return null - val asReferenceToVarArgParameter = - safeAs() - ?.mainReference - ?.resolve() - ?.safeAs() - ?.takeIf { it.isVarArg } - return if (asReferenceToVarArgParameter != null) { - GenericBoundType( - UnknownClassReference("Array"),//TODO - listOf(BoundTypeTypeParameter(typeVariableBoundType, Variance.INVARIANT)), - isNull = false - ) - } else typeVariableBoundType - } - - private fun KtExpression.toBoundTypeAsCallExpression(contextBoundType: BoundType?): BoundType? { - val typeElement = getCalleeExpressionIfAny() - ?.safeAs() - ?.resolve() - ?.safeAs() - ?.typeReference - ?.typeElement - typeElement?.let { analysisAnalysisContext.typeElementToTypeVariable[it] }?.also { - return TypeVariableBoundType(it) - } - val bindingContext = analyze() - val descriptor = - getResolvedCall(bindingContext)?.candidateDescriptor?.original?.safeAs() ?: return null - val typeParameters = - run { - if (this is KtCallElement) { - typeArguments.mapIndexed { index, typeArgument -> - //TODO better check - val typeParameter = descriptor.typeParameters.getOrNull(index) ?: return@run null - val typeVariable = - analysisAnalysisContext.typeElementToTypeVariable[typeArgument.typeReference?.typeElement ?: return@run null] - ?: return@run null - typeParameter to typeVariable - }.toMap() - } else emptyMap() - } ?: emptyMap() - return descriptor.returnType?.toBoundType(contextBoundType, typeParameters) - } - - private fun KtExpression.toBoundTypeAsCastExpression(): BoundType? { - val castExpression = KtPsiUtil.deparenthesize(this) - ?.safeAs() - ?.takeIf { KtPsiUtil.isUnsafeCast(it) } - ?: return null - return castExpression.right?.typeElement - ?.let { analysisAnalysisContext.typeElementToTypeVariable[it] } - ?.let { TypeVariableBoundType(it) } - } - - private fun KtExpression.toBoundType(contextBoundType: BoundType?): BoundType? = - toBoundTypeAsTypeVariable() - ?: toBoundTypeAsCallExpression(contextBoundType) - ?: toBoundTypeAsCastExpression() - - private fun KotlinType.toBoundType( - contextBoundType: BoundType?, - typeParameterDescriptors: Map - ): BoundType? { - fun KotlinType.toBoundType(): BoundType? { - val forcedNullability = when { - isMarkedNullable -> Nullability.NULLABLE - else -> null - } - val target = constructor.declarationDescriptor - return when (target) { - is ClassDescriptor -> { - val classReference = DescriptorClassReference(target) - GenericBoundType( - classReference, - (arguments zip constructor.parameters).map { (typeArgument, typeParameter) -> - BoundTypeTypeParameter( - typeArgument.type.toBoundType() ?: return null, - typeParameter.variance - ) - }, - forcedNullability, - isNullable() - ) - - } - is TypeParameterDescriptor -> { - when { - target in typeParameterDescriptors -> - TypeVariableBoundType(typeParameterDescriptors.getValue(target), forcedNullability) - contextBoundType != null -> - contextBoundType.typeParameters.getOrNull(target.index)?.boundType?.withForcedNullability(forcedNullability) - else -> null - } - } - else -> error(toString()) - } - } - return toBoundType() - } -} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/ConstraintBuilder.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/ConstraintBuilder.kt deleted file mode 100644 index d969dcf6dc0..00000000000 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/ConstraintBuilder.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.nullabilityAnalysis - -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.utils.addToStdlib.safeAs - -internal class ConstraintBuilder(val boundTypeStorage: BoundTypeStorage) { - private val constraints = mutableListOf() - - internal fun getConstraints(): List = constraints - - fun KtExpression.addSubtypeNullabilityConstraint(typeVariable: TypeVariable, cameFrom: ConstraintCameFrom) { - addSubtypeNullabilityConstraint(TypeVariableBoundType(typeVariable), cameFrom) - } - - fun KtExpression.addEqualsNullabilityConstraint(nullability: Nullability, cameFrom: ConstraintCameFrom) { - val boundType = boundTypeStorage.boundTypeFor(this).safeAs() - ?: return - constraints += EqualConstraint(boundType.bound, LiteralBound(nullability), cameFrom) - } - - fun TypeVariable.addEqualsNullabilityConstraint(other: BoundType, cameFrom: ConstraintCameFrom) { - TypeVariableBoundType(this).isTheSameType(other, cameFrom) - } - - fun KtExpression.addSubtypeNullabilityConstraint(upperTypeExpression: KtExpression, cameFrom: ConstraintCameFrom) { - boundTypeStorage.boundTypeFor(this).subtypeOf(boundTypeStorage.boundTypeFor(upperTypeExpression), cameFrom) - } - - fun KtExpression.addSubtypeNullabilityConstraint(upperBoundType: BoundType, cameFrom: ConstraintCameFrom) { - boundTypeStorage.boundTypeFor(this) - .subtypeOf(upperBoundType, cameFrom) - } - - fun TypeVariable.subtypeOf(other: BoundType, cameFrom: ConstraintCameFrom) { - TypeVariableBoundType(this).subtypeOf(other, cameFrom) - } - - fun BoundType.subtypeOf(other: BoundType, cameFrom: ConstraintCameFrom) { - (typeParameters zip other.typeParameters).forEach { (left, right) -> - val variance = left.variance - when (variance) { - Variance.OUT_VARIANCE -> left.boundType.subtypeOf(right.boundType, cameFrom) - Variance.IN_VARIANCE -> right.boundType.subtypeOf(left.boundType, cameFrom) - Variance.INVARIANT -> right.boundType.isTheSameType(left.boundType, cameFrom) - } - } - - constraints += SubtypeConstraint(bound, other.bound, cameFrom) - } - - fun BoundType.isTheSameType(other: BoundType, cameFrom: ConstraintCameFrom) { - (typeParameters zip other.typeParameters).forEach { (left, right) -> - left.boundType.isTheSameType(right.boundType, cameFrom) - } - constraints += EqualConstraint(bound, other.bound, cameFrom) - } -} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/constraints.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/constraints.kt deleted file mode 100644 index ba51bc2fa8b..00000000000 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/constraints.kt +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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.nullabilityAnalysis - -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiTypeParameter -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.utils.addToStdlib.safeAs - - -internal interface TypeVariableOwner { - val target: KtElement -} - -internal interface SingleTypeVariableOwner : TypeVariableOwner { - val typeVariable: TypeVariable -} - -internal interface MultipleTypeVariablesOwner : TypeVariableOwner { - val typeVariables: List -} - -internal val TypeVariableOwner.allTypeVariables - get() = when (this) { - is SingleTypeVariableOwner -> listOf(typeVariable) - is MultipleTypeVariablesOwner -> typeVariables - else -> error("TypeVariableOwner should be either SingleTypeVariableOwner or MultipleTypeVariablesOwner") - } - - -internal interface DeclarationTypeVariableOwner : SingleTypeVariableOwner { - override val target: KtCallableDeclaration -} - -internal data class PropertyTarget( - override val target: KtProperty, - override val typeVariable: TypeVariable -) : DeclarationTypeVariableOwner - -internal data class FunctionTarget( - override val target: KtNamedFunction, - override val typeVariable: TypeVariable -) : DeclarationTypeVariableOwner - -internal data class LambdaTarget( - override val target: KtFunctionLiteral, - override val typeVariable: TypeVariable -) : DeclarationTypeVariableOwner - -internal data class ParameterTarget( - override val target: KtParameter, - override val typeVariable: TypeVariable -) : DeclarationTypeVariableOwner - -internal data class TypeCastTarget( - override val target: KtBinaryExpressionWithTypeRHS, - override val typeVariable: TypeVariable -) : SingleTypeVariableOwner - -internal data class FunctionCallTypeArgumentTarget( - override val target: KtCallExpression, - override val typeVariables: List -) : MultipleTypeVariablesOwner - - -internal interface ClassReference -internal data class KtClassReference(val klass: KtClassOrObject) : ClassReference -internal data class DescriptorClassReference(val descriptor: ClassDescriptor) : ClassReference -internal data class JavaClassReference(val klass: PsiClass) : ClassReference -internal data class TypeParameterClassReference(val typeParameter: KtTypeParameter) : ClassReference -internal data class UnknownClassReference(val text: String) : ClassReference -internal object LiteralClassReference : ClassReference - - -internal interface BoundType { - val classReference: ClassReference - val typeParameters: List - val forcedNullabilityTo: Nullability? -} - -internal class TypeVariableBoundType( - val typeVariable: TypeVariable, - override val forcedNullabilityTo: Nullability? = null -) : BoundType { - override val classReference: ClassReference = typeVariable.classReference - override val typeParameters: List = - typeVariable.typeParameters.map { typeParameter -> - val boundType = - if (typeParameter is TypeVariableTypeParameterWithTypeParameter) - TypeVariableBoundType(typeParameter.typeVariable) - else StarProjectionBoundType - - BoundTypeTypeParameter( - boundType, - typeParameter.variance //TODO isMarkedNullable - ) - } -} - -internal class GenericBoundType( - override val classReference: ClassReference, - override val typeParameters: List, - override val forcedNullabilityTo: Nullability? = null, - val isNull: Boolean -) : BoundType - -internal class LiteralBoundType(val isNull: Boolean) : BoundType { - override val classReference = LiteralClassReference - override val typeParameters: List = emptyList() - override val forcedNullabilityTo: Nullability? = null -} - - -internal class TypeVariable( - val typeElement: KtTypeElement?, - val classReference: ClassReference, - val typeParameters: List, - var nullability: Nullability -) - -internal inline val BoundType.bound - get() = - when { - forcedNullabilityTo != null -> LiteralBound(forcedNullabilityTo!!) - this is TypeVariableBoundType -> TypeVariableBound(typeVariable) - this is LiteralBoundType -> LiteralBound(isNull.nullableForTrue()) - this is GenericBoundType -> LiteralBound(isNull.nullableForTrue()) - this is StarProjectionBoundType -> LiteralBound(Nullability.NULLABLE) - else -> error("Bad bound type $this") - } - -internal inline fun T.withForcedNullability(nullability: Nullability?): T = - if (forcedNullabilityTo == nullability || nullability == null) this - else when (this) { - is GenericBoundType -> - GenericBoundType( - classReference, - typeParameters, - nullability, - isNull - ) - is TypeVariableBoundType -> - TypeVariableBoundType( - typeVariable, - nullability - ) - is LiteralBoundType -> this - else -> this - } as T - -internal interface TypeVariableTypeParameter { - val variance: Variance -} - -internal data class TypeVariableTypeParameterWithTypeParameter( - val typeVariable: TypeVariable, - override val variance: Variance -) : TypeVariableTypeParameter - -internal object TypeVariableStartProjectionTypeParameter : TypeVariableTypeParameter { - override val variance = Variance.INVARIANT //TODO ?? -} - - -internal data class BoundTypeTypeParameter( - val boundType: BoundType, - val variance: Variance -) - -internal object StarProjectionBoundType : BoundType { - override val classReference = UnknownClassReference("*")//TODO - override val typeParameters: List = emptyList() - override val forcedNullabilityTo = null -} - -internal interface Constraint { - val cameFrom: ConstraintCameFrom -} - -interface ConstraintBound - -internal data class TypeVariableBound(val typeVariable: TypeVariable) : ConstraintBound -internal data class LiteralBound(val nullability: Nullability) : ConstraintBound - -internal data class SubtypeConstraint( - var lowerBound: ConstraintBound, - var upperBound: ConstraintBound, - override val cameFrom: ConstraintCameFrom -) : Constraint - -enum class ConstraintCameFrom { - SUPER_DECLARATION, - INITIALIZER, - COMPARED_WITH_NULL, - ASSIGNMENT_TARGET, - USED_AS_RECEIVER, - PARAMETER_PASSED -} - -internal data class EqualConstraint( - val leftBound: ConstraintBound, - val rightBound: ConstraintBound, - override val cameFrom: ConstraintCameFrom -) : Constraint - - -private fun PsiTypeParameter.variance() = Variance.INVARIANT//TODO real variance - -internal fun ClassReference.typeParametersVariance(parameterIndex: Int): Variance = - when (this) { - is KtClassReference -> klass.typeParameters.getOrNull(parameterIndex)?.variance ?: Variance.INVARIANT - is JavaClassReference -> klass.typeParameters.getOrNull(parameterIndex)?.variance() ?: Variance.INVARIANT - is DescriptorClassReference -> descriptor.typeConstructor.parameters[parameterIndex].variance - is TypeParameterClassReference -> Variance.INVARIANT - is UnknownClassReference -> Variance.INVARIANT - else -> error("Bad class reference `$this`") - } - -internal fun TypeVariable.setNullabilityIfNotFixed(nullability: Nullability) { - if (!isFixed) { - this.nullability = nullability - } -} - -internal val TypeVariable.isFixed: Boolean - get() = nullability != Nullability.UNKNOWN - -enum class Nullability { - NULLABLE, NOT_NULL, UNKNOWN -} - -internal fun Boolean.nullableForTrue() = - if (this) Nullability.NULLABLE else Nullability.NOT_NULL - - -internal fun TypeVariableOwner.innerTypeVariables(): List = - when (this) { - is SingleTypeVariableOwner -> typeVariable.innerTypeVariables() - is MultipleTypeVariablesOwner -> typeVariables.flatMap { it.innerTypeVariables() } - else -> error("") - } - -internal fun TypeVariable.innerTypeVariables(): List = - typeParameters.flatMap { typeParameter -> - typeParameter.safeAs()?.let { typeVariableTypeParameter -> - typeVariableTypeParameter.typeVariable.innerTypeVariables() + listOfNotNull(typeVariableTypeParameter.typeVariable) - }.orEmpty() - } \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/constraintsCollector.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/constraintsCollector.kt deleted file mode 100644 index 5fc249f8f1f..00000000000 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/constraintsCollector.kt +++ /dev/null @@ -1,310 +0,0 @@ -/* - * 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.nullabilityAnalysis - -import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression -import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi -import org.jetbrains.kotlin.nj2k.* -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.asAssignment -import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType -import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunction -import org.jetbrains.kotlin.resolve.calls.callUtil.getType -import org.jetbrains.kotlin.resolve.calls.components.isVararg -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter -import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -import org.jetbrains.kotlin.utils.addToStdlib.safeAs - - -internal class LabelToFunctionTypeVariableMapper(analysisContext: AnalysisContext) { - private val labelToFunction = analysisContext.declarationToTypeVariable.mapNotNull { (declaration, _) -> - if (declaration !is KtNamedFunction) return@mapNotNull null - val label = declaration.nameIdentifier?.getLabel() ?: return@mapNotNull null - label to declaration - }.toMap() - - fun functionByLabel(label: JKElementInfoLabel): KtNamedFunction? = - labelToFunction[label] - -} - -internal class ConstraintsCollector( - private val analysisContext: AnalysisContext, - private val converterContext: NewJ2kConverterContext?, - printConstraints: Boolean -) { - private val boundTypeStorage = BoundTypeStorage(analysisContext, printConstraints) - private val constraintBuilder = ConstraintBuilder(boundTypeStorage) - private val labelToFunctionTypeVariableMapper = LabelToFunctionTypeVariableMapper(analysisContext) - - private val PsiElement.elementInfo: List? - get() = getLabel()?.let { label -> - converterContext?.elementsInfoStorage?.getInfoForLabel(label) - } - - private inline val KtExpression.boundType - get() = boundTypeStorage.boundTypeFor(this) - - - internal fun collectConstraints(analysisScope: AnalysisScope): List { - analysisScope.forEach { element -> - element.forEachDescendantOfType { expression -> - collectConstraintsForExpression(expression) - } - } - return constraintBuilder.getConstraints() - } - - private fun collectConstraintsForExpression(expression: KtExpression) = with(constraintBuilder) { - when { - expression is KtQualifiedExpression -> { - expression.receiverExpression.addEqualsNullabilityConstraint(Nullability.NOT_NULL, ConstraintCameFrom.USED_AS_RECEIVER) - } - - expression is KtBinaryExpressionWithTypeRHS && KtPsiUtil.isUnsafeCast(expression) -> { - expression.right?.typeElement?.let { analysisContext.typeElementToTypeVariable[it] }?.also { typeVariable -> - expression.left.addSubtypeNullabilityConstraint(typeVariable, ConstraintCameFrom.ASSIGNMENT_TARGET) - } - } - - expression is KtBinaryExpression && expression.asAssignment() != null -> { - expression.right?.addSubtypeNullabilityConstraint(expression.left ?: return, ConstraintCameFrom.ASSIGNMENT_TARGET) - } - - expression is KtBinaryExpression && expression.isComaprationWithNull() -> { - val comparedExpression = - if (expression.left.isNullExpression()) expression.right - else expression.left - comparedExpression?.addEqualsNullabilityConstraint(Nullability.NULLABLE, ConstraintCameFrom.COMPARED_WITH_NULL) - } - - expression is KtBinaryExpression -> { - expression.left?.addEqualsNullabilityConstraint(Nullability.NOT_NULL, ConstraintCameFrom.USED_AS_RECEIVER) - expression.right?.addEqualsNullabilityConstraint(Nullability.NOT_NULL, ConstraintCameFrom.USED_AS_RECEIVER) - } - - expression is KtProperty -> { - analysisContext.declarationToTypeVariable[expression]?.also { typeVariable -> - expression.initializer?.addSubtypeNullabilityConstraint( - typeVariable, - ConstraintCameFrom.INITIALIZER - ) - } - } - - expression is KtParameter -> { - analysisContext.declarationToTypeVariable[expression]?.also { typeVariable -> - expression.defaultValue?.addSubtypeNullabilityConstraint( - typeVariable, - ConstraintCameFrom.INITIALIZER - ) - } - } - - expression is KtIfExpression -> { - expression.condition?.addEqualsNullabilityConstraint(Nullability.NOT_NULL, ConstraintCameFrom.INITIALIZER) - } - - expression is KtWhileExpression -> { - expression.condition?.addEqualsNullabilityConstraint(Nullability.NOT_NULL, ConstraintCameFrom.INITIALIZER) - } - - expression is KtCallExpression -> { - collectConstraintsForCallExpression( - expression, - expression.parent?.safeAs()?.receiverExpression - ) - } - - expression is KtReturnExpression -> { - val targetTypeVariable = expression.getTargetFunction(expression.analyze())?.let { function -> - analysisContext.declarationToTypeVariable[function] - } - if (targetTypeVariable != null) { - expression.returnedExpression?.addSubtypeNullabilityConstraint( - targetTypeVariable, - ConstraintCameFrom.ASSIGNMENT_TARGET - ) - } - } - - expression is KtNamedFunction -> { - collectSuperDeclarationConstraintsForFunction(expression) - } - - expression is KtForExpression -> { - expression.loopRange?.addEqualsNullabilityConstraint(Nullability.NOT_NULL, ConstraintCameFrom.INITIALIZER) - - val loopParameterTypeVariable = - expression.loopParameter?.typeReference?.typeElement?.let { typeElement -> - analysisContext.typeElementToTypeVariable[typeElement] - } - if (loopParameterTypeVariable != null) { - val loopRangeBoundType = boundTypeStorage.boundTypeFor(expression.loopRange ?: return) - val loopRangeType = expression.loopRange?.getType(expression.analyze()) ?: return - val loopRangeItemType = loopRangeType - .constructor - .declarationDescriptor - ?.safeAs() - ?.getMemberScope(loopRangeType.arguments) - ?.getDescriptorsFiltered(DescriptorKindFilter.FUNCTIONS) { - it.asString() == "iterator" - }?.filterIsInstance() - ?.firstOrNull { it.valueParameters.isEmpty() } - ?.original - ?.returnType - ?: return - val boundType = boundTypeStorage.boundTypeForType( - loopRangeItemType, - loopRangeBoundType, - emptyMap() - ) ?: return - loopParameterTypeVariable.addEqualsNullabilityConstraint( - boundType.typeParameters.firstOrNull()?.boundType ?: return, - ConstraintCameFrom.ASSIGNMENT_TARGET - ) - } - } - } - Unit - } - - - private fun SuperFunctionInfo.superFunctionBoundType( - originalFunctionDescriptor: FunctionDescriptor - ): BoundType? = - when (this) { - is ExternalSuperFunctionInfo -> { - val containingSuperClassBoundType = - descriptor.containingDeclaration.safeAs()?.let { klass -> - GenericBoundType( - DescriptorClassReference(klass), - emptyList(),//TODO, - isNull = false - ) - } - originalFunctionDescriptor.returnType?.let { type -> - boundTypeStorage.boundTypeForType(type, containingSuperClassBoundType, emptyMap()/*TODO*/) - } - } - is InternalSuperFunctionInfo -> { - labelToFunctionTypeVariableMapper.functionByLabel(label)?.let { function -> - analysisContext.declarationToTypeVariable[function]?.let { TypeVariableBoundType(it) } - } - } - } - - private fun SuperFunctionInfo.superFunctionParameterBoundType(parameterIndex: Int): BoundType? { - return when (this) { - is ExternalSuperFunctionInfo -> { - val containingSuperClassBoundType = - descriptor.containingDeclaration.safeAs()?.let { klass -> - GenericBoundType( - DescriptorClassReference(klass), - emptyList(),//TODO, - isNull = false - ) - } - val parameter = descriptor.valueParameters.getOrNull(parameterIndex) ?: return null - boundTypeStorage.boundTypeForType(parameter.type, containingSuperClassBoundType, emptyMap()/*TODO*/) - } - is InternalSuperFunctionInfo -> { - val function = labelToFunctionTypeVariableMapper.functionByLabel(label) ?: return null - val parameter = function.valueParameters.getOrNull(parameterIndex) ?: return null - analysisContext.declarationToTypeVariable[parameter]?.let { TypeVariableBoundType(it) } - } - } - } - - - private fun collectSuperDeclarationConstraintsForFunction(function: KtNamedFunction) = with(constraintBuilder) { - val (descriptor, superDeclarationDescriptors) = - function.nameIdentifier?.elementInfo?.firstIsInstanceOrNull() ?: return@with - - for (superDeclarationInfo in superDeclarationDescriptors) { - val superFunctionBoundType = superDeclarationInfo.superFunctionBoundType(descriptor) ?: continue - - analysisContext.declarationToTypeVariable[function]?.addEqualsNullabilityConstraint( - superFunctionBoundType, - ConstraintCameFrom.SUPER_DECLARATION - ) - - for (parameterIndex in function.valueParameters.indices) { - val parameterTypeVariable = - function.valueParameters[parameterIndex].let { analysisContext.declarationToTypeVariable[it] } ?: return - val superParameterBoundType = superDeclarationInfo.superFunctionParameterBoundType(parameterIndex) ?: return - parameterTypeVariable.addEqualsNullabilityConstraint(superParameterBoundType, ConstraintCameFrom.SUPER_DECLARATION) - } - } - } - - - private fun collectConstraintsForCallExpression(callExpression: KtCallExpression, receiver: KtExpression?) = with(constraintBuilder) { - val receiverBoundType = receiver?.boundType - val descriptor = callExpression.resolveToCall()?.candidateDescriptor?.original?.safeAs() ?: return - val function = descriptor.findPsi()?.safeAs() - - fun parameterBoundTypeIndex(index: Int): BoundType? = - function?.valueParameters?.let { parameters -> - val parameter = - if (index <= parameters.lastIndex) parameters[index] - else parameters.lastOrNull()?.takeIf { parameter -> - parameter.isVarArg - } - val typeVariable = parameter?.let { analysisContext.declarationToTypeVariable[it] } - typeVariable?.let { - TypeVariableBoundType(it) - } - } ?: run { - if (index < descriptor.valueParameters.lastIndex - || index == descriptor.valueParameters.lastIndex && descriptor.valueParameters.lastOrNull()?.isVararg == false - ) descriptor.valueParameters[index].type - else { - descriptor.valueParameters.lastOrNull()?.takeIf { parameter -> - parameter.isVararg && KotlinBuiltIns.isArray(parameter.type) - }?.let { parameter -> - parameter.type.arguments.singleOrNull()?.type - } - } - }?.let { type -> - boundTypeStorage - .boundTypeForType(type, receiverBoundType, callExpression.typeArgumentsDescriptors(descriptor).orEmpty()) - } - - - for (argumentIndex in callExpression.valueArguments.indices) { - val valueArgument = callExpression.valueArguments[argumentIndex] - val argument = valueArgument.getArgumentExpression() ?: continue - - if (valueArgument.isSpread) { - argument.addEqualsNullabilityConstraint(Nullability.NOT_NULL, ConstraintCameFrom.USED_AS_RECEIVER) - } - - argument.addSubtypeNullabilityConstraint( - parameterBoundTypeIndex(argumentIndex) ?: continue, - ConstraintCameFrom.PARAMETER_PASSED - ) - } - } - - private fun KtCallExpression.typeArgumentsDescriptors(descriptor: CallableDescriptor): Map? { - return descriptor.typeParameters.zip(typeArguments) { typeParameter, typeArgument -> - val typeVariable = - analysisContext.typeElementToTypeVariable[typeArgument.typeReference?.typeElement ?: return null] - ?: return null - typeParameter to typeVariable - }.toMap() - } -} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/context.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/context.kt deleted file mode 100644 index fb56b32bb0e..00000000000 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/context.kt +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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.nullabilityAnalysis - -import com.intellij.openapi.editor.RangeMarker -import com.intellij.openapi.util.TextRange -import com.intellij.psi.PsiComment -import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.nj2k.JKElementInfoLabel -import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext -import org.jetbrains.kotlin.nj2k.asLabel -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType -import org.jetbrains.kotlin.psi.psiUtil.elementsInRange -import org.jetbrains.kotlin.resolve.calls.callUtil.getType -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.utils.addToStdlib.safeAs - -internal class ContextCreator(private val getNullability: (KtTypeElement) -> Nullability) { - - private fun KtCallableDeclaration.typeElement(): KtTypeElement? = - typeReference?.typeElement - - private fun KtElement.asTypeVariableOwner(): TypeVariableOwner? { - return when (this) { - is KtParameter -> typeElement()?.asTypeVariable()?.let { ParameterTarget(this, it) } - is KtProperty -> typeElement()?.asTypeVariable()?.let { PropertyTarget(this, it) } - is KtNamedFunction -> typeElement()?.asTypeVariable()?.let { FunctionTarget(this, it) } - is KtLambdaExpression -> { - val context = analyze() - val returnType = getType(context)?.arguments?.lastOrNull()?.type ?: return null - val typeVariable = returnType.asTypeVariable() ?: return null - LambdaTarget(functionLiteral, typeVariable) - } - - is KtBinaryExpressionWithTypeRHS -> right?.typeElement - ?.takeIf { KtPsiUtil.isUnsafeCast(this) } - ?.asTypeVariable() - ?.let { TypeCastTarget(this, it) } - - is KtCallExpression -> - if (typeArguments.isNotEmpty()) - FunctionCallTypeArgumentTarget( - this, - typeArguments.map { it.typeReference?.typeElement?.asTypeVariable() ?: return null } - ) - else null - else -> null - } - } - - fun createContext(analysisScope: AnalysisScope): AnalysisContext { - val typeVariableOwners = analysisScope.flatMap { - it.collectDescendantsOfType().mapNotNull { ktElement -> - ktElement.asTypeVariableOwner() - } - } - - val typeElementsToTypeVariables = - typeVariableOwners.flatMap { - it.innerTypeVariables() + it.allTypeVariables - }.filter { it.typeElement != null } - .associateBy { it.typeElement!! } - - val declarationToTypeVariable = typeVariableOwners.asSequence() - .mapNotNull { owner -> - if (owner is DeclarationTypeVariableOwner) - owner.target to owner.typeVariable - else null - }.toMap() - return AnalysisContext(typeVariableOwners, typeElementsToTypeVariables, declarationToTypeVariable) - } - - private fun KtTypeElement.asTypeVariable(): TypeVariable { - val nullability = getNullability(this) - val classReference: ClassReference = classReference() - val typeParameters: List = - typeArgumentsAsTypes.mapIndexed { index, typeRef -> - typeRef?.typeElement?.asTypeVariable()?.let { typeVariable -> - TypeVariableTypeParameterWithTypeParameter( - typeVariable, - classReference.typeParametersVariance(index) - ) - } ?: TypeVariableStartProjectionTypeParameter - - } - return TypeVariable(this, classReference, typeParameters, nullability) - } - - private fun KotlinType.asTypeVariable(): TypeVariable? { - val classReference = constructor - .declarationDescriptor - ?.safeAs() - ?.let { DescriptorClassReference(it) } - ?: return null - val typeParameters = - arguments.zip(constructor.parameters) { argument, parameter -> - TypeVariableTypeParameterWithTypeParameter( - argument.type.asTypeVariable() ?: return null, - parameter.variance - ) - } - return TypeVariable(null, classReference, typeParameters, Nullability.UNKNOWN) - } -} - - -fun nullabilityByUndefinedNullabilityComment(typeElement: KtTypeElement, context: NewJ2kConverterContext): Nullability { - val hasUndefinedNullabilityLabel = - typeElement.parent?.safeAs()?.hasUndefinedNullabilityLabel(context) ?: false - return when { - hasUndefinedNullabilityLabel -> Nullability.UNKNOWN - typeElement is KtNullableType -> Nullability.NULLABLE - else -> Nullability.NOT_NULL - } -} - - -fun PsiElement.getLabel(): JKElementInfoLabel? = - prevSibling?.safeAs()?.text?.asLabel() - ?: parent?.safeAs()?.getLabel() - -private fun KtTypeReference.hasUndefinedNullabilityLabel(context: NewJ2kConverterContext) = - getLabel()?.let { label -> - context.elementsInfoStorage.getInfoForLabel(label).orEmpty().contains(org.jetbrains.kotlin.nj2k.UnknownNullability) - } ?: false - -fun prepareTypeElementByMakingAllTypesNullableConsideringNullabilityComment(typeElement: KtTypeElement, context: NewJ2kConverterContext) { - val hasUndefinedNullabilityLabel = - typeElement.parent?.safeAs()?.hasUndefinedNullabilityLabel(context) ?: false - - if (hasUndefinedNullabilityLabel) { - typeElement.changeNullability(toNullable = true) - } -} - -fun prepareTypeElementByMakingAllTypesNullable(typeElement: KtTypeElement) { - typeElement.changeNullability(toNullable = true) -} - - -internal data class AnalysisContext( - val typeVariableOwners: List, - val typeElementToTypeVariable: Map, - val declarationToTypeVariable: Map -) - -data class AnalysisScope(val elements: List) : Iterable by elements { - constructor(vararg elements: KtElement) : this(elements.toList()) - constructor(file: KtFile, rangeMarker: RangeMarker?) : - this(rangeMarker?.let { marker -> - file.elementsInRange(TextRange(marker.startOffset, marker.endOffset)) - } ?: listOf(file)) -} diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/nullabilityAnalysis.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/nullabilityAnalysis.kt deleted file mode 100644 index a6516a04304..00000000000 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/nullabilityAnalysis.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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.nullabilityAnalysis - -import com.intellij.openapi.application.runWriteAction -import com.intellij.openapi.command.CommandProcessor -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiComment -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiElementVisitor -import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext -import org.jetbrains.kotlin.nj2k.asLabel -import org.jetbrains.kotlin.nj2k.parentOfType -import org.jetbrains.kotlin.nj2k.postProcessing.resolve -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType -import org.jetbrains.kotlin.psi.psiUtil.isAncestor -import org.jetbrains.kotlin.utils.addToStdlib.safeAs - - -internal fun TypeVariable.changeNullability(toNullable: Boolean) { - typeElement?.changeNullability(toNullable) -} - -internal fun KtTypeElement.changeNullability(toNullable: Boolean) { - val factory = KtPsiFactory(this) - if (this is KtNullableType && !toNullable) { - replace(factory.createType(innerType?.text ?: return).typeElement ?: return) - } - if (this !is KtNullableType && toNullable) { - replace(factory.createType("$text?").typeElement ?: return) - } -} - - -internal fun AnalysisContext.fixTypeVariablesNullability() { - if (typeElementToTypeVariable.isEmpty()) return - - val deepComparator = Comparator { o1, o2 -> - if (o1.typeElement == null || o2.typeElement == null) return@Comparator -1 - if (o1.typeElement.isAncestor(o2.typeElement)) 1 else -1 - } - for (typeVariableOwner in typeVariableOwners) { - for (typeVariable in (typeVariableOwner.innerTypeVariables() + typeVariableOwner.allTypeVariables).sortedWith(deepComparator)) { - when (typeVariable.nullability) { - Nullability.NOT_NULL -> typeVariable.changeNullability(toNullable = false) - Nullability.NULLABLE -> typeVariable.changeNullability(toNullable = true) - Nullability.UNKNOWN -> { - if (typeVariableOwner is FunctionCallTypeArgumentTarget) { - typeVariable.changeNullability(toNullable = false) - } else { - typeVariable.changeNullability(toNullable = true) - } - } - } - } - } -} - -internal fun KtTypeElement.classReference(): ClassReference { - val target = when (this) { - is KtNullableType -> innerType?.safeAs() - is KtUserType -> this - else -> null - }?.referenceExpression?.resolve() - return when (target) { - is KtClassOrObject -> KtClassReference(target) - is PsiClass -> JavaClassReference(target) - is KtTypeAlias -> target.getTypeReference()?.typeElement?.classReference() - is KtTypeParameter -> TypeParameterClassReference(target) - else -> null - } ?: UnknownClassReference(text) -} - -class NullabilityAnalysisFacade( - private val conversionContext: NewJ2kConverterContext?, - private val getTypeElementNullability: (KtTypeElement) -> Nullability, - private val prepareTypeElement: (KtTypeElement) -> Unit, - private val debugPrint: Boolean -) { - fun fixNullability(analysisScope: AnalysisScope) { - CommandProcessor.getInstance().runUndoTransparentAction { - runWriteAction { - analysisScope.prepareTypeElements(prepareTypeElement) - val context = ContextCreator(getTypeElementNullability).createContext(analysisScope) - if (debugPrint) { - with(Printer(context)) { - analysisScope.forEach { it.addTypeVariablesNames() } - } - } - - val constraints = ConstraintsCollector(context, conversionContext, debugPrint).collectConstraints(analysisScope) - Solver(context, debugPrint).solveConstraints(constraints) - context.fixTypeVariablesNullability() - analysisScope.clearUndefinedLabels() - } - } - } -} - -private fun AnalysisScope.prepareTypeElements(prepareTypeElement: (KtTypeElement) -> Unit) { - val typeElements = flatMap { it.collectDescendantsOfType() } - typeElements.forEach { typeReference -> - val typeElement = typeReference.typeElement ?: return@forEach - if (typeElement.parentOfType() == null) { - prepareTypeElement(typeElement) - } - } -} - - -private fun AnalysisScope.clearUndefinedLabels() { - val comments = mutableListOf() - forEach { element -> - element.accept(object : PsiElementVisitor() { - override fun visitElement(element: PsiElement) { - element.acceptChildren(this) - } - - override fun visitComment(comment: PsiComment) { - if (comment.text.asLabel() != null) { - comments += comment - } - } - }) - } - comments.forEach { it.delete() } -} - - diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/printing.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/printing.kt deleted file mode 100644 index 2e592082093..00000000000 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/printing.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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.nullabilityAnalysis - -import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.KtTypeElement -import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType - -internal class Printer(private val analysisContext: AnalysisContext) { - private val namer = Namer(analysisContext) - - internal val TypeVariable.name: String - get() = namer.name(this) - - private fun ClassReference.asString() = - when (this) { - is KtClassReference -> klass.name - is JavaClassReference -> klass.name - is DescriptorClassReference -> descriptor.name.toString() - is TypeParameterClassReference -> typeParameter.name - is LiteralClassReference -> "LITERAL" - is UnknownClassReference -> text - else -> error(this::class.toString()) - } - - fun BoundType.asString(): String = - buildString { - if (this@asString is TypeVariableBoundType) { - append(this@asString.typeVariable.name) - append("@") - } - append(classReference.asString()) - if (typeParameters.isNotEmpty()) { - typeParameters.joinTo(this, ", ", "<", ">") { it.boundType.asString() } - } - } - - private fun Constraint.asString() = - when (this) { - is EqualConstraint -> "${leftBound.asString()} := ${rightBound.asString()}" - is SubtypeConstraint -> "${lowerBound.asString()} <: ${upperBound.asString()}" - else -> error("Unknown constraint ${this::class.qualifiedName}") - } + ", because of '$cameFrom'" - - - private fun ConstraintBound.asString(): String = - when (this) { - is LiteralBound -> nullability.toString() - is TypeVariableBound -> typeVariable.name - else -> error("Unknown constraint bound ${this::class.qualifiedName}") - } - - - internal fun PsiElement.addTypeVariablesNames() { - val factory = KtPsiFactory(this) - for (typeElement in collectDescendantsOfType()) { - val typeVariableName = this@Printer.analysisContext.typeElementToTypeVariable[typeElement]?.name ?: continue - val comment = factory.createComment("/*$typeVariableName@*/") - typeElement.parent.addBefore(comment, typeElement) - } - } - - internal fun List.listConstrains() = - joinToString(separator = "\n") { it.asString() } -} - - -private class Namer(analysisContext: AnalysisContext) { - val names = run { - val typeVariables = - analysisContext.typeVariableOwners.flatMap { owner -> - owner.allTypeVariables.flatMap { it.innerTypeVariables() + it } - } - typeVariables.mapIndexed { index, typeVariable -> - typeVariable to "T$index" - }.toMap() - } - - fun name(typeVariable: TypeVariable): String = - names.getValue(typeVariable) -} \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/utils.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/utils.kt deleted file mode 100644 index c265fb81a97..00000000000 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/nullabilityAnalysis/utils.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.nullabilityAnalysis - -import com.intellij.psi.tree.IElementType -import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.calls.callUtil.getType -import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo -import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue -import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactoryImpl -import org.jetbrains.kotlin.resolve.jvm.checkers.mustNotBeNull -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.isNullable -import org.jetbrains.kotlin.util.javaslang.getOrNull - -internal fun KtExpression.deepestReceiver(): KtExpression = - generateSequence(this) { - if (it is KtQualifiedExpression) it.receiverExpression else null - }.last() - -internal fun KtExpression.isNullable(): Boolean = - getType(analyze())?.isNullable() != false - -internal fun KtExpression.getForcedNullability(): Nullability? { - val bindingContext = analyze() - val type = this.getType(bindingContext) ?: return null - if (!type.isNullable()) return Nullability.NOT_NULL - - //TODO better way of getting DataFlowValueFactoryImpl - val dataFlowValue = DataFlowValueFactoryImpl(LanguageVersionSettingsImpl.DEFAULT) - .createDataFlowValue( - this, - type, - bindingContext, - getResolutionFacade().moduleDescriptor - ) - val dataFlowInfo = analyze()[BindingContext.EXPRESSION_TYPE_INFO, this]?.dataFlowInfo ?: return null - return when { - dataFlowInfo.completeNullabilityInfo.get(dataFlowValue)?.getOrNull() == - org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL -> Nullability.NOT_NULL - type.isExternallyAnnotatedNotNull(dataFlowInfo, dataFlowValue) -> Nullability.NOT_NULL - else -> null - } -} - - -private fun KotlinType.isExternallyAnnotatedNotNull(dataFlowInfo: DataFlowInfo, dataFlowValue: DataFlowValue): Boolean = - mustNotBeNull()?.isFromJava == true && dataFlowInfo.getStableNullability(dataFlowValue).canBeNull() - -private fun IElementType.isEqualsToken() = - this == KtTokens.EQEQ - || this == KtTokens.EXCLEQ - || this == KtTokens.EQEQEQ - || this == KtTokens.EXCLEQEQEQ - -fun KtBinaryExpression.isComaprationWithNull() = - operationToken.isEqualsToken() && - (left.isNullExpression() || right.isNullExpression()) - -fun KtExpression.isLiteral() = - this is KtStringTemplateExpression - || this is KtLiteralStringTemplateEntry - || this is KtConstantExpression - || isNullExpression() \ No newline at end of file diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/J2kPostProcessor.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/J2kPostProcessor.kt index 361c9e60579..caf4122e223 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/J2kPostProcessor.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/J2kPostProcessor.kt @@ -161,6 +161,7 @@ private val removeRedundantElementsProcessingGroup = runSingleTime = true, processings = listOf( RemoveExplicitTypeArgumentsProcessing(), + RemoveJavaStreamsCollectCallTypeArgumentsProcessing(), generalInspectionBasedProcessing(RedundantCompanionReferenceInspection()), generalInspectionBasedProcessing(ExplicitThisInspection()), intentionBasedProcessing(RemoveEmptyClassBodyIntention()) @@ -234,7 +235,10 @@ private val cleaningUpDiagnosticBasedPostProcessingGroup = private val processings: List = listOf( NamedPostProcessingGroup( "Inferring declarations nullability", - listOf(nullabilityProcessing) + listOf( + nullabilityProcessing, + clearUndefinedLabelsProcessing + ) ), NamedPostProcessingGroup( "Formatting code", diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/inspeҁtionLikeProcessings.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/inspeҁtionLikeProcessings.kt index 30913599ad6..4bf99661b4e 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/inspeҁtionLikeProcessings.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/inspeҁtionLikeProcessings.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.nj2k.postProcessing.processings import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod import com.intellij.psi.search.searches.ReferencesSearch import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor @@ -41,7 +42,6 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.isNullable -import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -57,8 +57,7 @@ class RemoveExplicitPropertyTypeProcessing : ApplicabilityBasedInspectionLikePro val withoutExpectedType = initializer.analyzeInContext(initializer.getResolutionScope()).getType(initializer) ?: return false val descriptor = element.resolveToDescriptorIfAny() as? CallableDescriptor ?: return false - return if (element.isVar) withoutExpectedType == descriptor.returnType - else withoutExpectedType.makeNotNullable() == descriptor.returnType?.makeNotNullable() + return withoutExpectedType == descriptor.returnType } override fun apply(element: KtProperty) { @@ -101,6 +100,26 @@ class RemoveExplicitTypeArgumentsProcessing : ApplicabilityBasedInspectionLikePr } } +// the types arguments for Stream.collect calls cannot be explicitly specified in Kotlin +// but we need them in nullability inference, so we remove it here +class RemoveJavaStreamsCollectCallTypeArgumentsProcessing : + ApplicabilityBasedInspectionLikeProcessing(KtCallExpression::class) { + override fun isApplicableTo(element: KtCallExpression, settings: ConverterSettings?): Boolean { + if (element.typeArgumentList == null) return false + val resolved = element.calleeExpression?.mainReference?.resolve() as? PsiMethod ?: return false + return resolved.getKotlinFqName()?.asString() == COLLECT_FQ_NAME + } + + override fun apply(element: KtCallExpression) { + element.typeArgumentList?.delete() + } + + companion object { + private const val COLLECT_FQ_NAME = "java.util.stream.Stream.collect" + } +} + + class RemoveRedundantOverrideVisibilityProcessing : InspectionLikeProcessing { override val writeActionNeeded = true diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/processings.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/processings.kt index c7f46b37ad2..d3b894d5278 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/processings.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/postProcessing/processings/processings.kt @@ -6,23 +6,33 @@ package org.jetbrains.kotlin.nj2k.postProcessing.processings import com.intellij.codeInsight.actions.OptimizeImportsProcessor +import com.intellij.psi.PsiComment +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiElementVisitor import com.intellij.psi.codeStyle.CodeStyleManager +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.util.range import org.jetbrains.kotlin.idea.formatter.commitAndUnblockDocument -import org.jetbrains.kotlin.nj2k.nullabilityAnalysis.AnalysisScope -import org.jetbrains.kotlin.nj2k.nullabilityAnalysis.NullabilityAnalysisFacade -import org.jetbrains.kotlin.nj2k.nullabilityAnalysis.nullabilityByUndefinedNullabilityComment -import org.jetbrains.kotlin.nj2k.nullabilityAnalysis.prepareTypeElementByMakingAllTypesNullableConsideringNullabilityComment +import org.jetbrains.kotlin.nj2k.asLabel +import org.jetbrains.kotlin.nj2k.inference.common.BoundTypeCalculatorImpl +import org.jetbrains.kotlin.nj2k.inference.common.ByInfoSuperFunctionsProvider +import org.jetbrains.kotlin.nj2k.inference.common.ConstraintsCollectorAggregator +import org.jetbrains.kotlin.nj2k.inference.common.InferenceFacade +import org.jetbrains.kotlin.nj2k.inference.common.collectors.CallExpressionConstraintCollector +import org.jetbrains.kotlin.nj2k.inference.common.collectors.CommonConstraintsCollector +import org.jetbrains.kotlin.nj2k.inference.common.collectors.FunctionConstraintsCollector +import org.jetbrains.kotlin.nj2k.inference.nullability.NullabilityBoundTypeEnhancer +import org.jetbrains.kotlin.nj2k.inference.nullability.NullabilityConstraintsCollector +import org.jetbrains.kotlin.nj2k.inference.nullability.NullabilityContextCollector +import org.jetbrains.kotlin.nj2k.inference.nullability.NullabilityStateUpdater import org.jetbrains.kotlin.nj2k.postProcessing.postProcessing -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtImportDirective -import org.jetbrains.kotlin.psi.KtImportList -import org.jetbrains.kotlin.psi.KtPackageDirective +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.elementsInRange val formatCodeProcessing = postProcessing { file, rangeMarker, _ -> + file.commitAndUnblockDocument() val codeStyleManager = CodeStyleManager.getInstance(file.project) if (rangeMarker != null) { if (rangeMarker.isValid) { @@ -35,14 +45,49 @@ val formatCodeProcessing = val nullabilityProcessing = postProcessing { file, rangeMarker, converterContext -> - NullabilityAnalysisFacade( - converterContext, - getTypeElementNullability = { nullabilityByUndefinedNullabilityComment(it, converterContext) }, - prepareTypeElement = { prepareTypeElementByMakingAllTypesNullableConsideringNullabilityComment(it, converterContext) }, - debugPrint = false - ).fixNullability(AnalysisScope(file, rangeMarker)) + val resolutionFacade = file.getResolutionFacade() + val inferenceFacade = InferenceFacade( + NullabilityContextCollector(resolutionFacade, converterContext), + ConstraintsCollectorAggregator( + resolutionFacade, + listOf( + CommonConstraintsCollector(), + CallExpressionConstraintCollector(), + FunctionConstraintsCollector(ByInfoSuperFunctionsProvider(resolutionFacade, converterContext)), + NullabilityConstraintsCollector() + ) + ), + BoundTypeCalculatorImpl(resolutionFacade, NullabilityBoundTypeEnhancer(resolutionFacade)), + NullabilityStateUpdater() + ) + val elements = if (rangeMarker != null) { + file.elementsInRange(rangeMarker.range ?: return@postProcessing).filterIsInstance() + } else listOf(file) + + inferenceFacade.runOn(elements) } +val clearUndefinedLabelsProcessing = + postProcessing { file, _, _ -> + file.clearUndefinedLabels() + } + +private fun KtFile.clearUndefinedLabels() { + val comments = mutableListOf() + accept(object : PsiElementVisitor() { + override fun visitElement(element: PsiElement) { + element.acceptChildren(this) + } + + override fun visitComment(comment: PsiComment) { + if (comment.text.asLabel() != null) { + comments += comment + } + } + }) + comments.forEach { it.delete() } +} + val shortenReferencesProcessing = postProcessing { file, rangeMarker, _ -> if (rangeMarker != null) { diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt index c55ca251ecc..f9b210e405c 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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 @@ -725,7 +714,9 @@ class NewCodeBuilder(context: NewJ2kConverterContext) { override fun visitArrayAccessExpressionRaw(arrayAccessExpression: JKArrayAccessExpression) { arrayAccessExpression.expression.accept(this) - printer.par(ParenthesisKind.SQUARE) { arrayAccessExpression.indexExpression.accept(this) } + printer.print(".get(") + arrayAccessExpression.indexExpression.accept(this) + printer.print(")") } override fun visitPackageAccessExpressionRaw(packageAccessExpression: JKPackageAccessExpression) { @@ -946,9 +937,7 @@ private class JKPrinter( fun renderType(type: JKType, owner: JKTreeElement?) { if (type is JKNoTypeImpl) return - elementInfoStorage.getOrCreateInfoForElement(type).let { - print(it.render()) - } + print(elementInfoStorage.getOrCreateInfoForElement(type).render()) when (type) { is JKClassType -> { renderClassSymbol(type.classReference, owner) @@ -975,6 +964,12 @@ private class JKPrinter( if (type.nullability == Nullability.Nullable) { printWithNoIndent("?") } + // we print undefined types as nullable because we need smartcast work in nullability inference in post-processing + if (type.nullability == Nullability.Default + && owner?.safeAs()?.functionalType?.type != type + ) { + printWithNoIndent("?") + } } fun renderClassSymbol(classSymbol: JKClassSymbol, owner: JKTreeElement?) { diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/AddElementsInfoConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/AddElementsInfoConversion.kt index 704ef496954..b94a2c4fadc 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/AddElementsInfoConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/AddElementsInfoConversion.kt @@ -36,14 +36,14 @@ class AddElementsInfoConversion(private val context: NewJ2kConverterContext) : R val psiMethod = function.psi() ?: return val descriptor = psiMethod.getJavaMethodDescriptor() ?: return val superDescriptorsInfo = - descriptor.overriddenDescriptors.map { superDescriptor -> - val psi = superDescriptor.findPsi() ?: return@map ExternalSuperFunctionInfo(descriptor) - when (val symbol = context.symbolProvider.symbolsByPsi[psi]) { + descriptor.overriddenDescriptors.mapNotNull { superDescriptor -> + val superPsi = superDescriptor.original.findPsi() + when (val symbol = context.symbolProvider.symbolsByPsi[superPsi]) { is JKUniverseMethodSymbol -> InternalSuperFunctionInfo( context.elementsInfoStorage.getOrCreateInfoForElement(symbol.target) ) - else -> ExternalSuperFunctionInfo(descriptor) + else -> ExternalSuperFunctionInfo(superDescriptor) } } context.elementsInfoStorage.addEntry(function, FunctionInfo(descriptor, superDescriptorsInfo)) diff --git a/nj2k/testData/copyPaste/SeveralMethodsSample.expected.kt b/nj2k/testData/copyPaste/SeveralMethodsSample.expected.kt index 36175151726..bc04269bcd9 100644 --- a/nj2k/testData/copyPaste/SeveralMethodsSample.expected.kt +++ b/nj2k/testData/copyPaste/SeveralMethodsSample.expected.kt @@ -1,7 +1,7 @@ class A { fun someOther() = false - private fun formatElement(element: PsiElement): String { + private fun formatElement(element: PsiElement): String? { var element: PsiElement = element element = JetPsiUtil.ascendIfPropertyAccessor(element) if (element is JetNamedFunction || element is JetProperty) { @@ -28,9 +28,9 @@ class A { } fun getSelected(): ArrayList { - val result: ArrayList = ArrayList() + val result: ArrayList = ArrayList() for (i in 0 until myChecked.length) { - if (myChecked[i]) { + if (myChecked.get(i)) { result.add(myOverridingMethods.get(i)) } } diff --git a/nj2k/testData/copyPastePlainText/AsExpression.expected.kt b/nj2k/testData/copyPastePlainText/AsExpression.expected.kt index 65fc3b8bb1b..ca296477dba 100644 --- a/nj2k/testData/copyPastePlainText/AsExpression.expected.kt +++ b/nj2k/testData/copyPastePlainText/AsExpression.expected.kt @@ -3,5 +3,5 @@ import java.util.ArrayList fun foo() { - bar(ArrayList()) + bar(ArrayList()) } \ No newline at end of file diff --git a/nj2k/testData/copyPastePlainText/AsExpressionBody.expected.kt b/nj2k/testData/copyPastePlainText/AsExpressionBody.expected.kt index fa4a1e80add..a435466eaaf 100644 --- a/nj2k/testData/copyPastePlainText/AsExpressionBody.expected.kt +++ b/nj2k/testData/copyPastePlainText/AsExpressionBody.expected.kt @@ -2,4 +2,4 @@ import java.util.ArrayList -fun foo() = ArrayList() \ No newline at end of file +fun foo() = ArrayList() \ No newline at end of file diff --git a/nj2k/testData/copyPastePlainText/ImportFromTarget.expected.kt b/nj2k/testData/copyPastePlainText/ImportFromTarget.expected.kt index 85ca628988d..feb7716f9e7 100644 --- a/nj2k/testData/copyPastePlainText/ImportFromTarget.expected.kt +++ b/nj2k/testData/copyPastePlainText/ImportFromTarget.expected.kt @@ -4,7 +4,7 @@ import java.util.UUID class ExampleClass { - override fun toString(): String { + override fun toString(): String? { return UUID.randomUUID().toString() } } \ No newline at end of file diff --git a/nj2k/testData/copyPastePlainText/ImportResolve.expected.kt b/nj2k/testData/copyPastePlainText/ImportResolve.expected.kt index a2c721bf84f..16c9ec163a2 100644 --- a/nj2k/testData/copyPastePlainText/ImportResolve.expected.kt +++ b/nj2k/testData/copyPastePlainText/ImportResolve.expected.kt @@ -9,7 +9,7 @@ import java.util.HashMap class Target { var listOfPlatformType: List = ArrayList() - var unresolved: UnresolvedInterface? = UnresolvedImplementation() // Should not add import + var unresolved: UnresolvedInterface = UnresolvedImplementation() // Should not add import var hashMapOfNotImported: Map = HashMap() @@ -18,11 +18,11 @@ class Target { internal fun acceptJavaClass(tbi: ToBeImportedJava?) {} - var ambiguousKotlin: IAmbiguousKotlin? = AmbiguousKotlin() // Should not add import in case of 2 declarations in Kotlin + var ambiguousKotlin: IAmbiguousKotlin = AmbiguousKotlin() // Should not add import in case of 2 declarations in Kotlin - var ambiguous: IAmbiguous? = Ambiguous() // Should not add import in case of ambiguous declarations in Kotlin and in Java + var ambiguous: IAmbiguous = Ambiguous() // Should not add import in case of ambiguous declarations in Kotlin and in Java - var ambiguousJava: IAmbiguousJava? = AmbiguousJava() // Should not add import in case of 2 declarations in Java + var ambiguousJava: IAmbiguousJava = AmbiguousJava() // Should not add import in case of 2 declarations in Java internal fun workWithStatics() { diff --git a/nj2k/testData/copyPastePlainText/KT13529_1.expected.kt b/nj2k/testData/copyPastePlainText/KT13529_1.expected.kt index a042bb2ee7d..06692dc2f82 100644 --- a/nj2k/testData/copyPastePlainText/KT13529_1.expected.kt +++ b/nj2k/testData/copyPastePlainText/KT13529_1.expected.kt @@ -3,5 +3,5 @@ import java.util.ArrayList fun foo() { - bar(/*comment*/ArrayList()) + bar(/*comment*/ArrayList()) } \ No newline at end of file diff --git a/nj2k/testData/copyPastePlainText/PostProcessing.expected.kt b/nj2k/testData/copyPastePlainText/PostProcessing.expected.kt index 1898bdff7a4..2b3d6cad61e 100644 --- a/nj2k/testData/copyPastePlainText/PostProcessing.expected.kt +++ b/nj2k/testData/copyPastePlainText/PostProcessing.expected.kt @@ -6,7 +6,7 @@ import java.util.ArrayList class JavaClass { internal fun foo(file: File?, target: List?) { - val list = ArrayList() + val list = ArrayList() if (file != null) { list.add(file.name) } diff --git a/nj2k/testData/inference/common/arrayAssignment.kt b/nj2k/testData/inference/common/arrayAssignment.kt new file mode 100644 index 00000000000..bec87171e12 --- /dev/null +++ b/nj2k/testData/inference/common/arrayAssignment.kt @@ -0,0 +1,8 @@ +fun test() { + val x: /*T2@*/Array = arrayOf()/*Array*/ + val y: /*T4@*/Array = x/*T2@Array*/ +} + +//T1 := T0 due to 'INITIALIZER' +//T3 := T1 due to 'INITIALIZER' +//T2 <: T4 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/arrayOfArrays.kt b/nj2k/testData/inference/common/arrayOfArrays.kt new file mode 100644 index 00000000000..b63f05a9192 --- /dev/null +++ b/nj2k/testData/inference/common/arrayOfArrays.kt @@ -0,0 +1,16 @@ +class Test { + fun foo() { + val x: /*T5@*/Array> = + Array>(1/*LIT*/, { + arrayOf(2/*LIT*/)/*Array*/ + }/*Function0>*/ + )/*Array>*/ + } +} + +//LOWER <: T0 due to 'PARAMETER' +//T7 := T0 due to 'RETURN' +//T1 := T7 due to 'PARAMETER' +//T6 <: T2 due to 'PARAMETER' +//T3 := T1 due to 'INITIALIZER' +//T4 := T2 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/callFunctionWithTypeParamFromOuterScope.kt b/nj2k/testData/inference/common/callFunctionWithTypeParamFromOuterScope.kt new file mode 100644 index 00000000000..171730d4330 --- /dev/null +++ b/nj2k/testData/inference/common/callFunctionWithTypeParamFromOuterScope.kt @@ -0,0 +1,12 @@ +class X { + fun x(): /*T1@*/List { + TODO() + } + + fun y() { + val a: /*T3@*/List = x()/*T1@List*/ + } +} + +//T0 <: T2 due to 'INITIALIZER' +//T1 <: T3 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/callWithTypeParams.kt b/nj2k/testData/inference/common/callWithTypeParams.kt new file mode 100644 index 00000000000..187c847fd8d --- /dev/null +++ b/nj2k/testData/inference/common/callWithTypeParams.kt @@ -0,0 +1,9 @@ +fun test() { + foo( + listOf()/*List*/ + ) +} + +fun foo (x: /*T3@*/List) {} + +//T0 <: T1 due to 'PARAMETER' diff --git a/nj2k/testData/inference/common/constructorCall.kt b/nj2k/testData/inference/common/constructorCall.kt new file mode 100644 index 00000000000..5e1d1785551 --- /dev/null +++ b/nj2k/testData/inference/common/constructorCall.kt @@ -0,0 +1,15 @@ +fun test() { + val x: /*T2@*/X = X(10/*LIT*/)/*X*/ + val x: /*T5@*/X = X(10/*LIT*/, 20/*LIT*/)/*X*/ +} + +class X(x: /*T6@*/T) { + constructor(x: /*T7@*/T, y: /*T8@*/Int): this(x/*T7@T*/) +} + +//LOWER <: T0 due to 'PARAMETER' +//T1 := T0 due to 'INITIALIZER' +//LOWER <: T3 due to 'PARAMETER' +//LOWER <: T8 due to 'PARAMETER' +//T4 := T3 due to 'INITIALIZER' +//T7 <: T6 due to 'PARAMETER' diff --git a/nj2k/testData/inference/common/delegationConstructorCall.kt b/nj2k/testData/inference/common/delegationConstructorCall.kt new file mode 100644 index 00000000000..7243c86a890 --- /dev/null +++ b/nj2k/testData/inference/common/delegationConstructorCall.kt @@ -0,0 +1,5 @@ +class X(x: /*T0@*/T) { + constructor(x: /*T1@*/T, y: /*T2@*/Int): this(x/*T1@T*/) +} + +//T1 <: T0 due to 'PARAMETER' diff --git a/nj2k/testData/inference/common/elementOfArrayAssignment.kt b/nj2k/testData/inference/common/elementOfArrayAssignment.kt new file mode 100644 index 00000000000..e68010f1b3c --- /dev/null +++ b/nj2k/testData/inference/common/elementOfArrayAssignment.kt @@ -0,0 +1,14 @@ +fun test() { + val x: /*T4@*/Array> = arrayOf>()/*Array>*/ + val y: /*T6@*/Array = x/*T4@Array>*/.get(0/*LIT*/)/*T3@Array*/ + val z: /*T7@*/Int = y/*T6@Array*/.get(0/*LIT*/)/*T5@Int*/ +} + +//T2 := T0 due to 'INITIALIZER' +//T3 := T1 due to 'INITIALIZER' +//T2 := T2 due to 'RECEIVER_PARAMETER' +//T3 := T3 due to 'RECEIVER_PARAMETER' +//T5 := T2 due to 'INITIALIZER' +//T3 <: T6 due to 'INITIALIZER' +//T5 := T5 due to 'RECEIVER_PARAMETER' +//T5 <: T7 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/elementOfListAssignment.kt b/nj2k/testData/inference/common/elementOfListAssignment.kt new file mode 100644 index 00000000000..477ce26313c --- /dev/null +++ b/nj2k/testData/inference/common/elementOfListAssignment.kt @@ -0,0 +1,14 @@ +fun test() { + val x: /*T4@*/List> = listOf>()/*List>*/ + val y: /*T6@*/List = x/*T4@List>*/.get(0/*LIT*/)/*T3@List*/ + val z: /*T7@*/Int = y/*T6@List*/.get(0/*LIT*/)/*T5@Int*/ +} + +//T0 <: T2 due to 'INITIALIZER' +//T1 <: T3 due to 'INITIALIZER' +//T2 <: T2 due to 'RECEIVER_PARAMETER' +//T3 <: T3 due to 'RECEIVER_PARAMETER' +//T2 <: T5 due to 'INITIALIZER' +//T3 <: T6 due to 'INITIALIZER' +//T5 <: T5 due to 'RECEIVER_PARAMETER' +//T5 <: T7 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/forLoop.kt b/nj2k/testData/inference/common/forLoop.kt new file mode 100644 index 00000000000..dad6ea0a54c --- /dev/null +++ b/nj2k/testData/inference/common/forLoop.kt @@ -0,0 +1,10 @@ +fun test() { + val x: /*T2@*/List = listOf()/*List*/ + for (y: /*T3@*/String in x/*T2@List*/) { + val z: /*T4@*/String = x/*T2@List*/ + } +} + +//T0 <: T1 due to 'INITIALIZER' +//T2 <: T4 due to 'INITIALIZER' +//T3 <: T1 due to 'ASSIGNMENT' diff --git a/nj2k/testData/inference/common/functionCall.kt b/nj2k/testData/inference/common/functionCall.kt new file mode 100644 index 00000000000..db63621f646 --- /dev/null +++ b/nj2k/testData/inference/common/functionCall.kt @@ -0,0 +1,10 @@ +fun test() { + val x: /*T1@*/List = nya()/*T3@List*/ +} + +fun nya(): /*T3@*/List { + TODO() +} + +//T2 <: T0 due to 'INITIALIZER' +//T3 <: T1 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/functionReturn.kt b/nj2k/testData/inference/common/functionReturn.kt new file mode 100644 index 00000000000..43c150abc26 --- /dev/null +++ b/nj2k/testData/inference/common/functionReturn.kt @@ -0,0 +1,7 @@ +fun f(): /*T1@*/Int { + val x: /*T0@*/Int = 42/*LIT*/ + return x/*T0@Int*/ +} + +//LOWER <: T0 due to 'INITIALIZER' +//T0 <: T1 due to 'RETURN' diff --git a/nj2k/testData/inference/common/functionWithTypeParamCall.kt b/nj2k/testData/inference/common/functionWithTypeParamCall.kt new file mode 100644 index 00000000000..a78703d7d09 --- /dev/null +++ b/nj2k/testData/inference/common/functionWithTypeParamCall.kt @@ -0,0 +1,11 @@ +fun test() { + val x: /*T3@*/Map = nya()/*T6@Map*/ +} + +fun nya(): /*T6@*/Map { + TODO() +} + +//T1 := T0 due to 'INITIALIZER' +//T5 <: T2 due to 'INITIALIZER' +//T6 <: T3 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/lambdaAsParameter.kt b/nj2k/testData/inference/common/lambdaAsParameter.kt new file mode 100644 index 00000000000..243971fce7c --- /dev/null +++ b/nj2k/testData/inference/common/lambdaAsParameter.kt @@ -0,0 +1,11 @@ +fun test() { + nya({ a: /*T0@*/Int, b: /*T1@*/Boolean -> ""/*LIT*/ }/*Function2*/) +} + +fun nya(x: /*T6@*/Function2) { +} + +//LOWER <: T7 due to 'RETURN' +//T2 <: T0 due to 'PARAMETER' +//T4 <: T1 due to 'PARAMETER' +//T7 <: T5 due to 'PARAMETER' diff --git a/nj2k/testData/inference/common/lambdaAssign.kt b/nj2k/testData/inference/common/lambdaAssign.kt new file mode 100644 index 00000000000..bab1a4add34 --- /dev/null +++ b/nj2k/testData/inference/common/lambdaAssign.kt @@ -0,0 +1,8 @@ +fun test() { + val x: /*T5@*/Function2 = { a: /*T0@*/Int, b: /*T1@*/String -> true/*LIT*/ }/*Function2*/ +} + +//LOWER <: T6 due to 'RETURN' +//T2 <: T0 due to 'INITIALIZER' +//T3 <: T1 due to 'INITIALIZER' +//T6 <: T4 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/lambdaImplicitReturn.kt b/nj2k/testData/inference/common/lambdaImplicitReturn.kt new file mode 100644 index 00000000000..b24e915a1ee --- /dev/null +++ b/nj2k/testData/inference/common/lambdaImplicitReturn.kt @@ -0,0 +1,12 @@ +fun test() { + val x: /*T6@*/Function2 = { a: /*T0@*/Int, b: /*T1@*/String -> + val a: /*T2@*/Boolean = true/*LIT*/ + a/*T2@Boolean*/ + }/*Function2*/ +} + +//LOWER <: T2 due to 'INITIALIZER' +//T2 <: T7 due to 'RETURN' +//T3 <: T0 due to 'INITIALIZER' +//T4 <: T1 due to 'INITIALIZER' +//T7 <: T5 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/lambdaReturn.kt b/nj2k/testData/inference/common/lambdaReturn.kt new file mode 100644 index 00000000000..3894c729512 --- /dev/null +++ b/nj2k/testData/inference/common/lambdaReturn.kt @@ -0,0 +1,21 @@ +class Test { + fun foo1(r: /*T2@*/Function1) {} + fun foo() { + foo1 { i: /*T3@*/Int -> + val str: /*T4@*/String = ""/*LIT*/ + val str2: /*T5@*/String = ""/*LIT*/ + + if (i > 1) { + return@foo1 str/*T4@String*/ + } + str2/*T5@String*/ + }/*Function1*/ + } +} + +//LOWER <: T4 due to 'INITIALIZER' +//LOWER <: T5 due to 'INITIALIZER' +//T4 <: T6 due to 'RETURN' +//T5 <: T6 due to 'RETURN' +//T0 <: T3 due to 'PARAMETER' +//T6 <: T1 due to 'PARAMETER' diff --git a/nj2k/testData/inference/common/listAssignment.kt b/nj2k/testData/inference/common/listAssignment.kt new file mode 100644 index 00000000000..e0b24f5075b --- /dev/null +++ b/nj2k/testData/inference/common/listAssignment.kt @@ -0,0 +1,8 @@ +fun test() { + val x: /*T2@*/List = listOf()/*List*/ + val y: /*T4@*/List = x/*T2@List*/ +} + +//T0 <: T1 due to 'INITIALIZER' +//T1 <: T3 due to 'INITIALIZER' +//T2 <: T4 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/listGenerator.kt b/nj2k/testData/inference/common/listGenerator.kt new file mode 100644 index 00000000000..0504c39b6a9 --- /dev/null +++ b/nj2k/testData/inference/common/listGenerator.kt @@ -0,0 +1,7 @@ +fun test() { + val x: /*T2@*/List = List(10/*LIT*/, { 10/*LIT*/ }/*Function0*/)/*List*/ +} + +//LOWER <: T3 due to 'RETURN' +//T3 <: T0 due to 'PARAMETER' +//T0 <: T1 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/listOfLists.kt b/nj2k/testData/inference/common/listOfLists.kt new file mode 100644 index 00000000000..aba56277c2f --- /dev/null +++ b/nj2k/testData/inference/common/listOfLists.kt @@ -0,0 +1,12 @@ +fun foo() { + val a: /*T5@*/List> = listOf>( + listOf( + 1/*LIT*/ + )/*List*/ + )/*List>*/ +} + +//LOWER <: T0 due to 'PARAMETER' +//T0 <: T1 due to 'PARAMETER' +//T1 <: T3 due to 'INITIALIZER' +//T2 <: T4 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/listOfListsGenerator.kt b/nj2k/testData/inference/common/listOfListsGenerator.kt new file mode 100644 index 00000000000..945344c793f --- /dev/null +++ b/nj2k/testData/inference/common/listOfListsGenerator.kt @@ -0,0 +1,16 @@ +fun test() { + val x: /*T5@*/List> = List>(13/*LIT*/, { + List(7/*LIT*/, { + 666/*LIT*/ + }/*Function0*/)/*List*/ + }/*Function0>*/ + )/*List>*/ +} + +//LOWER <: T6 due to 'RETURN' +//T6 <: T0 due to 'PARAMETER' +//T0 <: T8 due to 'RETURN' +//T8 <: T1 due to 'PARAMETER' +//T7 <: T2 due to 'PARAMETER' +//T1 <: T3 due to 'INITIALIZER' +//T2 <: T4 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/memberCall.kt b/nj2k/testData/inference/common/memberCall.kt new file mode 100644 index 00000000000..64581317c09 --- /dev/null +++ b/nj2k/testData/inference/common/memberCall.kt @@ -0,0 +1,16 @@ +fun test() { + val x: /*T2@*/X = X()/*X*/ + val y: /*T5@*/Map = x/*T2@X*/.foo()/*T8@Map*/ +} + +class X { + fun foo(): /*T8@*/Map { + TODO() + } +} + +//T1 := T0 due to 'INITIALIZER' +//T1 := T1 due to 'RECEIVER_PARAMETER' +//T3 := T1 due to 'INITIALIZER' +//T7 <: T4 due to 'INITIALIZER' +//T8 <: T5 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/returnFromLambda.kt b/nj2k/testData/inference/common/returnFromLambda.kt new file mode 100644 index 00000000000..20dd24f4c8d --- /dev/null +++ b/nj2k/testData/inference/common/returnFromLambda.kt @@ -0,0 +1,16 @@ +fun test() { + val x: /*T6@*/Function2 = l@{ a: /*T0@*/Int, b: /*T1@*/String -> + val y: /*T2@*/Boolean = true/*LIT*/ + if (a == 3) { + return@l y/*T2@Boolean*/ + } + true/*LIT*/ + }/*Function2*//*Function2*/ +} + +//LOWER <: T2 due to 'INITIALIZER' +//T2 <: T7 due to 'RETURN' +//LOWER <: T7 due to 'RETURN' +//T3 <: T0 due to 'INITIALIZER' +//T4 <: T1 due to 'INITIALIZER' +//T7 <: T5 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/sequenceOfCalls.kt b/nj2k/testData/inference/common/sequenceOfCalls.kt new file mode 100644 index 00000000000..553d182088a --- /dev/null +++ b/nj2k/testData/inference/common/sequenceOfCalls.kt @@ -0,0 +1,9 @@ +fun a(lst: /*T1@*/List) { + val newList: /*T5@*/List = lst/*T1@List*/ + .asSequence()/*Sequence*/ + .toList()/*List*/ +} + +//T0 <: T2 due to 'RECEIVER_PARAMETER' +//T2 <: T3 due to 'RECEIVER_PARAMETER' +//T3 <: T4 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/sequenceOfCallsWIthLambda.kt b/nj2k/testData/inference/common/sequenceOfCallsWIthLambda.kt new file mode 100644 index 00000000000..235b5cad9dd --- /dev/null +++ b/nj2k/testData/inference/common/sequenceOfCallsWIthLambda.kt @@ -0,0 +1,14 @@ +fun a(lst: /*T1@*/List) { + val newList: /*T8@*/List = lst/*T1@List*/ + .asSequence()/*Sequence*/ + .map({ x: /*T3@*/String -> 1/*LIT*/ }/*Function1*/)/*Sequence*/ + .toList()/*List*/ +} + +//T0 <: T2 due to 'RECEIVER_PARAMETER' +//LOWER <: T9 due to 'RETURN' +//T2 <: T4 due to 'RECEIVER_PARAMETER' +//T4 <: T3 due to 'PARAMETER' +//T9 <: T5 due to 'PARAMETER' +//T5 <: T6 due to 'RECEIVER_PARAMETER' +//T6 <: T7 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/simpleAssignment.kt b/nj2k/testData/inference/common/simpleAssignment.kt new file mode 100644 index 00000000000..52fa7663de8 --- /dev/null +++ b/nj2k/testData/inference/common/simpleAssignment.kt @@ -0,0 +1,9 @@ +fun test() { + val x: /*T0@*/Int = 10/*LIT*/ + val y: /*T1@*/Int = x/*T0@Int*/ + val z: /*T2@*/Int = y/*T1@Int*/ +} + +//LOWER <: T0 due to 'INITIALIZER' +//T0 <: T1 due to 'INITIALIZER' +//T1 <: T2 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/common/superCall.kt b/nj2k/testData/inference/common/superCall.kt new file mode 100644 index 00000000000..eafd4b538f0 --- /dev/null +++ b/nj2k/testData/inference/common/superCall.kt @@ -0,0 +1,14 @@ +open class A { + open fun foo(x: /*T0@*/T, y: /*T2@*/List) { + } +} + +class B : A() { + override fun foo(x: /*T3@*/Int, y: /*T5@*/List) { + super/*LIT*/.foo(x/*T3@Int*/, y/*T5@List*/) + } +} + +//T3 := T6 due to 'SUPER_DECLARATION' +//T4 := T6 due to 'SUPER_DECLARATION' +//T2 := T5 due to 'SUPER_DECLARATION' diff --git a/nj2k/testData/inference/common/superConstuctorCall.kt b/nj2k/testData/inference/common/superConstuctorCall.kt new file mode 100644 index 00000000000..d4aa7f76039 --- /dev/null +++ b/nj2k/testData/inference/common/superConstuctorCall.kt @@ -0,0 +1,7 @@ +open class X(x: /*T0@*/T) { +} + +class Y(x: /*T1@*/T) : X(x/*T1@T*/) { +} + +//T1 <: T0 due to 'PARAMETER' diff --git a/nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParameters.kt b/nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParameters.kt new file mode 100644 index 00000000000..5e86be40781 --- /dev/null +++ b/nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParameters.kt @@ -0,0 +1,15 @@ +interface A { + fun foo(): /*T3@*/List> +} + + +open class B : A { + override fun foo(): /*T7@*/List> { + TODO() + } +} + +//T4 := T8 due to 'SUPER_DECLARATION' +//T5 := T9 due to 'SUPER_DECLARATION' +//T2 := T6 due to 'SUPER_DECLARATION' +//T3 := T7 due to 'SUPER_DECLARATION' diff --git a/nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParametersSubstitution.kt b/nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParametersSubstitution.kt new file mode 100644 index 00000000000..b1cee92dfdc --- /dev/null +++ b/nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParametersSubstitution.kt @@ -0,0 +1,13 @@ +open class A { + open fun foo(): /*T0@*/T { + TODO() + } +} + +class B : A() { + override fun foo(): /*T1@*/Int { + TODO() + } +} + +//T1 := T2 due to 'SUPER_DECLARATION' diff --git a/nj2k/testData/inference/common/superFunctionType.kt b/nj2k/testData/inference/common/superFunctionType.kt new file mode 100644 index 00000000000..ed7d7be3b12 --- /dev/null +++ b/nj2k/testData/inference/common/superFunctionType.kt @@ -0,0 +1,13 @@ +open class A { + open fun foo(): /*T0@*/String { + TODO() + } +} + +class B : A() { + override fun foo(): /*T1@*/String { + TODO() + } +} + +//T0 := T1 due to 'SUPER_DECLARATION' diff --git a/nj2k/testData/inference/common/typeParamsBounds.kt b/nj2k/testData/inference/common/typeParamsBounds.kt new file mode 100644 index 00000000000..bdd83f130c7 --- /dev/null +++ b/nj2k/testData/inference/common/typeParamsBounds.kt @@ -0,0 +1,5 @@ +class Test { + fun x() { + } +} + diff --git a/nj2k/testData/inference/common/varargsInCall.kt b/nj2k/testData/inference/common/varargsInCall.kt new file mode 100644 index 00000000000..bfd0038684c --- /dev/null +++ b/nj2k/testData/inference/common/varargsInCall.kt @@ -0,0 +1,14 @@ +fun test() { + val x: /*T0@*/String = ""/*LIT*/ + val y: /*T1@*/String = ""/*LIT*/ + val z: /*T2@*/String = ""/*LIT*/ + val e: /*T5@*/List = listOf(x/*T0@String*/, y/*T1@String*/, z/*T2@String*/)/*List*/ +} + +//LOWER <: T0 due to 'INITIALIZER' +//LOWER <: T1 due to 'INITIALIZER' +//LOWER <: T2 due to 'INITIALIZER' +//T0 <: T3 due to 'PARAMETER' +//T1 <: T3 due to 'PARAMETER' +//T2 <: T3 due to 'PARAMETER' +//T3 <: T4 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/arrayOfArraysOfNull.kt b/nj2k/testData/inference/nullability/arrayOfArraysOfNull.kt new file mode 100644 index 00000000000..aeafeb6499d --- /dev/null +++ b/nj2k/testData/inference/nullability/arrayOfArraysOfNull.kt @@ -0,0 +1,10 @@ +class Test { + fun foo() { + val ss = Array>(5/*LIT*/, { arrayOfNulls(5/*LIT*/)/*Array!!L*/ }/*Function0>!!L*/) + } +} + +//T4 := UPPER due to 'RETURN' +//LOWER <: T3 due to 'RETURN' +//T1 := T4 due to 'PARAMETER' +//T3 <: T2 due to 'PARAMETER' diff --git a/nj2k/testData/inference/nullability/arrayOfNulls.kt b/nj2k/testData/inference/nullability/arrayOfNulls.kt new file mode 100644 index 00000000000..6cdaa3c406d --- /dev/null +++ b/nj2k/testData/inference/nullability/arrayOfNulls.kt @@ -0,0 +1,6 @@ +fun test() { + val x: /*T2@*/Array = arrayOfNulls(10/*LIT*/)/*Array!!L*/ +} + +//T1 := UPPER due to 'INITIALIZER' +//LOWER <: T2 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/binaryExpressionOperand.kt b/nj2k/testData/inference/nullability/binaryExpressionOperand.kt new file mode 100644 index 00000000000..3641de584c0 --- /dev/null +++ b/nj2k/testData/inference/nullability/binaryExpressionOperand.kt @@ -0,0 +1,7 @@ +fun test() { + val x: /*T0@*/Int = 10/*LIT*/ + x/*T0@Int*/ > 0/*LIT*/ +} + +//LOWER <: T0 due to 'INITIALIZER' +//T0 := LOWER due to 'USE_AS_RECEIVER' diff --git a/nj2k/testData/inference/nullability/callExternallyAnnotatedJavaFunction.kt b/nj2k/testData/inference/nullability/callExternallyAnnotatedJavaFunction.kt new file mode 100644 index 00000000000..b7484f11f83 --- /dev/null +++ b/nj2k/testData/inference/nullability/callExternallyAnnotatedJavaFunction.kt @@ -0,0 +1,11 @@ +import java.util.Arrays.asList + +fun test() { + val x: /*T2@*/List = asList(1/*LIT*/)/*MutableList!!L*/ + val i: /*T3@*/Int = Integer/*LIT*/.valueOf(""/*LIT*/)/*Int!!L*/ +} + +//LOWER <: T0 due to 'PARAMETER' +//T1 := T0 due to 'INITIALIZER' +//LOWER <: T2 due to 'INITIALIZER' +//LOWER <: T3 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/classTypeParameters.kt b/nj2k/testData/inference/nullability/classTypeParameters.kt new file mode 100644 index 00000000000..831d5abfaba --- /dev/null +++ b/nj2k/testData/inference/nullability/classTypeParameters.kt @@ -0,0 +1,27 @@ +open class A { + open fun foo(): /*T3@*/Map>? { + TODO() + } + + open fun bar(): /*T4@*/T? { + return null/*NULL!!U*/ + } +} + +class B : A() { + override fun foo(): /*T8@*/Map>? { + return null/*NULL!!U*/ + } + override fun bar(): /*T9@*/Int { + return 42/*LIT*/ + } +} + +//UPPER <: T4 due to 'RETURN' +//UPPER <: T8 due to 'RETURN' +//T5 := T10 due to 'SUPER_DECLARATION' +//T6 := T10 due to 'SUPER_DECLARATION' +//T2 := T7 due to 'SUPER_DECLARATION' +//T3 := T8 due to 'SUPER_DECLARATION' +//LOWER <: T9 due to 'RETURN' +//T9 := T10 due to 'SUPER_DECLARATION' diff --git a/nj2k/testData/inference/nullability/compareWithNull.kt b/nj2k/testData/inference/nullability/compareWithNull.kt new file mode 100644 index 00000000000..1de976aec98 --- /dev/null +++ b/nj2k/testData/inference/nullability/compareWithNull.kt @@ -0,0 +1,19 @@ +fun a(): /*T0@*/Int? { + return 42/*LIT*/ +} + +val b: /*T1@*/Int? = 2/*LIT*/ + +fun c(p: /*T2@*/Int?) { + if (p/*T2@Int*/ == null/*LIT*/); +} + +fun check() { + if (a()/*T0@Int*/ == null/*LIT*/ || b/*T1@Int*/ == null/*LIT*//*LIT*/); +} + +//LOWER <: T0 due to 'RETURN' +//LOWER <: T1 due to 'INITIALIZER' +//T2 := UPPER due to 'COMPARE_WITH_NULL' +//T0 := UPPER due to 'COMPARE_WITH_NULL' +//T1 := UPPER due to 'COMPARE_WITH_NULL' diff --git a/nj2k/testData/inference/nullability/forcedNullability.kt b/nj2k/testData/inference/nullability/forcedNullability.kt new file mode 100644 index 00000000000..4cd230b1111 --- /dev/null +++ b/nj2k/testData/inference/nullability/forcedNullability.kt @@ -0,0 +1,9 @@ +fun b(m: /*T2@*/Map): /*T3@*/String? { + return m/*T2@Map*/.get(42/*LIT*/)/*T1@String!!U*/ +} + +//T0 := T0 due to 'RECEIVER_PARAMETER' +//T1 <: T1 due to 'RECEIVER_PARAMETER' +//LOWER <: T0 due to 'PARAMETER' +//T2 := LOWER due to 'USE_AS_RECEIVER' +//UPPER <: T3 due to 'RETURN' diff --git a/nj2k/testData/inference/nullability/functionTypeParameterNullability.kt b/nj2k/testData/inference/nullability/functionTypeParameterNullability.kt new file mode 100644 index 00000000000..159dde46e1d --- /dev/null +++ b/nj2k/testData/inference/nullability/functionTypeParameterNullability.kt @@ -0,0 +1,20 @@ +fun foo(x: /*T0@*/T, y: /*T2@*/List, z: /*T4@*/List, a: /*T5@*/S) {} + +fun bar() { + val lst: /*T8@*/List = listOf(null/*NULL!!U*/)/*List!!L*/ + val lst2: /*T11@*/List = listOf(1/*LIT*/)/*List!!L*/ + foo(null/*NULL!!U*/, lst/*T8@List*/, lst2/*T11@List*/, "nya"/*LIT*/) +} + +//UPPER <: T6 due to 'PARAMETER' +//T6 <: T7 due to 'INITIALIZER' +//LOWER <: T8 due to 'INITIALIZER' +//LOWER <: T9 due to 'PARAMETER' +//T9 <: T10 due to 'INITIALIZER' +//LOWER <: T11 due to 'INITIALIZER' +//UPPER <: T12 due to 'PARAMETER' +//T7 <: T13 due to 'PARAMETER' +//T8 <: T2 due to 'PARAMETER' +//T10 <: T14 due to 'PARAMETER' +//T11 <: T4 due to 'PARAMETER' +//LOWER <: T15 due to 'PARAMETER' diff --git a/nj2k/testData/inference/nullability/functions.kt b/nj2k/testData/inference/nullability/functions.kt new file mode 100644 index 00000000000..f1735e78c4e --- /dev/null +++ b/nj2k/testData/inference/nullability/functions.kt @@ -0,0 +1,40 @@ +fun notNullParameters(f: /*T3@*/Function2) {} +fun nullableParameter(f: /*T7@*/Function2) {} +fun nullableReturnType(f: /*T11@*/Function2) {} + + +fun test() { + notNullParameters({ i: /*T12@*/Int, j: /*T13@*/Int -> + if (i/*T12@Int*/ < 10/*LIT*//*LIT*/ && j/*T13@Int*/ > 0/*LIT*//*LIT*//*LIT*/) ""/*LIT*/ else ""/*LIT*/ + }/*Function2!!L*/) + + nullableParameter({ i: /*T14@*/Int?, j: /*T15@*/Int -> + if (i/*T14@Int*/ == null/*LIT*/) ""/*LIT*/ else ""/*LIT*/ + }/*Function2!!L*/) + + nullableReturnType({ i: /*T16@*/Int, j: /*T17@*/Int -> + if (i/*T16@Int*/ < 10/*LIT*//*LIT*/) return@nullableReturnType null/*NULL!!U*/ + return@nullableReturnType "nya"/*LIT*/ + }/*Function2!!L*/) +} + +//T12 := LOWER due to 'USE_AS_RECEIVER' +//T13 := LOWER due to 'USE_AS_RECEIVER' +//LOWER <: T18 due to 'RETURN' +//T0 <: T12 due to 'PARAMETER' +//T1 <: T13 due to 'PARAMETER' +//T18 <: T2 due to 'PARAMETER' +//LOWER <: T3 due to 'PARAMETER' +//T14 := UPPER due to 'COMPARE_WITH_NULL' +//LOWER <: T19 due to 'RETURN' +//T4 <: T14 due to 'PARAMETER' +//T5 <: T15 due to 'PARAMETER' +//T19 <: T6 due to 'PARAMETER' +//LOWER <: T7 due to 'PARAMETER' +//T16 := LOWER due to 'USE_AS_RECEIVER' +//UPPER <: T20 due to 'RETURN' +//LOWER <: T20 due to 'RETURN' +//T8 <: T16 due to 'PARAMETER' +//T9 <: T17 due to 'PARAMETER' +//T20 <: T10 due to 'PARAMETER' +//LOWER <: T11 due to 'PARAMETER' diff --git a/nj2k/testData/inference/nullability/ifCondition.kt b/nj2k/testData/inference/nullability/ifCondition.kt new file mode 100644 index 00000000000..e427717623c --- /dev/null +++ b/nj2k/testData/inference/nullability/ifCondition.kt @@ -0,0 +1,5 @@ +fun test(a: /*T0@*/Boolean) { + if (a/*T0@Boolean*/) {} +} + +//T0 := LOWER due to 'USE_AS_RECEIVER' diff --git a/nj2k/testData/inference/nullability/javaStream.kt b/nj2k/testData/inference/nullability/javaStream.kt new file mode 100644 index 00000000000..c4cacc4ccdc --- /dev/null +++ b/nj2k/testData/inference/nullability/javaStream.kt @@ -0,0 +1,25 @@ +// RUNTIME_WITH_FULL_JDK + +import java.util.stream.Collector +import java.util.stream.Collectors +import java.util.stream.Stream + +fun test(list: /*T1@*/List) { + val x: /*T9@*/List = list/*T1@List*/.stream()/*Stream!!L*/ + .map({ x: /*T2@*/String -> x/*T2@String*/ + ""/*LIT*//*LIT*/ }/*Function1!!L*/)/*Stream*/ + .collect, /*T7@*/Any?>(Collectors/*LIT*/.toList()/*Collector>*/)/*T6@List*/ + +} + +//T0 <: T0 due to 'RECEIVER_PARAMETER' +//T1 := LOWER due to 'USE_AS_RECEIVER' +//T2 := LOWER due to 'USE_AS_RECEIVER' +//LOWER <: T10 due to 'RETURN' +//T0 := T0 due to 'RECEIVER_PARAMETER' +//T0 <: T2 due to 'PARAMETER' +//T10 <: T3 due to 'PARAMETER' +//T3 := T3 due to 'RECEIVER_PARAMETER' +//T3 := T4 due to 'PARAMETER' +//T5 := T4 due to 'PARAMETER' +//T5 <: T8 due to 'INITIALIZER' +//T6 <: T9 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/lambdaReturnNull.kt b/nj2k/testData/inference/nullability/lambdaReturnNull.kt new file mode 100644 index 00000000000..1266ee5a484 --- /dev/null +++ b/nj2k/testData/inference/nullability/lambdaReturnNull.kt @@ -0,0 +1,23 @@ +class Test { + fun foo1(r: /*T2@*/Function1) {} + fun foo() { + foo1({ x: /*T3@*/Int -> ""/*LIT*/ }/*Function1!!L*/) + foo1({ i: /*T4@*/Int -> + if (i/*T4@Int*/ > 1/*LIT*//*LIT*/) { + return@foo1 null/*NULL!!U*/ + } + ""/*LIT*/ + }/*Function1!!L*/) + } +} + +//LOWER <: T5 due to 'RETURN' +//T0 <: T3 due to 'PARAMETER' +//T5 <: T1 due to 'PARAMETER' +//LOWER <: T2 due to 'PARAMETER' +//T4 := LOWER due to 'USE_AS_RECEIVER' +//UPPER <: T6 due to 'RETURN' +//LOWER <: T6 due to 'RETURN' +//T0 <: T4 due to 'PARAMETER' +//T6 <: T1 due to 'PARAMETER' +//LOWER <: T2 due to 'PARAMETER' diff --git a/nj2k/testData/inference/nullability/listOfWithNullLiteral.kt b/nj2k/testData/inference/nullability/listOfWithNullLiteral.kt new file mode 100644 index 00000000000..819ee6271c2 --- /dev/null +++ b/nj2k/testData/inference/nullability/listOfWithNullLiteral.kt @@ -0,0 +1,9 @@ +fun test() { + val x: /*T2@*/List = listOf(1/*LIT*/, null/*NULL!!U*/, 3/*LIT*/)/*List!!L*/ +} + +//LOWER <: T0 due to 'PARAMETER' +//UPPER <: T0 due to 'PARAMETER' +//LOWER <: T0 due to 'PARAMETER' +//T0 <: T1 due to 'INITIALIZER' +//LOWER <: T2 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/loopIterator.kt b/nj2k/testData/inference/nullability/loopIterator.kt new file mode 100644 index 00000000000..5d9e0d7d0c1 --- /dev/null +++ b/nj2k/testData/inference/nullability/loopIterator.kt @@ -0,0 +1,8 @@ +fun test(a: /*T1@*/List) { + for (i: /*T2@*/Int in a/*T1@List*/) { + + } +} + +//T2 <: T0 due to 'ASSIGNMENT' +//T1 := LOWER due to 'USE_AS_RECEIVER' diff --git a/nj2k/testData/inference/nullability/loops.kt b/nj2k/testData/inference/nullability/loops.kt new file mode 100644 index 00000000000..bd5b7f83511 --- /dev/null +++ b/nj2k/testData/inference/nullability/loops.kt @@ -0,0 +1,31 @@ +fun bar(map: /*T2@*/HashMap, list1: /*T4@*/List, list2: /*T6@*/List) { + for (entry: /*T9@*/MutableMap.MutableEntry in map/*T2@HashMap*/.entries/*MutableSet>*/) { + val value: /*T10@*/Int = entry/*T9@MutableEntry*/.value/*T8@Int*/ + if (entry/*T9@MutableEntry*/.key/*T7@String*/ == null/*LIT*/) { + println(value/*T10@Int*/ + 1/*LIT*//*LIT*/) + } + } + + for (i: /*T11@*/Int in list1/*T4@List*/) { + i/*T11@Int*/ + 1/*LIT*/ + } + + for (i: /*T12@*/String? in list2/*T6@List*/) { + i/*T12@String*/ == null + } +} + +//T2 := LOWER due to 'USE_AS_RECEIVER' +//T9 := LOWER due to 'USE_AS_RECEIVER' +//T8 <: T10 due to 'INITIALIZER' +//T9 := LOWER due to 'USE_AS_RECEIVER' +//T7 := UPPER due to 'COMPARE_WITH_NULL' +//T10 := LOWER due to 'USE_AS_RECEIVER' +//T0 := T7 due to 'ASSIGNMENT' +//T1 := T8 due to 'ASSIGNMENT' +//T11 := LOWER due to 'USE_AS_RECEIVER' +//T11 <: T3 due to 'ASSIGNMENT' +//T4 := LOWER due to 'USE_AS_RECEIVER' +//T12 := UPPER due to 'COMPARE_WITH_NULL' +//T12 <: T5 due to 'ASSIGNMENT' +//T6 := LOWER due to 'USE_AS_RECEIVER' diff --git a/nj2k/testData/inference/nullability/notNullCallSequence.kt b/nj2k/testData/inference/nullability/notNullCallSequence.kt new file mode 100644 index 00000000000..b42c320f987 --- /dev/null +++ b/nj2k/testData/inference/nullability/notNullCallSequence.kt @@ -0,0 +1,16 @@ +// RUNTIME_WITH_FULL_JDK + +fun main() { + val list: /*T5@*/List = + listOf(""/*LIT*/, null/*NULL!!U*/)/*List!!L*/ + .map({ x: /*T1@*/String? -> x/*T1@String*/ }/*Function1!!L*/)/*List!!L*/ +} + +//LOWER <: T0 due to 'PARAMETER' +//UPPER <: T0 due to 'PARAMETER' +//T1 <: T6 due to 'RETURN' +//T0 <: T2 due to 'RECEIVER_PARAMETER' +//T2 <: T1 due to 'PARAMETER' +//T6 <: T3 due to 'PARAMETER' +//T3 <: T4 due to 'INITIALIZER' +//LOWER <: T5 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/nullAsAssignment.kt b/nj2k/testData/inference/nullability/nullAsAssignment.kt new file mode 100644 index 00000000000..29cd5793af5 --- /dev/null +++ b/nj2k/testData/inference/nullability/nullAsAssignment.kt @@ -0,0 +1,18 @@ +fun test() { + var x: /*T0@*/Int? = 1/*LIT*/ + x/*T0@Int*/ = null/*NULL!!U*/ + + var y: /*T1@*/Int? = 5/*LIT*/ + y/*T1@Int*/ = nullableFun()/*T2@Int*/ +} + +fun nullableFun(): /*T2@*/Int? { + return null/*NULL!!U*/ +} + +//LOWER <: T0 due to 'INITIALIZER' +//UPPER <: T0 due to 'ASSIGNMENT' +//T0 := UPPER due to 'COMPARE_WITH_NULL' +//LOWER <: T1 due to 'INITIALIZER' +//T2 <: T1 due to 'ASSIGNMENT' +//UPPER <: T2 due to 'RETURN' diff --git a/nj2k/testData/inference/nullability/nullAsInitializer.kt b/nj2k/testData/inference/nullability/nullAsInitializer.kt new file mode 100644 index 00000000000..5a37fa6ed46 --- /dev/null +++ b/nj2k/testData/inference/nullability/nullAsInitializer.kt @@ -0,0 +1,5 @@ +val x: /*T0@*/Int? = null/*NULL!!U*/ +fun foo(p: /*T1@*/Int? = null/*NULL!!U*/) {} + +//UPPER <: T0 due to 'INITIALIZER' +//UPPER <: T1 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/nullLiteral.kt b/nj2k/testData/inference/nullability/nullLiteral.kt new file mode 100644 index 00000000000..af3ac44013f --- /dev/null +++ b/nj2k/testData/inference/nullability/nullLiteral.kt @@ -0,0 +1,5 @@ +fun test() { + val x: /*T0@*/Int? = null/*NULL!!U*/ +} + +//UPPER <: T0 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/returnNull.kt b/nj2k/testData/inference/nullability/returnNull.kt new file mode 100644 index 00000000000..1905896f92e --- /dev/null +++ b/nj2k/testData/inference/nullability/returnNull.kt @@ -0,0 +1,5 @@ +fun nya() : /*T0@*/Int? { + return null/*NULL!!U*/ +} + +//UPPER <: T0 due to 'RETURN' diff --git a/nj2k/testData/inference/nullability/sequenceOfCallsWIthLambda.kt b/nj2k/testData/inference/nullability/sequenceOfCallsWIthLambda.kt new file mode 100644 index 00000000000..fdb89826498 --- /dev/null +++ b/nj2k/testData/inference/nullability/sequenceOfCallsWIthLambda.kt @@ -0,0 +1,16 @@ +fun a(lst: /*T1@*/List) { + val newList: /*T8@*/List = lst/*T1@List*/ + .asSequence()/*Sequence!!L*/ + .map({ x: /*T3@*/String -> 1/*LIT*/ }/*Function1!!L*/)/*Sequence!!L*/ + .toList()/*List!!L*/ +} + +//T0 <: T2 due to 'RECEIVER_PARAMETER' +//T1 := LOWER due to 'USE_AS_RECEIVER' +//LOWER <: T9 due to 'RETURN' +//T2 <: T4 due to 'RECEIVER_PARAMETER' +//T4 <: T3 due to 'PARAMETER' +//T9 <: T5 due to 'PARAMETER' +//T5 <: T6 due to 'RECEIVER_PARAMETER' +//T6 <: T7 due to 'INITIALIZER' +//LOWER <: T8 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/smartCast.kt b/nj2k/testData/inference/nullability/smartCast.kt new file mode 100644 index 00000000000..691e7eb8c8b --- /dev/null +++ b/nj2k/testData/inference/nullability/smartCast.kt @@ -0,0 +1,7 @@ +fun foo(o: /*T0@*/Int??) { + if (o/*T0@Int*/ == null/*LIT*/) return + val a: /*T1@*/Int = o/*T0@Int!!L*/ +} + +//T0 := UPPER due to 'COMPARE_WITH_NULL' +//LOWER <: T1 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/spreadExpression.kt b/nj2k/testData/inference/nullability/spreadExpression.kt new file mode 100644 index 00000000000..c75fed3dcce --- /dev/null +++ b/nj2k/testData/inference/nullability/spreadExpression.kt @@ -0,0 +1,9 @@ +import java.lang.reflect.Constructor + +fun foo(constructor: /*T1@*/Constructor, args: /*T3@*/Array) { + constructor/*T1@Constructor*/.newInstance(*args/*T3@Array*/) +} + +//T3 := LOWER due to 'USE_AS_RECEIVER' +//T0 := T0 due to 'RECEIVER_PARAMETER' +//T1 := LOWER due to 'USE_AS_RECEIVER' diff --git a/nj2k/testData/inference/nullability/superMethod.kt b/nj2k/testData/inference/nullability/superMethod.kt new file mode 100644 index 00000000000..e30be400483 --- /dev/null +++ b/nj2k/testData/inference/nullability/superMethod.kt @@ -0,0 +1,18 @@ +open class A () { + open fun foo(x: /*T0@*/Int?): /*T1@*/Int? { + if (x/*T0@Int*/ == null/*LIT*/); + return null/*NULL!!U*/ + } +} + +class B : A() { + override fun foo(x: /*T2@*/Int?): /*T3@*/Int? { + return 1/*LIT*/ + } +} + +//T0 := UPPER due to 'COMPARE_WITH_NULL' +//UPPER <: T1 due to 'RETURN' +//LOWER <: T3 due to 'RETURN' +//T1 := T3 due to 'SUPER_DECLARATION' +//T0 := T2 due to 'SUPER_DECLARATION' diff --git a/nj2k/testData/inference/nullability/typeCast.kt b/nj2k/testData/inference/nullability/typeCast.kt new file mode 100644 index 00000000000..05a004c7753 --- /dev/null +++ b/nj2k/testData/inference/nullability/typeCast.kt @@ -0,0 +1,18 @@ +fun foo() { + val cast1: /*T1@*/Int = 1/*LIT*/ as /*T0@*/Int/*T0@Int*/ + val cast2: /*T3@*/Int? = null/*NULL!!U*/ as /*T2@*/Int?/*T2@Int*/ + val cast3: /*T5@*/Float = (1/*LIT*/ as /*T4@*/Int/*T4@Int*/)/*T4@Int*/.toFloat()/*Float!!L*/ + val nya: /*T6@*/Int? = null/*NULL!!U*/ + val cast4: /*T8@*/Int? = nya/*T6@Int*/ as /*T7@*/Int?/*T7@Int*/ +} + +//LOWER <: T0 due to 'ASSIGNMENT' +//T0 <: T1 due to 'INITIALIZER' +//UPPER <: T2 due to 'ASSIGNMENT' +//T2 <: T3 due to 'INITIALIZER' +//LOWER <: T4 due to 'ASSIGNMENT' +//T4 := LOWER due to 'USE_AS_RECEIVER' +//LOWER <: T5 due to 'INITIALIZER' +//UPPER <: T6 due to 'INITIALIZER' +//T6 <: T7 due to 'ASSIGNMENT' +//T7 <: T8 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/typeParameters.kt b/nj2k/testData/inference/nullability/typeParameters.kt new file mode 100644 index 00000000000..d7e1aff147e --- /dev/null +++ b/nj2k/testData/inference/nullability/typeParameters.kt @@ -0,0 +1,20 @@ +fun foo() { + val a: /*T5@*/List> = listOf>( + listOf( + 1/*LIT*/ + )/*List!!L*/ + )/*List>!!L*/ + val b: /*T7@*/List = a/*T5@List>*/.get(0/*LIT*/)/*T4@List*/ +} + +//LOWER <: T0 due to 'PARAMETER' +//T0 <: T1 due to 'PARAMETER' +//LOWER <: T2 due to 'PARAMETER' +//T1 <: T3 due to 'INITIALIZER' +//T2 <: T4 due to 'INITIALIZER' +//LOWER <: T5 due to 'INITIALIZER' +//T3 <: T3 due to 'RECEIVER_PARAMETER' +//T4 <: T4 due to 'RECEIVER_PARAMETER' +//T5 := LOWER due to 'USE_AS_RECEIVER' +//T3 <: T6 due to 'INITIALIZER' +//T4 <: T7 due to 'INITIALIZER' diff --git a/nj2k/testData/inference/nullability/typeParametersReturnType.kt b/nj2k/testData/inference/nullability/typeParametersReturnType.kt new file mode 100644 index 00000000000..692c9878cee --- /dev/null +++ b/nj2k/testData/inference/nullability/typeParametersReturnType.kt @@ -0,0 +1,20 @@ +open class A { + open fun foo(): /*T3@*/Map> { + TODO() + } + + open fun bar(): /*T4@*/T { + TODO() + } +} + +class B : A() { + override fun foo(): /*T8@*/Map> { + TODO() + } +} + +//T5 := T9 due to 'SUPER_DECLARATION' +//T6 := T9 due to 'SUPER_DECLARATION' +//T2 := T7 due to 'SUPER_DECLARATION' +//T3 := T8 due to 'SUPER_DECLARATION' diff --git a/nj2k/testData/inference/nullability/typeParametersValueParams.kt b/nj2k/testData/inference/nullability/typeParametersValueParams.kt new file mode 100644 index 00000000000..e548d8b5fc4 --- /dev/null +++ b/nj2k/testData/inference/nullability/typeParametersValueParams.kt @@ -0,0 +1,16 @@ +open class A { + open fun foo(x: /*T1@*/List, y: /*T2@*/Boolean, z: /*T3@*/T) { + TODO() + } +} + +class B : A() { + override fun foo(x: /*T5@*/List, y: /*T6@*/Boolean, z: /*T7@*/Int) { + TODO() + } +} + +//T4 := T8 due to 'SUPER_DECLARATION' +//T1 := T5 due to 'SUPER_DECLARATION' +//T2 := T6 due to 'SUPER_DECLARATION' +//T7 := T8 due to 'SUPER_DECLARATION' diff --git a/nj2k/testData/inference/nullability/useAsReceiver.kt b/nj2k/testData/inference/nullability/useAsReceiver.kt new file mode 100644 index 00000000000..c8d89222030 --- /dev/null +++ b/nj2k/testData/inference/nullability/useAsReceiver.kt @@ -0,0 +1,9 @@ +fun test() { + val x: /*T2@*/List = listOf()/*List!!L*/ + x/*T2@List*/.get(0/*LIT*/) +} + +//T0 <: T1 due to 'INITIALIZER' +//LOWER <: T2 due to 'INITIALIZER' +//T1 <: T1 due to 'RECEIVER_PARAMETER' +//T2 := LOWER due to 'USE_AS_RECEIVER' diff --git a/nj2k/testData/inference/nullability/whileCondition.kt b/nj2k/testData/inference/nullability/whileCondition.kt new file mode 100644 index 00000000000..f7b0473a1f1 --- /dev/null +++ b/nj2k/testData/inference/nullability/whileCondition.kt @@ -0,0 +1,5 @@ +fun test(a: /*T0@*/Boolean) { + while (a/*T0@Boolean*/) {} +} + +//T0 := LOWER due to 'USE_AS_RECEIVER' diff --git a/nj2k/testData/newJ2k/arrayAccessExpression/expressionIndex.kt b/nj2k/testData/newJ2k/arrayAccessExpression/expressionIndex.kt index 7a99230c2f6..7984a5cbb2e 100644 --- a/nj2k/testData/newJ2k/arrayAccessExpression/expressionIndex.kt +++ b/nj2k/testData/newJ2k/arrayAccessExpression/expressionIndex.kt @@ -1 +1 @@ -myArray[myLibrary.calculateIndex(100)] \ No newline at end of file +myArray.get(myLibrary.calculateIndex(100)) \ No newline at end of file diff --git a/nj2k/testData/newJ2k/arrayAccessExpression/intIndex.kt b/nj2k/testData/newJ2k/arrayAccessExpression/intIndex.kt index 8a7de5e4e73..dc5ad8eb72e 100644 --- a/nj2k/testData/newJ2k/arrayAccessExpression/intIndex.kt +++ b/nj2k/testData/newJ2k/arrayAccessExpression/intIndex.kt @@ -1 +1 @@ -myArray[10] \ No newline at end of file +myArray.get(10) \ No newline at end of file diff --git a/nj2k/testData/newJ2k/arrayAccessExpression/variableIndex.kt b/nj2k/testData/newJ2k/arrayAccessExpression/variableIndex.kt index 2a40dae7f3b..11816663338 100644 --- a/nj2k/testData/newJ2k/arrayAccessExpression/variableIndex.kt +++ b/nj2k/testData/newJ2k/arrayAccessExpression/variableIndex.kt @@ -1 +1 @@ -myArray[i] \ No newline at end of file +myArray.get(i) \ No newline at end of file diff --git a/nj2k/testData/newJ2k/arrayInitializerExpression/objectArrayWithLength.kt b/nj2k/testData/newJ2k/arrayInitializerExpression/objectArrayWithLength.kt index 91ced175767..fa6abe5123e 100644 --- a/nj2k/testData/newJ2k/arrayInitializerExpression/objectArrayWithLength.kt +++ b/nj2k/testData/newJ2k/arrayInitializerExpression/objectArrayWithLength.kt @@ -1 +1 @@ -val a = arrayOfNulls(10) \ No newline at end of file +val a = arrayOfNulls(10) \ No newline at end of file diff --git a/nj2k/testData/newJ2k/arrayType/arrayInitializationStatementWithDimension.kt b/nj2k/testData/newJ2k/arrayType/arrayInitializationStatementWithDimension.kt index 1462d0c46d1..239e170a566 100644 --- a/nj2k/testData/newJ2k/arrayType/arrayInitializationStatementWithDimension.kt +++ b/nj2k/testData/newJ2k/arrayType/arrayInitializationStatementWithDimension.kt @@ -1 +1 @@ -val d2 = arrayOfNulls(5) \ No newline at end of file +val d2 = arrayOfNulls(5) \ No newline at end of file diff --git a/nj2k/testData/newJ2k/arrayType/arrayInitializationStatementWithDimension3d.kt b/nj2k/testData/newJ2k/arrayType/arrayInitializationStatementWithDimension3d.kt index c92369fb13f..d8bb9a288d4 100644 --- a/nj2k/testData/newJ2k/arrayType/arrayInitializationStatementWithDimension3d.kt +++ b/nj2k/testData/newJ2k/arrayType/arrayInitializationStatementWithDimension3d.kt @@ -1 +1 @@ -val d3 = Array>(5) { arrayOfNulls(5) } \ No newline at end of file +val d3 = Array(5) { arrayOfNulls(5) } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/arrayType/d2StringEmptyArray.kt b/nj2k/testData/newJ2k/arrayType/d2StringEmptyArray.kt index 0db72939b6b..71e6c99097d 100644 --- a/nj2k/testData/newJ2k/arrayType/d2StringEmptyArray.kt +++ b/nj2k/testData/newJ2k/arrayType/d2StringEmptyArray.kt @@ -1 +1 @@ -val ss = Array>(5) { arrayOfNulls(5) } \ No newline at end of file +val ss = Array(5) { arrayOfNulls(5) } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/arrayType/d3StringEmptyArray.kt b/nj2k/testData/newJ2k/arrayType/d3StringEmptyArray.kt index 14d4dd69cf5..d563126920f 100644 --- a/nj2k/testData/newJ2k/arrayType/d3StringEmptyArray.kt +++ b/nj2k/testData/newJ2k/arrayType/d3StringEmptyArray.kt @@ -1 +1 @@ -val sss = Array(5) { Array>(5) { arrayOfNulls(5) } } \ No newline at end of file +val sss = Array(5) { Array(5) { arrayOfNulls(5) } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/boxedType/kt-671.kt b/nj2k/testData/newJ2k/boxedType/kt-671.kt index c6936f66b6a..d3ab3327326 100644 --- a/nj2k/testData/newJ2k/boxedType/kt-671.kt +++ b/nj2k/testData/newJ2k/boxedType/kt-671.kt @@ -1,6 +1,6 @@ internal class Test { fun test() { - val i = Integer.valueOf(100) + val i: Int? = Integer.valueOf(100) val s: Short = 3 val ss = s } diff --git a/nj2k/testData/newJ2k/class/ClassShadowing.kt b/nj2k/testData/newJ2k/class/ClassShadowing.kt index 8d0dd358dbf..3a73aeb2f92 100644 --- a/nj2k/testData/newJ2k/class/ClassShadowing.kt +++ b/nj2k/testData/newJ2k/class/ClassShadowing.kt @@ -1,6 +1,6 @@ package test -class Integer(s: String?) { +class Integer(s: String) { companion object { fun valueOf(value: String): Integer { return Integer(value) diff --git a/nj2k/testData/newJ2k/class/kt-639.kt b/nj2k/testData/newJ2k/class/kt-639.kt index b450b040511..44f7056b18c 100644 --- a/nj2k/testData/newJ2k/class/kt-639.kt +++ b/nj2k/testData/newJ2k/class/kt-639.kt @@ -4,15 +4,14 @@ import java.util.HashMap internal class Test { constructor() {} - constructor(s: String?) {} + constructor(s: String) {} } internal class User { fun main() { val m: HashMap<*, *> = HashMap(1) val m2: HashMap<*, *> = HashMap(10) - val t1 = Test() val t2 = Test("") } -} +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/constructors/fieldsInitializedFromParams8.kt b/nj2k/testData/newJ2k/constructors/fieldsInitializedFromParams8.kt index 2428ec5be91..8fcb8ff6322 100644 --- a/nj2k/testData/newJ2k/constructors/fieldsInitializedFromParams8.kt +++ b/nj2k/testData/newJ2k/constructors/fieldsInitializedFromParams8.kt @@ -1,3 +1,2 @@ -internal open class Base(o: Any?, l: Int) - -internal class C(private val string: String) : Base(string, string.length) +internal open class Base(o: Any, l: Int) +internal class C(private val string: String) : Base(string, string.length) \ No newline at end of file diff --git a/nj2k/testData/newJ2k/constructors/genericIdentifier.kt b/nj2k/testData/newJ2k/constructors/genericIdentifier.kt index 88731a06536..19f8d4ff6d3 100644 --- a/nj2k/testData/newJ2k/constructors/genericIdentifier.kt +++ b/nj2k/testData/newJ2k/constructors/genericIdentifier.kt @@ -17,12 +17,13 @@ class Identifier { myHasDollar = hasDollar myNullable = isNullable } + } object User { fun main() { - val i1: Identifier<*> = Identifier("name", false, true) - val i2: Identifier<*> = Identifier("name", false) - val i3: Identifier<*> = Identifier("name") + val i1: Identifier<*> = Identifier("name", false, true) + val i2: Identifier<*> = Identifier("name", false) + val i3: Identifier<*> = Identifier("name") } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/constructors/nestedClassNameInSuperParameters.kt b/nj2k/testData/newJ2k/constructors/nestedClassNameInSuperParameters.kt index d8143794497..3f6f4d3ca39 100644 --- a/nj2k/testData/newJ2k/constructors/nestedClassNameInSuperParameters.kt +++ b/nj2k/testData/newJ2k/constructors/nestedClassNameInSuperParameters.kt @@ -1,4 +1,4 @@ -internal open class Base(nested: Nested?) { +internal open class Base(nested: Nested) { internal class Nested(p: Int) { companion object { const val FIELD = 0 diff --git a/nj2k/testData/newJ2k/detectProperties/OverridesOfExternalCode.kt b/nj2k/testData/newJ2k/detectProperties/OverridesOfExternalCode.kt index 70f59af6178..a98bc4cc224 100644 --- a/nj2k/testData/newJ2k/detectProperties/OverridesOfExternalCode.kt +++ b/nj2k/testData/newJ2k/detectProperties/OverridesOfExternalCode.kt @@ -82,9 +82,9 @@ internal class C : A() { } internal class D : JavaClassDerivedFromKotlinClassWithProperties() { - override fun getSomeVar1(): String? { + override fun getSomeVar1(): String { return "a" } - override fun setSomeVar2(value: String?) {} + override fun setSomeVar2(value: String) {} } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/function/externalKtFunctionalInterface.kt b/nj2k/testData/newJ2k/function/externalKtFunctionalInterface.kt index b62cc818d64..d8b53b259eb 100644 --- a/nj2k/testData/newJ2k/function/externalKtFunctionalInterface.kt +++ b/nj2k/testData/newJ2k/function/externalKtFunctionalInterface.kt @@ -11,6 +11,6 @@ internal class Test { fun nya(): Double { //TODO explicitlly call apply here - return foo(1, FunctionalI { x: Int -> this.toDouble(x) }) + return foo(1, FunctionalI { x: Int -> this.toDouble(x) }) } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/function/internalFunctionalInterface.kt b/nj2k/testData/newJ2k/function/internalFunctionalInterface.kt index 7ab1f821ca1..e084777bac0 100644 --- a/nj2k/testData/newJ2k/function/internalFunctionalInterface.kt +++ b/nj2k/testData/newJ2k/function/internalFunctionalInterface.kt @@ -1,4 +1,3 @@ -// ERROR: Type mismatch: inferred type is B? but B was expected // ERROR: Unresolved reference: A // ERROR: Interface FunctionalI does not have constructors internal interface FunctionalI { @@ -6,7 +5,7 @@ internal interface FunctionalI { } internal class Test { - fun foo(value: A, `fun`: FunctionalI): B { + fun foo(value: A, `fun`: FunctionalI): B { return `fun`.apply(value) } @@ -15,6 +14,6 @@ internal class Test { } fun nya(): Double { - return foo(1, FunctionalI { x: A -> this.toDouble(x) }) + return foo(1, FunctionalI { x: A -> this.toDouble(x) }) } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/function/ownGenericParam.kt b/nj2k/testData/newJ2k/function/ownGenericParam.kt index 6616cfad757..59e72c209a5 100644 --- a/nj2k/testData/newJ2k/function/ownGenericParam.kt +++ b/nj2k/testData/newJ2k/function/ownGenericParam.kt @@ -1 +1 @@ -fun putU(u: U?) {} \ No newline at end of file +fun putU(u: U) {} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/function/ownSeveralGenericParams.kt b/nj2k/testData/newJ2k/function/ownSeveralGenericParams.kt index c8fe75c2efd..5fcfd22be51 100644 --- a/nj2k/testData/newJ2k/function/ownSeveralGenericParams.kt +++ b/nj2k/testData/newJ2k/function/ownSeveralGenericParams.kt @@ -1 +1 @@ -fun putUVW(u: U?, v: V?, w: W?) {} \ No newline at end of file +fun putUVW(u: U, v: V, w: W) {} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseGeneric.kt b/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseGeneric.kt index 316fbbd64b1..99ec8d6fcf7 100644 --- a/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseGeneric.kt +++ b/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseGeneric.kt @@ -1,3 +1,2 @@ -internal open class Base(name: T?) - -internal class One(name: T?, private val mySecond: K) : Base(name) \ No newline at end of file +internal open class Base(name: T) +internal class One(name: T, private val mySecond: K) : Base(name) \ No newline at end of file diff --git a/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseWithOneParam.kt b/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseWithOneParam.kt index 2a9d7cd20cf..c64c1b12506 100644 --- a/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseWithOneParam.kt +++ b/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseWithOneParam.kt @@ -1,3 +1,2 @@ -internal open class Base(name: String?) - -internal class One(name: String?, second: String?) : Base(name) \ No newline at end of file +internal open class Base(name: String) +internal class One(name: String, second: String?) : Base(name) \ No newline at end of file diff --git a/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseWithZeroParamsNonEmptyConstructor.kt b/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseWithZeroParamsNonEmptyConstructor.kt index 9e7675451fd..ba9d813490b 100644 --- a/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseWithZeroParamsNonEmptyConstructor.kt +++ b/nj2k/testData/newJ2k/inheritance/classOneExtendsBaseWithZeroParamsNonEmptyConstructor.kt @@ -1,3 +1,2 @@ -internal open class Base(name: String?) - -internal class One(name: String?, private val mySecond: String) : Base(name) \ No newline at end of file +internal open class Base(name: String) +internal class One(name: String, private val mySecond: String) : Base(name) \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-1048.kt b/nj2k/testData/newJ2k/issues/kt-1048.kt index 7c75ba22201..2df6a082a50 100644 --- a/nj2k/testData/newJ2k/issues/kt-1048.kt +++ b/nj2k/testData/newJ2k/issues/kt-1048.kt @@ -3,7 +3,7 @@ // ERROR: Type argument is not within its bounds: should be subtype of 'String?' import java.util.HashMap -internal class G(t: T?) +internal class G(t: T) class Java { internal fun test() { val m: HashMap<*, *> = HashMap() diff --git a/nj2k/testData/newJ2k/issues/kt-19327.kt b/nj2k/testData/newJ2k/issues/kt-19327.kt index 4693bd2eedc..ec03905bffd 100644 --- a/nj2k/testData/newJ2k/issues/kt-19327.kt +++ b/nj2k/testData/newJ2k/issues/kt-19327.kt @@ -1,10 +1,7 @@ -// ERROR: Unresolved reference: stream -// ERROR: Unresolved reference: stream -// ERROR: Unresolved reference: Collectors import java.util.stream.Collectors internal class JavaCode { - fun toJSON(collection: Collection): String { - return "[" + collection.stream().map({ obj: Object -> obj.toString() }).collect(Collectors.joining(", ")).toString() + "]" + fun toJSON(collection: Collection): String { + return "[" + collection.stream().map { obj: Int -> obj.toString() }.collect(Collectors.joining(", ")).toString() + "]" } -} +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-19336.kt b/nj2k/testData/newJ2k/issues/kt-19336.kt index 1c30926646e..99323f59e87 100644 --- a/nj2k/testData/newJ2k/issues/kt-19336.kt +++ b/nj2k/testData/newJ2k/issues/kt-19336.kt @@ -1,6 +1,6 @@ class TestReturnsArray { fun strings(n: Int): Array { - val result = arrayOfNulls(n) + val result = arrayOfNulls(n) for (i in 0 until n) { result[i] = Integer.toString(i) } diff --git a/nj2k/testData/newJ2k/issues/kt-19346.kt b/nj2k/testData/newJ2k/issues/kt-19346.kt index dee7e60ca01..810b32e4623 100644 --- a/nj2k/testData/newJ2k/issues/kt-19346.kt +++ b/nj2k/testData/newJ2k/issues/kt-19346.kt @@ -2,7 +2,7 @@ package test class TestAssignmentInReturn { private var last: String? = null - fun foo(s: String): String? { + fun foo(s: String): String { return s.also { last = it } } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-19348.kt b/nj2k/testData/newJ2k/issues/kt-19348.kt index e4554cd289a..92f0461e53b 100644 --- a/nj2k/testData/newJ2k/issues/kt-19348.kt +++ b/nj2k/testData/newJ2k/issues/kt-19348.kt @@ -14,7 +14,7 @@ class TestMutltipleCtorsWithJavadoc * @param x * @param y */ - constructor(x: String?, y: String?) : this(x!!) { + constructor(x: String, y: String?) : this(x) { this.y = y } diff --git a/nj2k/testData/newJ2k/issues/kt-19382.kt b/nj2k/testData/newJ2k/issues/kt-19382.kt index a6b4f579b0d..3cadb176f1f 100644 --- a/nj2k/testData/newJ2k/issues/kt-19382.kt +++ b/nj2k/testData/newJ2k/issues/kt-19382.kt @@ -3,7 +3,7 @@ package test import java.util.HashMap class TestPrimitiveFromMap { - fun foo(map: HashMap): Int { + fun foo(map: HashMap): Int { return map["zzz"]!! } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-19383.kt b/nj2k/testData/newJ2k/issues/kt-19383.kt index 5e49ea51bfd..c2bf1ecada5 100644 --- a/nj2k/testData/newJ2k/issues/kt-19383.kt +++ b/nj2k/testData/newJ2k/issues/kt-19383.kt @@ -1,7 +1,7 @@ package test class TestMapGetAsReceiver { - fun foo(map: Map): Int { + fun foo(map: Map): Int { return map["zzz"]!!.length } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-19396.kt b/nj2k/testData/newJ2k/issues/kt-19396.kt index a27436ac9e1..a92ef992b37 100644 --- a/nj2k/testData/newJ2k/issues/kt-19396.kt +++ b/nj2k/testData/newJ2k/issues/kt-19396.kt @@ -3,7 +3,7 @@ package test class TestValReassign(private val s1: String) { private var s2: String? = null - constructor(s1: String?, s2: String?) : this(s1!!) { + constructor(s1: String, s2: String?) : this(s1) { this.s2 = s2 } diff --git a/nj2k/testData/newJ2k/issues/kt-19550.kt b/nj2k/testData/newJ2k/issues/kt-19550.kt index 760f559b11c..96bf5371d57 100644 --- a/nj2k/testData/newJ2k/issues/kt-19550.kt +++ b/nj2k/testData/newJ2k/issues/kt-19550.kt @@ -3,15 +3,15 @@ class TestToStringReturnsNullable { var string: String? = null } - open class Ctor(string: String?) : Base() { + open class Ctor(string: String) : Base() { init { this.string = string } } - class Derived(string: String?) : Ctor(string) { + class Derived(string: String) : Ctor(string) { override fun toString(): String { return string!! } } -} +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-19639.kt b/nj2k/testData/newJ2k/issues/kt-19639.kt index b5bbdeff0ba..1f0db751a83 100644 --- a/nj2k/testData/newJ2k/issues/kt-19639.kt +++ b/nj2k/testData/newJ2k/issues/kt-19639.kt @@ -1,13 +1,13 @@ -// ERROR: Type mismatch: inferred type is Enumeration<(raw) Any!>! but Enumeration? was expected +// ERROR: Type mismatch: inferred type is Enumeration<(raw) Any!>! but Enumeration was expected import java.util.Enumeration import javax.swing.tree.DefaultMutableTreeNode class TestJavaExpectedTypeInference { fun test(node: DefaultMutableTreeNode) { - val e: Enumeration? = node.children() - while (e!!.hasMoreElements()) { - val child = e.nextElement() - val name = child!!.userObject as String + val e: Enumeration = node.children() + while (e.hasMoreElements()) { + val child: DefaultMutableTreeNode = e.nextElement() + val name = child.userObject as String println(name) } } diff --git a/nj2k/testData/newJ2k/issues/kt-24677.java b/nj2k/testData/newJ2k/issues/kt-24677.java new file mode 100644 index 00000000000..0227c3a3d31 --- /dev/null +++ b/nj2k/testData/newJ2k/issues/kt-24677.java @@ -0,0 +1,16 @@ +import java.util.ArrayList; + +interface FooInterface { + ArrayList foo(); +} + +public class Foo implements FooInterface { + + @Override + public ArrayList foo() { + return null; + } + + public static class SomeClass { + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-24677.kt b/nj2k/testData/newJ2k/issues/kt-24677.kt new file mode 100644 index 00000000000..7648ba14608 --- /dev/null +++ b/nj2k/testData/newJ2k/issues/kt-24677.kt @@ -0,0 +1,13 @@ +import java.util.ArrayList + +internal interface FooInterface { + fun foo(): ArrayList? +} + +class Foo : FooInterface { + override fun foo(): ArrayList? { + return null + } + + class SomeClass +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-32572.java b/nj2k/testData/newJ2k/issues/kt-32572.java new file mode 100644 index 00000000000..495637fdee2 --- /dev/null +++ b/nj2k/testData/newJ2k/issues/kt-32572.java @@ -0,0 +1,7 @@ +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TestClass { + private Map> hashMap = new HashMap<>(); +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-32572.kt b/nj2k/testData/newJ2k/issues/kt-32572.kt new file mode 100644 index 00000000000..56d830dc225 --- /dev/null +++ b/nj2k/testData/newJ2k/issues/kt-32572.kt @@ -0,0 +1,5 @@ +import java.util.HashMap + +class TestClass { + private val hashMap: Map> = HashMap() +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-32609.java b/nj2k/testData/newJ2k/issues/kt-32609.java new file mode 100644 index 00000000000..71479ae37b7 --- /dev/null +++ b/nj2k/testData/newJ2k/issues/kt-32609.java @@ -0,0 +1,8 @@ +import org.jetbrains.annotations.NotNull; + +public class Book implements Comparable { + @Override + public int compareTo(@NotNull Book o) { + return 0; + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-32609.kt b/nj2k/testData/newJ2k/issues/kt-32609.kt new file mode 100644 index 00000000000..1d4c9690af2 --- /dev/null +++ b/nj2k/testData/newJ2k/issues/kt-32609.kt @@ -0,0 +1,5 @@ +class Book : Comparable { + override fun compareTo(o: Book): Int { + return 0 + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-638.kt b/nj2k/testData/newJ2k/issues/kt-638.kt index a479a6bfbc0..e2863fc9fa6 100644 --- a/nj2k/testData/newJ2k/issues/kt-638.kt +++ b/nj2k/testData/newJ2k/issues/kt-638.kt @@ -17,13 +17,14 @@ class Identifier { myHasDollar = hasDollar myNullable = isNullable } + } object User { @JvmStatic fun main(args: Array) { - val i1: Identifier<*> = Identifier("name", false, true) - val i2: Identifier<*> = Identifier("name", false) - val i3: Identifier<*> = Identifier("name") + val i1: Identifier<*> = Identifier("name", false, true) + val i2: Identifier<*> = Identifier("name", false) + val i3: Identifier<*> = Identifier("name") } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/issues/kt-792-mixed.kt b/nj2k/testData/newJ2k/issues/kt-792-mixed.kt index c42d5d13704..8ca7aaaa333 100644 --- a/nj2k/testData/newJ2k/issues/kt-792-mixed.kt +++ b/nj2k/testData/newJ2k/issues/kt-792-mixed.kt @@ -1,7 +1,6 @@ package demo -internal class Test(i: Int?) { - +internal class Test(i: Int) { fun test() { val i = 10 Test(i) diff --git a/nj2k/testData/newJ2k/issues/kt-807.kt b/nj2k/testData/newJ2k/issues/kt-807.kt index f4407133b15..bc27457fa35 100644 --- a/nj2k/testData/newJ2k/issues/kt-807.kt +++ b/nj2k/testData/newJ2k/issues/kt-807.kt @@ -13,7 +13,7 @@ internal object FileRead { val fstream = FileInputStream(File("file.txt")) val `in` = DataInputStream(fstream) val br = BufferedReader(InputStreamReader(`in`)) - var strLine: String? + var strLine: String while (br.readLine().also { strLine = it } != null) { println(strLine) } diff --git a/nj2k/testData/newJ2k/issues/kt-809-string.kt b/nj2k/testData/newJ2k/issues/kt-809-string.kt index fcd0dc07745..afa3bbcb248 100644 --- a/nj2k/testData/newJ2k/issues/kt-809-string.kt +++ b/nj2k/testData/newJ2k/issues/kt-809-string.kt @@ -8,8 +8,7 @@ internal object One { var myContainer = Container() } -internal class StringContainer(s: String?) - +internal class StringContainer(s: String) internal class Test { fun putString(s: String) {} fun test() { diff --git a/nj2k/testData/newJ2k/issues/kt-8170.kt b/nj2k/testData/newJ2k/issues/kt-8170.kt index 1aff1e6334e..af2dc349d8a 100644 --- a/nj2k/testData/newJ2k/issues/kt-8170.kt +++ b/nj2k/testData/newJ2k/issues/kt-8170.kt @@ -2,12 +2,12 @@ object ArrayNullable { @JvmStatic fun main(args: Array) { val notNull = 0 - val a1 = arrayOfNulls(2) + val a1 = arrayOfNulls(2) a1[0] = null a1[1] = notNull println(a1[0]) println(a1[1]) - val a2 = arrayOfNulls(2) + val a2 = arrayOfNulls(2) a2[0] = nullable() a2[1] = notNull println(a2[0]) diff --git a/nj2k/testData/newJ2k/javaStreamsApi/collectStream.java b/nj2k/testData/newJ2k/javaStreamsApi/collectStream.java new file mode 100644 index 00000000000..c79802fc944 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/collectStream.java @@ -0,0 +1,17 @@ +// RUNTIME_WITH_FULL_JDK + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +class Test { + public void main(List lst) { + List toList = lst.stream().collect(Collectors.toList()); + Set toSet = lst.stream().collect(Collectors.toSet()); + long count = lst.stream().count(); + boolean anyMatch = lst.stream().anyMatch(v -> v.isEmpty()); + boolean allMatch = lst.stream().allMatch(v -> v.isEmpty()); + boolean noneMatch = lst.stream().noneMatch(v -> v.isEmpty()); + lst.stream().forEach(v -> System.out.println(v)); + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/collectStream.kt b/nj2k/testData/newJ2k/javaStreamsApi/collectStream.kt new file mode 100644 index 00000000000..85c2b60fa95 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/collectStream.kt @@ -0,0 +1,13 @@ +import java.util.stream.Collectors + +internal class Test { + fun main(lst: List) { + val toList: List = lst.stream().collect(Collectors.toList()) + val toSet: Set = lst.stream().collect(Collectors.toSet()) + val count = lst.stream().count() + val anyMatch = lst.stream().anyMatch { v: String -> v.isEmpty() } + val allMatch = lst.stream().allMatch { v: String -> v.isEmpty() } + val noneMatch = lst.stream().noneMatch { v: String -> v.isEmpty() } + lst.stream().forEach { v: String -> println(v) } + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/createStream.java b/nj2k/testData/newJ2k/javaStreamsApi/createStream.java new file mode 100644 index 00000000000..d0d01b2c6b8 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/createStream.java @@ -0,0 +1,36 @@ +// RUNTIME_WITH_FULL_JDK + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class Test { + public void main(List lst) { + List streamOfList = lst.stream() + .map(x -> x + "e") + .collect(Collectors.toList()); + + List streamOfElements = Stream.of(1, 2, 3) + .map(x -> x + 1) + .collect(Collectors.toList()); + + Integer[] array = {1, 2, 3}; + List streamOfArray = Arrays.stream(array) + .map(x -> x + 1) + .collect(Collectors.toList()); + + List streamOfArray2 = Stream.of(array) + .map(x -> x + 1) + .collect(Collectors.toList()); + + List streamIterate = Stream.iterate(2, v -> v * 2) + .map(x -> x + 1) + .collect(Collectors.toList()); + + List streamGenerate = Stream.generate(() -> 42) + .map(x -> x + 1) + .collect(Collectors.toList()); + + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/createStream.kt b/nj2k/testData/newJ2k/javaStreamsApi/createStream.kt new file mode 100644 index 00000000000..a464b4e55f6 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/createStream.kt @@ -0,0 +1,27 @@ +import java.util.Arrays +import java.util.stream.Collectors +import java.util.stream.Stream + +internal class Test { + fun main(lst: List) { + val streamOfList: List = lst.stream() + .map { x: String -> x + "e" } + .collect(Collectors.toList()) + val streamOfElements: List = Stream.of(1, 2, 3) + .map { x: Int -> x + 1 } + .collect(Collectors.toList()) + val array = arrayOf(1, 2, 3) + val streamOfArray: List = Arrays.stream(array) + .map { x: Int -> x + 1 } + .collect(Collectors.toList()) + val streamOfArray2: List = Stream.of(*array) + .map { x: Int -> x + 1 } + .collect(Collectors.toList()) + val streamIterate: List = Stream.iterate(2, { v: Int -> v * 2 }) + .map { x: Int -> x + 1 } + .collect(Collectors.toList()) + val streamGenerate: List = Stream.generate { 42 } + .map { x: Int -> x + 1 } + .collect(Collectors.toList()) + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/dontCollectOnExistingStreams.java b/nj2k/testData/newJ2k/javaStreamsApi/dontCollectOnExistingStreams.java new file mode 100644 index 00000000000..7e0f9f75ced --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/dontCollectOnExistingStreams.java @@ -0,0 +1,13 @@ +// RUNTIME_WITH_FULL_JDK + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + +class Test { + public void main(List lst) { + Stream stream = Stream.of(1); + List list = stream.collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/dontCollectOnExistingStreams.kt b/nj2k/testData/newJ2k/javaStreamsApi/dontCollectOnExistingStreams.kt new file mode 100644 index 00000000000..9ad1baf6050 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/dontCollectOnExistingStreams.kt @@ -0,0 +1,9 @@ +import java.util.stream.Collectors +import java.util.stream.Stream + +internal class Test { + fun main(lst: List?) { + val stream: Stream = Stream.of(1) + val list: List = stream.collect(Collectors.toList()) + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/formatting.java b/nj2k/testData/newJ2k/javaStreamsApi/formatting.java new file mode 100644 index 00000000000..4794d3852c0 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/formatting.java @@ -0,0 +1,17 @@ +// RUNTIME_WITH_FULL_JDK + +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +class Test { + public void main(List lst) { + List newLst = /*before list*/lst/*after list*/./*before stream*/stream()/* after stream*/ + .filter(x -> x > 10) + .map(x -> x + 2)/*some comment*/./*another comment*/distinct()/* one more comment */.sorted()/*another one comment*/ + .sorted(Comparator.naturalOrder()) + .peek(x -> System.out.println(x)).limit(1) + .skip(42)/*skipped*/ + /*collecting one*/./*collecting two */collect(Collectors.toList())/* cool */; + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/formatting.kt b/nj2k/testData/newJ2k/javaStreamsApi/formatting.kt new file mode 100644 index 00000000000..da10b78bb70 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/formatting.kt @@ -0,0 +1,14 @@ +import java.util.Comparator +import java.util.stream.Collectors + +internal class Test { + fun main(lst: List) { + val newLst: List = /*before list*/lst/*after list*/.stream/*before stream*/()/* after stream*/ + .filter { x: Int -> x > 10 } + .map { x: Int -> x + 2 }/*some comment*/.distinct/*another comment*/()/* one more comment */.sorted()/*another one comment*/ + .sorted(Comparator.naturalOrder()) + .peek { x: Int -> println(x) }.limit(1) + .skip(42)/*skipped*/ + /*collecting one*/.collect/*collecting two */(Collectors.toList())/* cool */ + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/kt-21467.java b/nj2k/testData/newJ2k/javaStreamsApi/kt-21467.java new file mode 100644 index 00000000000..50a548f337e --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/kt-21467.java @@ -0,0 +1,23 @@ +// RUNTIME_WITH_FULL_JDK + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class Test { + public void main() { + List activities = Stream.of("12") + .map(v -> v + "nya") + .filter(v -> v != null) + .flatMap(v -> Stream.of(v) + .flatMap(s -> Stream.of(s)) + ).filter(v -> { + String name = v.getClass().getName(); + if (name.equals("name")) { + return false; + } + return !name.equals("other_name"); + }) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/kt-21467.kt b/nj2k/testData/newJ2k/javaStreamsApi/kt-21467.kt new file mode 100644 index 00000000000..9a5b2caba74 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/kt-21467.kt @@ -0,0 +1,21 @@ +import java.util.stream.Collectors +import java.util.stream.Stream + +internal class Test { + fun main() { + val activities: List = Stream.of("12") + .map { v: String -> v + "nya" } + .filter { v: String? -> v != null } + .flatMap { v: String -> + Stream.of(v) + .flatMap { s: String -> Stream.of(s) } + }.filter { v: String -> + val name: String = v.javaClass.name + if (name == "name") { + return@filter false + } + name != "other_name" + } + .collect(Collectors.toList()) + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/streamOperations.java b/nj2k/testData/newJ2k/javaStreamsApi/streamOperations.java new file mode 100644 index 00000000000..0f42899f952 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/streamOperations.java @@ -0,0 +1,21 @@ +// RUNTIME_WITH_FULL_JDK + +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class Test { + public void main(List lst) { + List newLst = lst.stream() + .filter(x -> x > 10) + .map(x -> x + 2) + .distinct() + .sorted() + .sorted(Comparator.naturalOrder()) + .peek(x-> System.out.println(x)) + .limit(1) + .skip(42) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/javaStreamsApi/streamOperations.kt b/nj2k/testData/newJ2k/javaStreamsApi/streamOperations.kt new file mode 100644 index 00000000000..ed970e78156 --- /dev/null +++ b/nj2k/testData/newJ2k/javaStreamsApi/streamOperations.kt @@ -0,0 +1,17 @@ +import java.util.Comparator +import java.util.stream.Collectors + +internal class Test { + fun main(lst: List) { + val newLst: List = lst.stream() + .filter { x: Int -> x > 10 } + .map { x: Int -> x + 2 } + .distinct() + .sorted() + .sorted(Comparator.naturalOrder()) + .peek { x: Int -> println(x) } + .limit(1) + .skip(42) + .collect(Collectors.toList()) + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/list/ForEach.kt b/nj2k/testData/newJ2k/list/ForEach.kt index f5f440b62f8..faf8b72d496 100644 --- a/nj2k/testData/newJ2k/list/ForEach.kt +++ b/nj2k/testData/newJ2k/list/ForEach.kt @@ -4,7 +4,7 @@ import java.util.ArrayList class ForEach { fun test() { val xs = ArrayList() - val ys: MutableList = LinkedList() + val ys: MutableList = LinkedList() for (x in xs) { ys.add(x) } diff --git a/nj2k/testData/newJ2k/list/Lists.kt b/nj2k/testData/newJ2k/list/Lists.kt index d11b79c3f35..3529329f0b7 100644 --- a/nj2k/testData/newJ2k/list/Lists.kt +++ b/nj2k/testData/newJ2k/list/Lists.kt @@ -4,7 +4,7 @@ import java.util.ArrayList class Lists { fun test() { val xs: MutableList = ArrayList() - val ys: MutableList = LinkedList() + val ys: MutableList = LinkedList() val zs = ArrayList() xs.add(null) ys.add(null) diff --git a/nj2k/testData/newJ2k/methodCallExpression/genericMethod.kt b/nj2k/testData/newJ2k/methodCallExpression/genericMethod.kt index 53c37030ee7..46f7994d56d 100644 --- a/nj2k/testData/newJ2k/methodCallExpression/genericMethod.kt +++ b/nj2k/testData/newJ2k/methodCallExpression/genericMethod.kt @@ -1,12 +1,12 @@ package demo internal class Map { - fun put(k: K?, v: V) {} + fun put(k: K, v: V) {} } internal class U { fun test() { val m = Map() - m.put(null, 10) + m.put(null, 10) } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/methodCallExpression/specialBuiltinMembers.kt b/nj2k/testData/newJ2k/methodCallExpression/specialBuiltinMembers.kt index 5a399e1e73f..9c99a2e0182 100644 --- a/nj2k/testData/newJ2k/methodCallExpression/specialBuiltinMembers.kt +++ b/nj2k/testData/newJ2k/methodCallExpression/specialBuiltinMembers.kt @@ -2,7 +2,7 @@ import java.util.HashMap internal enum class E { A, B, C } internal class A { - fun foo(list: List, collection: Collection, map: Map) { + fun foo(list: List, collection: Collection, map: Map) { val a = "".length val b = E.A.name val c = E.A.ordinal @@ -21,7 +21,6 @@ internal class A { val f = 10.1.toFloat() val l = 10.1.toLong() val s = 10.1.toShort() - try { val removed = list.removeAt(10) val isRemoved = list.remove("a") @@ -29,11 +28,10 @@ internal class A { System.err.println(e.message) throw RuntimeException(e.cause) } - for (entry in map.entries) { val key = entry.key val value = entry.value entry.setValue(value + 1) } } -} +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/methodCallExpression/stringMethods.kt b/nj2k/testData/newJ2k/methodCallExpression/stringMethods.kt index 28a9b703df6..68c60845be8 100644 --- a/nj2k/testData/newJ2k/methodCallExpression/stringMethods.kt +++ b/nj2k/testData/newJ2k/methodCallExpression/stringMethods.kt @@ -14,7 +14,7 @@ internal class A { String(intArrayOf(32, 65, 127), 0, 3) val bytes = byteArrayOf(32, 65, 100, 81) - val charset = Charset.forName("utf-8") + val charset: Charset = Charset.forName("utf-8") String(bytes) String(bytes, charset) String(bytes, 0, 2) @@ -60,7 +60,6 @@ internal class A { s.toLowerCase(Locale.FRENCH) s.toUpperCase() s.toUpperCase(Locale.FRENCH) - s s.toCharArray() } @@ -80,7 +79,8 @@ internal class A { 2 , ignoreCase = true) s.regionMatches(0, "st", 1, 2) - s.replace("\\w+".toRegex(), "---").replaceFirst("([s-t])".toRegex(), "A$1") + s.replace("\\w+".toRegex(), "---") + .replaceFirst("([s-t])".toRegex(), "A$1") /* TODO s.matches("\\w+"); useSplit(s.split("\\s+")); diff --git a/nj2k/testData/newJ2k/methodCallExpression/vararg1.kt b/nj2k/testData/newJ2k/methodCallExpression/vararg1.kt index 37649aa64e2..32d319acb9c 100644 --- a/nj2k/testData/newJ2k/methodCallExpression/vararg1.kt +++ b/nj2k/testData/newJ2k/methodCallExpression/vararg1.kt @@ -2,7 +2,7 @@ import java.lang.reflect.Constructor internal object X { @Throws(Exception::class) - fun foo(constructor: Constructor, args1: Array, args2: Array?) { + fun foo(constructor: Constructor, args1: Array, args2: Array?) { constructor.newInstance(*args1) constructor.newInstance(args1, args2) } diff --git a/nj2k/testData/newJ2k/mutableCollections/FunctionParameters.kt b/nj2k/testData/newJ2k/mutableCollections/FunctionParameters.kt index fd7a682d7ed..82533f68e54 100644 --- a/nj2k/testData/newJ2k/mutableCollections/FunctionParameters.kt +++ b/nj2k/testData/newJ2k/mutableCollections/FunctionParameters.kt @@ -1,9 +1,9 @@ internal class A { - fun foo(nonMutableCollection: Collection, + fun foo(nonMutableCollection: Collection?, mutableCollection: MutableCollection, mutableSet: MutableSet, - mutableMap: MutableMap) { - mutableCollection.addAll(nonMutableCollection) + mutableMap: MutableMap) { + mutableCollection.addAll(nonMutableCollection!!) mutableSet.add(mutableMap.remove("a")) } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/nullability/MethodResultInitializesNullableField.kt b/nj2k/testData/newJ2k/nullability/MethodResultInitializesNullableField.kt index 6fa75648e49..47e3824b341 100644 --- a/nj2k/testData/newJ2k/nullability/MethodResultInitializesNullableField.kt +++ b/nj2k/testData/newJ2k/nullability/MethodResultInitializesNullableField.kt @@ -1,10 +1,9 @@ // ERROR: Unresolved reference: x internal class C { - private val string = getString() + private val string: String? = getString() companion object { - - fun getString(): String? { + fun getString(): String { return x() } } diff --git a/nj2k/testData/newJ2k/nullability/kt-12050.kt b/nj2k/testData/newJ2k/nullability/kt-12050.kt index 25adb4aa436..2773fd39f6d 100644 --- a/nj2k/testData/newJ2k/nullability/kt-12050.kt +++ b/nj2k/testData/newJ2k/nullability/kt-12050.kt @@ -1,6 +1,6 @@ class NullableArray { fun createArrayFailure(size: Int): Array { - return arrayOfNulls(size) + return arrayOfNulls(size) } fun createArraySuccess(size: Int): Array { diff --git a/nj2k/testData/newJ2k/objectLiteral/MyFrame.kt b/nj2k/testData/newJ2k/objectLiteral/MyFrame.kt index 6cdfb27fd24..e0a74722156 100644 --- a/nj2k/testData/newJ2k/objectLiteral/MyFrame.kt +++ b/nj2k/testData/newJ2k/objectLiteral/MyFrame.kt @@ -11,18 +11,19 @@ internal open class WindowAdapter : WindowListener { } internal open class Frame { - fun addWindowListener(listener: WindowListener) {} + fun addWindowListener(listener: WindowListener?) {} } -internal class Client : Frame() {init { - val a: WindowAdapter = object : WindowAdapter() { - override fun windowClosing() {} +internal class Client : Frame() { + init { + val a: WindowAdapter = object : WindowAdapter() { + override fun windowClosing() {} + } + addWindowListener(a) + addWindowListener(object : WindowAdapter() { + override fun windowClosing() {} + }) + val b: EmptyWindowListener = object : EmptyWindowListener {} + val c: EmptyWindowAdapter = object : EmptyWindowAdapter() {} } - addWindowListener(a) - addWindowListener(object : WindowAdapter() { - override fun windowClosing() {} - }) - val b: EmptyWindowListener = object : EmptyWindowListener {} - val c: EmptyWindowAdapter = object : EmptyWindowAdapter() {} -} } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/overloads/Override.kt b/nj2k/testData/newJ2k/overloads/Override.kt index 320f95fb191..04ed0a08788 100644 --- a/nj2k/testData/newJ2k/overloads/Override.kt +++ b/nj2k/testData/newJ2k/overloads/Override.kt @@ -21,13 +21,11 @@ internal open class A : I { } fun bar(i: Int) {} - open fun x() { x(1) } fun x(i: Int) {} - fun y() { y(1) } diff --git a/nj2k/testData/newJ2k/postProcessing/GetOperator.kt b/nj2k/testData/newJ2k/postProcessing/GetOperator.kt index 2130fcffdb3..8058ae29076 100644 --- a/nj2k/testData/newJ2k/postProcessing/GetOperator.kt +++ b/nj2k/testData/newJ2k/postProcessing/GetOperator.kt @@ -9,7 +9,7 @@ internal class X { } internal class C { - fun foo(map: HashMap): String? { + fun foo(map: HashMap): String? { return map["a"] } @@ -24,4 +24,4 @@ internal class C { fun foo(javaClass: JavaClass): Int { return javaClass.get(0) } -} +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/postProcessing/IfToElvis.kt b/nj2k/testData/newJ2k/postProcessing/IfToElvis.kt index 9b4da7382d5..eb61b93373f 100644 --- a/nj2k/testData/newJ2k/postProcessing/IfToElvis.kt +++ b/nj2k/testData/newJ2k/postProcessing/IfToElvis.kt @@ -1,5 +1,5 @@ internal class C { - fun foo(s: String?): String { + fun foo(s: String?): String? { return s ?: "" } -} +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/postProcessing/RedundantTypeCast.kt b/nj2k/testData/newJ2k/postProcessing/RedundantTypeCast.kt index 10bf32e2e43..c7fea317dbb 100644 --- a/nj2k/testData/newJ2k/postProcessing/RedundantTypeCast.kt +++ b/nj2k/testData/newJ2k/postProcessing/RedundantTypeCast.kt @@ -4,4 +4,4 @@ internal class C { val l = o.length } } -} +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/postProcessing/RedunduntTypeCastAndProhibitedInline.kt b/nj2k/testData/newJ2k/postProcessing/RedunduntTypeCastAndProhibitedInline.kt index 9e18458fcc5..c7e80a46cdc 100644 --- a/nj2k/testData/newJ2k/postProcessing/RedunduntTypeCastAndProhibitedInline.kt +++ b/nj2k/testData/newJ2k/postProcessing/RedunduntTypeCastAndProhibitedInline.kt @@ -1,12 +1,10 @@ object C { - fun consume1(c: C?) {} - - fun consume2(c: C?) {} - - fun foo(cList: List) { + fun consume1(c: C) {} + fun consume2(c: C) {} + fun foo(cList: List) { val iter: Iterator<*> = cList.iterator() while (iter.hasNext()) { - val c = iter.next() as C? + val c = iter.next() as C consume1(c) consume2(c) } diff --git a/nj2k/testData/newJ2k/rawGenerics/kt-540-rawGenericClass.kt b/nj2k/testData/newJ2k/rawGenerics/kt-540-rawGenericClass.kt index 7fa47cc0c58..bf137ee7d70 100644 --- a/nj2k/testData/newJ2k/rawGenerics/kt-540-rawGenericClass.kt +++ b/nj2k/testData/newJ2k/rawGenerics/kt-540-rawGenericClass.kt @@ -1,6 +1,6 @@ package demo -internal class Collection(e: E?) { +internal class Collection(e: E) { init { println(e) } @@ -9,7 +9,7 @@ internal class Collection(e: E?) { internal class Test { fun main() { val raw1: Collection<*> = Collection(1) - val raw2: Collection<*> = Collection(1) - val raw3: Collection<*> = Collection("1") + val raw2: Collection<*> = Collection(1) + val raw3: Collection<*> = Collection("1") } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/rawGenerics/rawGenericMethod.kt b/nj2k/testData/newJ2k/rawGenerics/rawGenericMethod.kt index 6be2c6454ee..0e0d7378861 100644 --- a/nj2k/testData/newJ2k/rawGenerics/rawGenericMethod.kt +++ b/nj2k/testData/newJ2k/rawGenerics/rawGenericMethod.kt @@ -7,8 +7,8 @@ internal class TestT { internal class U { fun main() { val t = TestT() - t.getT() - t.getT() - t.getT() + t.getT() + t.getT() + t.getT() } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/toArray/toArray.kt b/nj2k/testData/newJ2k/toArray/toArray.kt index c4e615cae33..23ae7934308 100644 --- a/nj2k/testData/newJ2k/toArray/toArray.kt +++ b/nj2k/testData/newJ2k/toArray/toArray.kt @@ -6,7 +6,7 @@ import java.util.Arrays class Foo { fun test() { val list: List = Arrays.asList("a", "b") - val array1: Array = list.toTypedArray() + val array1: Array = list.toTypedArray() val array2: Array = list.toTypedArray() } } \ No newline at end of file diff --git a/nj2k/testData/newJ2k/toKotlinClasses/LibraryFunctions.kt b/nj2k/testData/newJ2k/toKotlinClasses/LibraryFunctions.kt index 1d7e0207db9..6d11f2c0c8c 100644 --- a/nj2k/testData/newJ2k/toKotlinClasses/LibraryFunctions.kt +++ b/nj2k/testData/newJ2k/toKotlinClasses/LibraryFunctions.kt @@ -3,7 +3,7 @@ package demo import java.util.ArrayList class TestJava { - fun f(result: Function1) { + fun f(result: Function1) { result.invoke("a") } diff --git a/nj2k/testData/newJ2k/typeCastExpression/extendsWildcardCast.kt b/nj2k/testData/newJ2k/typeCastExpression/extendsWildcardCast.kt index 63c3b30c0b5..af022671ead 100644 --- a/nj2k/testData/newJ2k/typeCastExpression/extendsWildcardCast.kt +++ b/nj2k/testData/newJ2k/typeCastExpression/extendsWildcardCast.kt @@ -1 +1 @@ -list as List? \ No newline at end of file +list as List \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeCastExpression/fooCast.kt b/nj2k/testData/newJ2k/typeCastExpression/fooCast.kt index c3d8f283675..646436f8d38 100644 --- a/nj2k/testData/newJ2k/typeCastExpression/fooCast.kt +++ b/nj2k/testData/newJ2k/typeCastExpression/fooCast.kt @@ -1 +1 @@ -t as Foo? \ No newline at end of file +t as Foo \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeCastExpression/simpleGenericCast.kt b/nj2k/testData/newJ2k/typeCastExpression/simpleGenericCast.kt index e1d2af10984..9148e3728fc 100644 --- a/nj2k/testData/newJ2k/typeCastExpression/simpleGenericCast.kt +++ b/nj2k/testData/newJ2k/typeCastExpression/simpleGenericCast.kt @@ -1 +1 @@ -list as List? \ No newline at end of file +list as List \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeCastExpression/stringCast.kt b/nj2k/testData/newJ2k/typeCastExpression/stringCast.kt index 6ab1deb69ce..3ee4ad88930 100644 --- a/nj2k/testData/newJ2k/typeCastExpression/stringCast.kt +++ b/nj2k/testData/newJ2k/typeCastExpression/stringCast.kt @@ -1 +1 @@ -t as String? \ No newline at end of file +t as String \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeCastExpression/superWildcardCast.kt b/nj2k/testData/newJ2k/typeCastExpression/superWildcardCast.kt index 7af8092d7e3..f84dd00e3e5 100644 --- a/nj2k/testData/newJ2k/typeCastExpression/superWildcardCast.kt +++ b/nj2k/testData/newJ2k/typeCastExpression/superWildcardCast.kt @@ -1 +1 @@ -list as List? \ No newline at end of file +list as List \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeCastExpression/wildcardCast.kt b/nj2k/testData/newJ2k/typeCastExpression/wildcardCast.kt index 05e19f3a6a8..8871eb54620 100644 --- a/nj2k/testData/newJ2k/typeCastExpression/wildcardCast.kt +++ b/nj2k/testData/newJ2k/typeCastExpression/wildcardCast.kt @@ -1 +1 @@ -list as List<*>? \ No newline at end of file +list as List<*> \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeParameters/classDoubleParametrizationWithTwoBoundsWithExtending.kt b/nj2k/testData/newJ2k/typeParameters/classDoubleParametrizationWithTwoBoundsWithExtending.kt index 617bb53be56..3170f947737 100644 --- a/nj2k/testData/newJ2k/typeParameters/classDoubleParametrizationWithTwoBoundsWithExtending.kt +++ b/nj2k/testData/newJ2k/typeParameters/classDoubleParametrizationWithTwoBoundsWithExtending.kt @@ -1,4 +1,4 @@ internal interface INode internal interface Node internal open class A -internal class CC : A() where T : INode?, T : Comparable?, K : Node?, K : Collection? \ No newline at end of file +internal class CC : A() where T : INode?, T : Comparable?, K : Node?, K : Collection? \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeParameters/classParametrizationWithTwoBounds.kt b/nj2k/testData/newJ2k/typeParameters/classParametrizationWithTwoBounds.kt index d83caf1682f..718bd6c5059 100644 --- a/nj2k/testData/newJ2k/typeParameters/classParametrizationWithTwoBounds.kt +++ b/nj2k/testData/newJ2k/typeParameters/classParametrizationWithTwoBounds.kt @@ -1,2 +1,2 @@ internal interface INode -internal class C where T : INode?, T : Comparable? \ No newline at end of file +internal class C where T : INode?, T : Comparable? \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeParameters/classParametrizationWithTwoBoundsWithExtending.kt b/nj2k/testData/newJ2k/typeParameters/classParametrizationWithTwoBoundsWithExtending.kt index 5e1ec0c8bc6..5e1679f7ee3 100644 --- a/nj2k/testData/newJ2k/typeParameters/classParametrizationWithTwoBoundsWithExtending.kt +++ b/nj2k/testData/newJ2k/typeParameters/classParametrizationWithTwoBoundsWithExtending.kt @@ -1,4 +1,3 @@ internal interface INode internal open class A - -internal class C : A() where T : INode?, T : Comparable? \ No newline at end of file +internal class C : A() where T : INode?, T : Comparable? \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeParameters/methodDoubleParametrizationWithTwoBounds.kt b/nj2k/testData/newJ2k/typeParameters/methodDoubleParametrizationWithTwoBounds.kt index 339e3c8dcbc..745e563c42e 100644 --- a/nj2k/testData/newJ2k/typeParameters/methodDoubleParametrizationWithTwoBounds.kt +++ b/nj2k/testData/newJ2k/typeParameters/methodDoubleParametrizationWithTwoBounds.kt @@ -1 +1 @@ -fun max(coll: Collection?): T? where T : Any?, T : Comparable?, K : Node?, K : Collection? {} \ No newline at end of file +fun max(coll: Collection?): T where T : Any?, T : Comparable?, K : Node?, K : Collection? {} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeParameters/traitDoubleParametrizationWithTwoBoundsWithExtending.kt b/nj2k/testData/newJ2k/typeParameters/traitDoubleParametrizationWithTwoBoundsWithExtending.kt index 659a47d1fa2..dea1de15915 100644 --- a/nj2k/testData/newJ2k/typeParameters/traitDoubleParametrizationWithTwoBoundsWithExtending.kt +++ b/nj2k/testData/newJ2k/typeParameters/traitDoubleParametrizationWithTwoBoundsWithExtending.kt @@ -1,5 +1,4 @@ internal interface INode internal interface Node internal interface II - -internal interface I : II where T : INode?, T : Comparable?, K : Node?, K : Collection? \ No newline at end of file +internal interface I : II where T : INode?, T : Comparable?, K : Node?, K : Collection? \ No newline at end of file diff --git a/nj2k/testData/newJ2k/typeParameters/where.kt b/nj2k/testData/newJ2k/typeParameters/where.kt index f3e4a71fe22..6c84c59a450 100644 --- a/nj2k/testData/newJ2k/typeParameters/where.kt +++ b/nj2k/testData/newJ2k/typeParameters/where.kt @@ -1 +1 @@ -fun max(coll: Collection?): T? where T : Any?, T : Comparable? {} \ No newline at end of file +fun max(coll: Collection?): T where T : Any?, T : Comparable? {} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/compareWithNull.kt b/nj2k/testData/nullabilityAnalysis/compareWithNull.kt deleted file mode 100644 index fbc379d45e7..00000000000 --- a/nj2k/testData/nullabilityAnalysis/compareWithNull.kt +++ /dev/null @@ -1,13 +0,0 @@ -fun a(): Int { - return 42 -} - -val b: Int = 2 - -fun c(p: Int) { - if (p == null); -} - -fun check() { - if (a() == null || b == null); -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/compareWithNull.kt.after b/nj2k/testData/nullabilityAnalysis/compareWithNull.kt.after deleted file mode 100644 index d1c8c886a8e..00000000000 --- a/nj2k/testData/nullabilityAnalysis/compareWithNull.kt.after +++ /dev/null @@ -1,13 +0,0 @@ -fun a(): Int? { - return 42 -} - -val b: Int? = 2 - -fun c(p: Int?) { - if (p == null); -} - -fun check() { - if (a() == null || b == null); -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/forcedNullability.kt b/nj2k/testData/nullabilityAnalysis/forcedNullability.kt deleted file mode 100644 index fefd4eae7a2..00000000000 --- a/nj2k/testData/nullabilityAnalysis/forcedNullability.kt +++ /dev/null @@ -1,11 +0,0 @@ -fun a(m: Map): String { - return m.get(42) -} - -fun b(m: Map): String { - return m.get(42) -} - -fun c() { - a(mapOf(q.to("nya"))) -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/forcedNullability.kt.after b/nj2k/testData/nullabilityAnalysis/forcedNullability.kt.after deleted file mode 100644 index 262ee0a29ce..00000000000 --- a/nj2k/testData/nullabilityAnalysis/forcedNullability.kt.after +++ /dev/null @@ -1,11 +0,0 @@ -fun a(m: Map): String? { - return m.get(42) -} - -fun b(m: Map): String? { - return m.get(42) -} - -fun c() { - a(mapOf(q.to("nya"))) -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/functionTypeParameterNullability.kt b/nj2k/testData/nullabilityAnalysis/functionTypeParameterNullability.kt deleted file mode 100644 index d08e635c7ec..00000000000 --- a/nj2k/testData/nullabilityAnalysis/functionTypeParameterNullability.kt +++ /dev/null @@ -1,6 +0,0 @@ -fun foo (x: T, y: List, z: S) {} - -fun bar() { - val lst: List = listOf(null) - foo(null, lst, "nya") -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/functionTypeParameterNullability.kt.after b/nj2k/testData/nullabilityAnalysis/functionTypeParameterNullability.kt.after deleted file mode 100644 index 8ff8ad5af68..00000000000 --- a/nj2k/testData/nullabilityAnalysis/functionTypeParameterNullability.kt.after +++ /dev/null @@ -1,6 +0,0 @@ -fun foo (x: T?, y: List, z: S) {} - -fun bar() { - val lst: List = listOf(null) - foo(null, lst, "nya") -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/functions.kt b/nj2k/testData/nullabilityAnalysis/functions.kt deleted file mode 100644 index 0da0f2aa2f7..00000000000 --- a/nj2k/testData/nullabilityAnalysis/functions.kt +++ /dev/null @@ -1,19 +0,0 @@ -fun notNullParameters(f: Function2) {} -fun nullableParameter(f: Function2) {} -fun nullableReturnType(f: Function2) {} - - -fun test() { - notNullParameters({ i: Int, j: Int -> - if (i < 10 && j > 0) "" else "" - }) - - nullableParameter({ i: Int, j: Int -> - if (i == null) "" else "" - }) - - nullableReturnType({ i: Int, j: Int -> - if (i < 10) return@nullableReturnType null - return@nullableReturnType "nya" - }) -} diff --git a/nj2k/testData/nullabilityAnalysis/functions.kt.after b/nj2k/testData/nullabilityAnalysis/functions.kt.after deleted file mode 100644 index 1c69c4c888d..00000000000 --- a/nj2k/testData/nullabilityAnalysis/functions.kt.after +++ /dev/null @@ -1,19 +0,0 @@ -fun notNullParameters(f: Function2) {} -fun nullableParameter(f: Function2) {} -fun nullableReturnType(f: Function2) {} - - -fun test() { - notNullParameters({ i: Int, j: Int -> - if (i < 10 && j > 0) "" else "" - }) - - nullableParameter({ i: Int?, j: Int -> - if (i == null) "" else "" - }) - - nullableReturnType({ i: Int, j: Int -> - if (i < 10) return@nullableReturnType null - return@nullableReturnType "nya" - }) -} diff --git a/nj2k/testData/nullabilityAnalysis/loops.kt b/nj2k/testData/nullabilityAnalysis/loops.kt deleted file mode 100644 index 3ef8700fd80..00000000000 --- a/nj2k/testData/nullabilityAnalysis/loops.kt +++ /dev/null @@ -1,16 +0,0 @@ -fun bar(map: HashMap, list1: List, list2: List) { - for (entry: MutableMap.MutableEntry in map.entries) { - val value: Int = entry.value - if (entry.key == null) { - println(value + 1) - } - } - - for (i: Int in list1) { - i + 1 - } - - for (i: String in list2) { - i == null - } -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/loops.kt.after b/nj2k/testData/nullabilityAnalysis/loops.kt.after deleted file mode 100644 index ee995b10c67..00000000000 --- a/nj2k/testData/nullabilityAnalysis/loops.kt.after +++ /dev/null @@ -1,16 +0,0 @@ -fun bar(map: HashMap, list1: List, list2: List) { - for (entry: MutableMap.MutableEntry in map.entries) { - val value: Int = entry.value - if (entry.key == null) { - println(value + 1) - } - } - - for (i: Int in list1) { - i + 1 - } - - for (i: String? in list2) { - i == null - } -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/nullAsAssignment.kt b/nj2k/testData/nullabilityAnalysis/nullAsAssignment.kt deleted file mode 100644 index 0a067e7faa2..00000000000 --- a/nj2k/testData/nullabilityAnalysis/nullAsAssignment.kt +++ /dev/null @@ -1,11 +0,0 @@ -fun test() { - var x: Int = 1 - x = null - - var y: Int = 5 - y = nullableFun() -} - -fun nullableFun(): Int { - return null -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/nullAsAssignment.kt.after b/nj2k/testData/nullabilityAnalysis/nullAsAssignment.kt.after deleted file mode 100644 index 8f118b7dd24..00000000000 --- a/nj2k/testData/nullabilityAnalysis/nullAsAssignment.kt.after +++ /dev/null @@ -1,11 +0,0 @@ -fun test() { - var x: Int? = 1 - x = null - - var y: Int? = 5 - y = nullableFun() -} - -fun nullableFun(): Int? { - return null -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/nullAsInitializer.kt b/nj2k/testData/nullabilityAnalysis/nullAsInitializer.kt deleted file mode 100644 index bf51fd3c3f1..00000000000 --- a/nj2k/testData/nullabilityAnalysis/nullAsInitializer.kt +++ /dev/null @@ -1,2 +0,0 @@ -val x: Int = null -fun foo(p: Int = null) {} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/nullAsInitializer.kt.after b/nj2k/testData/nullabilityAnalysis/nullAsInitializer.kt.after deleted file mode 100644 index 41fc7bb48c4..00000000000 --- a/nj2k/testData/nullabilityAnalysis/nullAsInitializer.kt.after +++ /dev/null @@ -1,2 +0,0 @@ -val x: Int? = null -fun foo(p: Int? = null) {} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/smartCast.kt b/nj2k/testData/nullabilityAnalysis/smartCast.kt deleted file mode 100644 index 559192a9fb8..00000000000 --- a/nj2k/testData/nullabilityAnalysis/smartCast.kt +++ /dev/null @@ -1,4 +0,0 @@ -fun foo(o: Int) { - if (o == null) return - val a: Int = o -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/smartCast.kt.after b/nj2k/testData/nullabilityAnalysis/smartCast.kt.after deleted file mode 100644 index 039d05d44e6..00000000000 --- a/nj2k/testData/nullabilityAnalysis/smartCast.kt.after +++ /dev/null @@ -1,4 +0,0 @@ -fun foo(o: Int?) { - if (o == null) return - val a: Int = o -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/spreadExpression.kt b/nj2k/testData/nullabilityAnalysis/spreadExpression.kt deleted file mode 100644 index 1078280306e..00000000000 --- a/nj2k/testData/nullabilityAnalysis/spreadExpression.kt +++ /dev/null @@ -1,5 +0,0 @@ -import java.lang.reflect.Constructor - -fun foo(constructor: Constructor, args: Array) { - constructor.newInstance(*args) -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/spreadExpression.kt.after b/nj2k/testData/nullabilityAnalysis/spreadExpression.kt.after deleted file mode 100644 index 5bbbca54d27..00000000000 --- a/nj2k/testData/nullabilityAnalysis/spreadExpression.kt.after +++ /dev/null @@ -1,5 +0,0 @@ -import java.lang.reflect.Constructor - -fun foo(constructor: Constructor, args: Array) { - constructor.newInstance(*args) -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/superMethod.kt b/nj2k/testData/nullabilityAnalysis/superMethod.kt deleted file mode 100644 index 06a7226ce21..00000000000 --- a/nj2k/testData/nullabilityAnalysis/superMethod.kt +++ /dev/null @@ -1,12 +0,0 @@ -open class A () { - open fun foo(x: Int): Int { - if (x == null); - return null - } -} - -class B : A() { - override fun foo(x: Int): Int { - return 1 - } -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/superMethod.kt.after b/nj2k/testData/nullabilityAnalysis/superMethod.kt.after deleted file mode 100644 index 266c2c118a1..00000000000 --- a/nj2k/testData/nullabilityAnalysis/superMethod.kt.after +++ /dev/null @@ -1,12 +0,0 @@ -open class A () { - open fun foo(x: Int?): Int? { - if (x == null); - return null - } -} - -class B : A() { - override fun foo(x: Int?): Int { - return 1 - } -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/typeCast.kt b/nj2k/testData/nullabilityAnalysis/typeCast.kt deleted file mode 100644 index 0b48e0ad566..00000000000 --- a/nj2k/testData/nullabilityAnalysis/typeCast.kt +++ /dev/null @@ -1,7 +0,0 @@ -fun foo() { - val cast1: Int = 1 as Int - val cast2: Int = null as Int - val cast3: Float = (1 as Int).toFloat() - val nya: Int = null - val cast4: Int = nya as Int -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/typeCast.kt.after b/nj2k/testData/nullabilityAnalysis/typeCast.kt.after deleted file mode 100644 index 6ee36f0edef..00000000000 --- a/nj2k/testData/nullabilityAnalysis/typeCast.kt.after +++ /dev/null @@ -1,7 +0,0 @@ -fun foo() { - val cast1: Int = 1 as Int - val cast2: Int? = null as Int? - val cast3: Float = (1 as Int).toFloat() - val nya: Int? = null - val cast4: Int? = nya as Int? -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/typeParameters.kt b/nj2k/testData/nullabilityAnalysis/typeParameters.kt deleted file mode 100644 index 25d179aad98..00000000000 --- a/nj2k/testData/nullabilityAnalysis/typeParameters.kt +++ /dev/null @@ -1,13 +0,0 @@ -fun foo() { - val l: List = List(1, {1}) - val a: Array = arrayOfNulls(42) - val b: Array = arrayOf(1,2,3) - val c: Array> = arrayOf>(arrayOfNulls(42)) - val d: Array> = arrayOf>(arrayOf(42)) - val e: Array> = arrayOf>(arrayOf(42, null)) - val f: Array> = arrayOf>(arrayOf(42, null), null) - val g: Array> = arrayOf>(arrayOf(42), null) - val h: Array = arrayOfNulls(5) - val i: Array> = Array>(5, { arrayOfNulls(5) }) - val k: Array = arrayOf(null) -} \ No newline at end of file diff --git a/nj2k/testData/nullabilityAnalysis/typeParameters.kt.after b/nj2k/testData/nullabilityAnalysis/typeParameters.kt.after deleted file mode 100644 index fdb5da98553..00000000000 --- a/nj2k/testData/nullabilityAnalysis/typeParameters.kt.after +++ /dev/null @@ -1,13 +0,0 @@ -fun foo() { - val l: List = List(1, {1}) - val a: Array = arrayOfNulls(42) - val b: Array = arrayOf(1,2,3) - val c: Array> = arrayOf>(arrayOfNulls(42)) - val d: Array> = arrayOf>(arrayOf(42)) - val e: Array> = arrayOf>(arrayOf(42, null)) - val f: Array?> = arrayOf?>(arrayOf(42, null), null) - val g: Array?> = arrayOf?>(arrayOf(42), null) - val h: Array = arrayOfNulls(5) - val i: Array> = Array>(5, { arrayOfNulls(5) }) - val k: Array = arrayOf(null) -} \ No newline at end of file diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterSingleFileTest.kt b/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterSingleFileTest.kt index 315a5a2dd1c..454223b2dd7 100644 --- a/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterSingleFileTest.kt +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNewJavaToKotlinConverterSingleFileTest.kt @@ -1,35 +1,16 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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 -import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.project.Project -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.projectRoots.SdkModificator -import com.intellij.openapi.projectRoots.impl.JavaSdkImpl -import com.intellij.openapi.util.io.FileUtil import com.intellij.psi.codeStyle.JavaCodeStyleSettings -import com.intellij.testFramework.LightProjectDescriptor import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices -import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterSingleFileTest import org.jetbrains.kotlin.j2k.ConverterSettings import org.jetbrains.kotlin.nj2k.postProcessing.NewJ2kPostProcessor -import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.KotlinTestUtils import java.io.File @@ -73,24 +54,6 @@ abstract class AbstractNewJavaToKotlinConverterSingleFileTest : AbstractJavaToKo File(javaPath.replace(".java", ".new.kt")).takeIf { it.exists() } ?: super.provideExpectedFile(javaPath) - private fun projectDescriptorByFileDirective(): LightProjectDescriptor { - if (isAllFilesPresentInTest()) return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - val fileText = FileUtil.loadFile(File(testDataPath, fileName()), true) - return if (InTextDirectivesUtils.isDirectiveDefined(fileText, "RUNTIME_WITH_FULL_JDK")) - KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK - else KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - } - - override fun getProjectDescriptor(): KotlinWithJdkAndRuntimeLightProjectDescriptor = - object : KotlinWithJdkAndRuntimeLightProjectDescriptor() { - override fun getSdk(): Sdk? { - val sdk = projectDescriptorByFileDirective().sdk ?: return null - runWriteAction { - val modificator: SdkModificator = sdk.sdkModificator - JavaSdkImpl.attachJdkAnnotations(modificator) - modificator.commitChanges() - } - return sdk - } - } + override fun getProjectDescriptor() = + descriptorByFileDirective(File(testDataPath, fileName()), isAllFilesPresentInTest()) } \ No newline at end of file diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNullabilityAnalysisTest.kt b/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNullabilityAnalysisTest.kt deleted file mode 100644 index 842065956e4..00000000000 --- a/nj2k/tests/org/jetbrains/kotlin/nj2k/AbstractNullabilityAnalysisTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 - -import com.intellij.openapi.util.io.FileUtil -import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase -import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor -import org.jetbrains.kotlin.nj2k.nullabilityAnalysis.AnalysisScope -import org.jetbrains.kotlin.nj2k.nullabilityAnalysis.Nullability -import org.jetbrains.kotlin.nj2k.nullabilityAnalysis.NullabilityAnalysisFacade -import org.jetbrains.kotlin.nj2k.nullabilityAnalysis.prepareTypeElementByMakingAllTypesNullable -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.test.KotlinTestUtils -import java.io.File - -abstract class AbstractNullabilityAnalysisTest : KotlinLightCodeInsightFixtureTestCase() { - - fun doTest(path: String) { - val file = File(path) - val text = FileUtil.loadFile(file, true) - val ktFile = myFixture.configureByText("converterTestFile.kt", text) as KtFile - NullabilityAnalysisFacade( - conversionContext = null, - getTypeElementNullability = { Nullability.UNKNOWN }, - prepareTypeElement = ::prepareTypeElementByMakingAllTypesNullable, - debugPrint = false - ) - .fixNullability(AnalysisScope(ktFile)) - val expectedFile = File(path.replace(".kt", ".kt.after")) - KotlinTestUtils.assertEqualsToFile(expectedFile, ktFile.text) - } - - override fun getProjectDescriptor() = - KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE -} \ No newline at end of file diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java b/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java index 1983cfcc7f8..8e654f04043 100644 --- a/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java @@ -2881,6 +2881,11 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew runTest("nj2k/testData/newJ2k/issues/kt-22848.java"); } + @TestMetadata("kt-24677.java") + public void testKt_24677() throws Exception { + runTest("nj2k/testData/newJ2k/issues/kt-24677.java"); + } + @TestMetadata("kt-28899.java") public void testKt_28899() throws Exception { runTest("nj2k/testData/newJ2k/issues/kt-28899.java"); @@ -2896,6 +2901,16 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew runTest("nj2k/testData/newJ2k/issues/kt-32436.java"); } + @TestMetadata("kt-32572.java") + public void testKt_32572() throws Exception { + runTest("nj2k/testData/newJ2k/issues/kt-32572.java"); + } + + @TestMetadata("kt-32609.java") + public void testKt_32609() throws Exception { + runTest("nj2k/testData/newJ2k/issues/kt-32609.java"); + } + @TestMetadata("kt-32702.java") public void testKt_32702() throws Exception { runTest("nj2k/testData/newJ2k/issues/kt-32702.java"); @@ -3077,6 +3092,49 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew } } + @TestMetadata("nj2k/testData/newJ2k/javaStreamsApi") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JavaStreamsApi extends AbstractNewJavaToKotlinConverterSingleFileTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInJavaStreamsApi() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("nj2k/testData/newJ2k/javaStreamsApi"), Pattern.compile("^([^\\.]+)\\.java$"), TargetBackend.ANY, true); + } + + @TestMetadata("collectStream.java") + public void testCollectStream() throws Exception { + runTest("nj2k/testData/newJ2k/javaStreamsApi/collectStream.java"); + } + + @TestMetadata("createStream.java") + public void testCreateStream() throws Exception { + runTest("nj2k/testData/newJ2k/javaStreamsApi/createStream.java"); + } + + @TestMetadata("dontCollectOnExistingStreams.java") + public void testDontCollectOnExistingStreams() throws Exception { + runTest("nj2k/testData/newJ2k/javaStreamsApi/dontCollectOnExistingStreams.java"); + } + + @TestMetadata("formatting.java") + public void testFormatting() throws Exception { + runTest("nj2k/testData/newJ2k/javaStreamsApi/formatting.java"); + } + + @TestMetadata("kt-21467.java") + public void testKt_21467() throws Exception { + runTest("nj2k/testData/newJ2k/javaStreamsApi/kt-21467.java"); + } + + @TestMetadata("streamOperations.java") + public void testStreamOperations() throws Exception { + runTest("nj2k/testData/newJ2k/javaStreamsApi/streamOperations.java"); + } + } + @TestMetadata("nj2k/testData/newJ2k/kotlinApiAccess") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/NullabilityAnalysisTestGenerated.java b/nj2k/tests/org/jetbrains/kotlin/nj2k/NullabilityAnalysisTestGenerated.java deleted file mode 100644 index bfe1b7e1b4f..00000000000 --- a/nj2k/tests/org/jetbrains/kotlin/nj2k/NullabilityAnalysisTestGenerated.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("nj2k/testData/nullabilityAnalysis") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class NullabilityAnalysisTestGenerated extends AbstractNullabilityAnalysisTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); - } - - public void testAllFilesPresentInNullabilityAnalysis() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("nj2k/testData/nullabilityAnalysis"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("compareWithNull.kt") - public void testCompareWithNull() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/compareWithNull.kt"); - } - - @TestMetadata("forcedNullability.kt") - public void testForcedNullability() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/forcedNullability.kt"); - } - - @TestMetadata("functionTypeParameterNullability.kt") - public void testFunctionTypeParameterNullability() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/functionTypeParameterNullability.kt"); - } - - @TestMetadata("functions.kt") - public void testFunctions() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/functions.kt"); - } - - @TestMetadata("loops.kt") - public void testLoops() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/loops.kt"); - } - - @TestMetadata("nullAsAssignment.kt") - public void testNullAsAssignment() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/nullAsAssignment.kt"); - } - - @TestMetadata("nullAsInitializer.kt") - public void testNullAsInitializer() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/nullAsInitializer.kt"); - } - - @TestMetadata("smartCast.kt") - public void testSmartCast() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/smartCast.kt"); - } - - @TestMetadata("spreadExpression.kt") - public void testSpreadExpression() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/spreadExpression.kt"); - } - - @TestMetadata("superMethod.kt") - public void testSuperMethod() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/superMethod.kt"); - } - - @TestMetadata("typeCast.kt") - public void testTypeCast() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/typeCast.kt"); - } - - @TestMetadata("typeParameters.kt") - public void testTypeParameters() throws Exception { - runTest("nj2k/testData/nullabilityAnalysis/typeParameters.kt"); - } -} diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/AbstractConstraintCollectorTest.kt b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/AbstractConstraintCollectorTest.kt new file mode 100644 index 00000000000..bd08f26c96b --- /dev/null +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/AbstractConstraintCollectorTest.kt @@ -0,0 +1,51 @@ +/* + * 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 + +import com.intellij.openapi.command.CommandProcessor +import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.PsiComment +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.idea.util.application.runWriteAction +import org.jetbrains.kotlin.nj2k.inference.common.InferenceFacade +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.io.File + +abstract class AbstractConstraintCollectorTest : KotlinLightCodeInsightFixtureTestCase() { + abstract fun createInferenceFacade(resolutionFacade: ResolutionFacade): InferenceFacade + + fun doTest(path: String) { + val file = File(path) + val text = FileUtil.loadFile(file, true) + val ktFile = myFixture.configureByText("converterTestFile.kt", text) as KtFile + val resolutionFacade = ktFile.getResolutionFacade() + CommandProcessor.getInstance().runUndoTransparentAction { + ktFile.prepareFile() + createInferenceFacade(resolutionFacade).runOn(listOf(ktFile)) + } + KotlinTestUtils.assertEqualsToFile(file, ktFile.text) + } + + open fun KtFile.prepareFile() = runWriteAction { + deleteComments() + } + + fun KtFile.deleteComments() { + for (comment in collectDescendantsOfType()) { + if (!comment.text.startsWith("// RUNTIME_WITH_FULL_JDK")) { + comment.delete() + } + } + } + + override fun getProjectDescriptor() = + KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE +} \ No newline at end of file diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/common/AbstractCommonConstraintCollectorTest.kt b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/common/AbstractCommonConstraintCollectorTest.kt new file mode 100644 index 00000000000..8e1f07f3e84 --- /dev/null +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/common/AbstractCommonConstraintCollectorTest.kt @@ -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.common + +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.nj2k.inference.AbstractConstraintCollectorTest +import org.jetbrains.kotlin.nj2k.inference.common.collectors.CallExpressionConstraintCollector +import org.jetbrains.kotlin.nj2k.inference.common.collectors.CommonConstraintsCollector +import org.jetbrains.kotlin.nj2k.inference.common.collectors.FunctionConstraintsCollector +import org.jetbrains.kotlin.psi.KtTypeElement + +abstract class AbstractCommonConstraintCollectorTest : AbstractConstraintCollectorTest() { + override fun createInferenceFacade(resolutionFacade: ResolutionFacade): InferenceFacade = + InferenceFacade( + object : ContextCollector(resolutionFacade) { + override fun ClassReference.getState(typeElement: KtTypeElement?): State? = + State.UNKNOWN + }, + ConstraintsCollectorAggregator( + resolutionFacade, + listOf( + CommonConstraintsCollector(), + CallExpressionConstraintCollector(), + FunctionConstraintsCollector(ResolveSuperFunctionsProvider(resolutionFacade)) + ) + ), + BoundTypeCalculatorImpl(resolutionFacade, BoundTypeEnhancer.ID), + object : StateUpdater() { + override fun updateStates(inferenceContext: InferenceContext) {} + }, + renderDebugTypes = true + ) +} \ No newline at end of file diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/common/CommonConstraintCollectorTestGenerated.java b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/common/CommonConstraintCollectorTestGenerated.java new file mode 100644 index 00000000000..42eb3a6058d --- /dev/null +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/common/CommonConstraintCollectorTestGenerated.java @@ -0,0 +1,191 @@ +/* + * 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; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("nj2k/testData/inference/common") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class CommonConstraintCollectorTestGenerated extends AbstractCommonConstraintCollectorTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInCommon() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("nj2k/testData/inference/common"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("arrayAssignment.kt") + public void testArrayAssignment() throws Exception { + runTest("nj2k/testData/inference/common/arrayAssignment.kt"); + } + + @TestMetadata("arrayOfArrays.kt") + public void testArrayOfArrays() throws Exception { + runTest("nj2k/testData/inference/common/arrayOfArrays.kt"); + } + + @TestMetadata("callFunctionWithTypeParamFromOuterScope.kt") + public void testCallFunctionWithTypeParamFromOuterScope() throws Exception { + runTest("nj2k/testData/inference/common/callFunctionWithTypeParamFromOuterScope.kt"); + } + + @TestMetadata("callWithTypeParams.kt") + public void testCallWithTypeParams() throws Exception { + runTest("nj2k/testData/inference/common/callWithTypeParams.kt"); + } + + @TestMetadata("constructorCall.kt") + public void testConstructorCall() throws Exception { + runTest("nj2k/testData/inference/common/constructorCall.kt"); + } + + @TestMetadata("delegationConstructorCall.kt") + public void testDelegationConstructorCall() throws Exception { + runTest("nj2k/testData/inference/common/delegationConstructorCall.kt"); + } + + @TestMetadata("elementOfArrayAssignment.kt") + public void testElementOfArrayAssignment() throws Exception { + runTest("nj2k/testData/inference/common/elementOfArrayAssignment.kt"); + } + + @TestMetadata("elementOfListAssignment.kt") + public void testElementOfListAssignment() throws Exception { + runTest("nj2k/testData/inference/common/elementOfListAssignment.kt"); + } + + @TestMetadata("forLoop.kt") + public void testForLoop() throws Exception { + runTest("nj2k/testData/inference/common/forLoop.kt"); + } + + @TestMetadata("functionCall.kt") + public void testFunctionCall() throws Exception { + runTest("nj2k/testData/inference/common/functionCall.kt"); + } + + @TestMetadata("functionReturn.kt") + public void testFunctionReturn() throws Exception { + runTest("nj2k/testData/inference/common/functionReturn.kt"); + } + + @TestMetadata("functionWithTypeParamCall.kt") + public void testFunctionWithTypeParamCall() throws Exception { + runTest("nj2k/testData/inference/common/functionWithTypeParamCall.kt"); + } + + @TestMetadata("lambdaAsParameter.kt") + public void testLambdaAsParameter() throws Exception { + runTest("nj2k/testData/inference/common/lambdaAsParameter.kt"); + } + + @TestMetadata("lambdaAssign.kt") + public void testLambdaAssign() throws Exception { + runTest("nj2k/testData/inference/common/lambdaAssign.kt"); + } + + @TestMetadata("lambdaImplicitReturn.kt") + public void testLambdaImplicitReturn() throws Exception { + runTest("nj2k/testData/inference/common/lambdaImplicitReturn.kt"); + } + + @TestMetadata("lambdaReturn.kt") + public void testLambdaReturn() throws Exception { + runTest("nj2k/testData/inference/common/lambdaReturn.kt"); + } + + @TestMetadata("listAssignment.kt") + public void testListAssignment() throws Exception { + runTest("nj2k/testData/inference/common/listAssignment.kt"); + } + + @TestMetadata("listGenerator.kt") + public void testListGenerator() throws Exception { + runTest("nj2k/testData/inference/common/listGenerator.kt"); + } + + @TestMetadata("listOfLists.kt") + public void testListOfLists() throws Exception { + runTest("nj2k/testData/inference/common/listOfLists.kt"); + } + + @TestMetadata("listOfListsGenerator.kt") + public void testListOfListsGenerator() throws Exception { + runTest("nj2k/testData/inference/common/listOfListsGenerator.kt"); + } + + @TestMetadata("memberCall.kt") + public void testMemberCall() throws Exception { + runTest("nj2k/testData/inference/common/memberCall.kt"); + } + + @TestMetadata("returnFromLambda.kt") + public void testReturnFromLambda() throws Exception { + runTest("nj2k/testData/inference/common/returnFromLambda.kt"); + } + + @TestMetadata("sequenceOfCalls.kt") + public void testSequenceOfCalls() throws Exception { + runTest("nj2k/testData/inference/common/sequenceOfCalls.kt"); + } + + @TestMetadata("sequenceOfCallsWIthLambda.kt") + public void testSequenceOfCallsWIthLambda() throws Exception { + runTest("nj2k/testData/inference/common/sequenceOfCallsWIthLambda.kt"); + } + + @TestMetadata("simpleAssignment.kt") + public void testSimpleAssignment() throws Exception { + runTest("nj2k/testData/inference/common/simpleAssignment.kt"); + } + + @TestMetadata("superCall.kt") + public void testSuperCall() throws Exception { + runTest("nj2k/testData/inference/common/superCall.kt"); + } + + @TestMetadata("superConstuctorCall.kt") + public void testSuperConstuctorCall() throws Exception { + runTest("nj2k/testData/inference/common/superConstuctorCall.kt"); + } + + @TestMetadata("superFunctionReturnTypeWithTypeParameters.kt") + public void testSuperFunctionReturnTypeWithTypeParameters() throws Exception { + runTest("nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParameters.kt"); + } + + @TestMetadata("superFunctionReturnTypeWithTypeParametersSubstitution.kt") + public void testSuperFunctionReturnTypeWithTypeParametersSubstitution() throws Exception { + runTest("nj2k/testData/inference/common/superFunctionReturnTypeWithTypeParametersSubstitution.kt"); + } + + @TestMetadata("superFunctionType.kt") + public void testSuperFunctionType() throws Exception { + runTest("nj2k/testData/inference/common/superFunctionType.kt"); + } + + @TestMetadata("typeParamsBounds.kt") + public void testTypeParamsBounds() throws Exception { + runTest("nj2k/testData/inference/common/typeParamsBounds.kt"); + } + + @TestMetadata("varargsInCall.kt") + public void testVarargsInCall() throws Exception { + runTest("nj2k/testData/inference/common/varargsInCall.kt"); + } +} diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/nullability/AbstractNullabilityInferenceTest.kt b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/nullability/AbstractNullabilityInferenceTest.kt new file mode 100644 index 00000000000..e19ce1e4c60 --- /dev/null +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/nullability/AbstractNullabilityInferenceTest.kt @@ -0,0 +1,72 @@ +/* + * 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 com.intellij.openapi.application.runWriteAction +import com.intellij.psi.codeStyle.JavaCodeStyleSettings +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.nj2k.descriptorByFileDirective +import org.jetbrains.kotlin.nj2k.inference.AbstractConstraintCollectorTest +import org.jetbrains.kotlin.nj2k.inference.common.* +import org.jetbrains.kotlin.nj2k.inference.common.collectors.CallExpressionConstraintCollector +import org.jetbrains.kotlin.nj2k.inference.common.collectors.CommonConstraintsCollector +import org.jetbrains.kotlin.nj2k.inference.common.collectors.FunctionConstraintsCollector +import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtTypeElement +import org.jetbrains.kotlin.psi.KtTypeReference +import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType +import java.io.File + +abstract class AbstractNullabilityInferenceTest : AbstractConstraintCollectorTest() { + override fun createInferenceFacade(resolutionFacade: ResolutionFacade): InferenceFacade { + val typeEnhancer = NullabilityBoundTypeEnhancer(resolutionFacade) + return InferenceFacade( + object : ContextCollector(resolutionFacade) { + override fun ClassReference.getState(typeElement: KtTypeElement?): State? = + State.UNKNOWN + }, + ConstraintsCollectorAggregator( + resolutionFacade, + listOf( + CommonConstraintsCollector(), + CallExpressionConstraintCollector(), + FunctionConstraintsCollector(ResolveSuperFunctionsProvider(resolutionFacade)), + NullabilityConstraintsCollector() + ) + ), + BoundTypeCalculatorImpl(resolutionFacade, typeEnhancer), + NullabilityStateUpdater(), + renderDebugTypes = true + ) + } + + override fun KtFile.prepareFile() = runWriteAction { + fun KtTypeReference.updateNullability() { + NullabilityStateUpdater.changeState(typeElement ?: return, toNullable = true) + for (typeArgument in typeElement!!.typeArgumentsAsTypes) { + typeArgument.updateNullability() + } + } + for (typeReference in collectDescendantsOfType()) { + if (typeReference.parent is KtConstructorCalleeExpression) continue + typeReference.updateNullability() + } + deleteComments() + } + + override fun setUp() { + super.setUp() + JavaCodeStyleSettings.getInstance(project).USE_EXTERNAL_ANNOTATIONS = true + } + + override fun tearDown() { + JavaCodeStyleSettings.getInstance(project).USE_EXTERNAL_ANNOTATIONS = false + super.tearDown() + } + + override fun getProjectDescriptor() = + descriptorByFileDirective(File(testDataPath, fileName()), isAllFilesPresentInTest())} \ No newline at end of file diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityInferenceTestGenerated.java b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityInferenceTestGenerated.java new file mode 100644 index 00000000000..f07fdbedfb5 --- /dev/null +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/inference/nullability/NullabilityInferenceTestGenerated.java @@ -0,0 +1,181 @@ +/* + * 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 com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("nj2k/testData/inference/nullability") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class NullabilityInferenceTestGenerated extends AbstractNullabilityInferenceTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInNullability() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("nj2k/testData/inference/nullability"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("arrayOfArraysOfNull.kt") + public void testArrayOfArraysOfNull() throws Exception { + runTest("nj2k/testData/inference/nullability/arrayOfArraysOfNull.kt"); + } + + @TestMetadata("arrayOfNulls.kt") + public void testArrayOfNulls() throws Exception { + runTest("nj2k/testData/inference/nullability/arrayOfNulls.kt"); + } + + @TestMetadata("binaryExpressionOperand.kt") + public void testBinaryExpressionOperand() throws Exception { + runTest("nj2k/testData/inference/nullability/binaryExpressionOperand.kt"); + } + + @TestMetadata("callExternallyAnnotatedJavaFunction.kt") + public void testCallExternallyAnnotatedJavaFunction() throws Exception { + runTest("nj2k/testData/inference/nullability/callExternallyAnnotatedJavaFunction.kt"); + } + + @TestMetadata("classTypeParameters.kt") + public void testClassTypeParameters() throws Exception { + runTest("nj2k/testData/inference/nullability/classTypeParameters.kt"); + } + + @TestMetadata("compareWithNull.kt") + public void testCompareWithNull() throws Exception { + runTest("nj2k/testData/inference/nullability/compareWithNull.kt"); + } + + @TestMetadata("forcedNullability.kt") + public void testForcedNullability() throws Exception { + runTest("nj2k/testData/inference/nullability/forcedNullability.kt"); + } + + @TestMetadata("functionTypeParameterNullability.kt") + public void testFunctionTypeParameterNullability() throws Exception { + runTest("nj2k/testData/inference/nullability/functionTypeParameterNullability.kt"); + } + + @TestMetadata("functions.kt") + public void testFunctions() throws Exception { + runTest("nj2k/testData/inference/nullability/functions.kt"); + } + + @TestMetadata("ifCondition.kt") + public void testIfCondition() throws Exception { + runTest("nj2k/testData/inference/nullability/ifCondition.kt"); + } + + @TestMetadata("javaStream.kt") + public void testJavaStream() throws Exception { + runTest("nj2k/testData/inference/nullability/javaStream.kt"); + } + + @TestMetadata("lambdaReturnNull.kt") + public void testLambdaReturnNull() throws Exception { + runTest("nj2k/testData/inference/nullability/lambdaReturnNull.kt"); + } + + @TestMetadata("listOfWithNullLiteral.kt") + public void testListOfWithNullLiteral() throws Exception { + runTest("nj2k/testData/inference/nullability/listOfWithNullLiteral.kt"); + } + + @TestMetadata("loopIterator.kt") + public void testLoopIterator() throws Exception { + runTest("nj2k/testData/inference/nullability/loopIterator.kt"); + } + + @TestMetadata("loops.kt") + public void testLoops() throws Exception { + runTest("nj2k/testData/inference/nullability/loops.kt"); + } + + @TestMetadata("notNullCallSequence.kt") + public void testNotNullCallSequence() throws Exception { + runTest("nj2k/testData/inference/nullability/notNullCallSequence.kt"); + } + + @TestMetadata("nullAsAssignment.kt") + public void testNullAsAssignment() throws Exception { + runTest("nj2k/testData/inference/nullability/nullAsAssignment.kt"); + } + + @TestMetadata("nullAsInitializer.kt") + public void testNullAsInitializer() throws Exception { + runTest("nj2k/testData/inference/nullability/nullAsInitializer.kt"); + } + + @TestMetadata("nullLiteral.kt") + public void testNullLiteral() throws Exception { + runTest("nj2k/testData/inference/nullability/nullLiteral.kt"); + } + + @TestMetadata("returnNull.kt") + public void testReturnNull() throws Exception { + runTest("nj2k/testData/inference/nullability/returnNull.kt"); + } + + @TestMetadata("sequenceOfCallsWIthLambda.kt") + public void testSequenceOfCallsWIthLambda() throws Exception { + runTest("nj2k/testData/inference/nullability/sequenceOfCallsWIthLambda.kt"); + } + + @TestMetadata("smartCast.kt") + public void testSmartCast() throws Exception { + runTest("nj2k/testData/inference/nullability/smartCast.kt"); + } + + @TestMetadata("spreadExpression.kt") + public void testSpreadExpression() throws Exception { + runTest("nj2k/testData/inference/nullability/spreadExpression.kt"); + } + + @TestMetadata("superMethod.kt") + public void testSuperMethod() throws Exception { + runTest("nj2k/testData/inference/nullability/superMethod.kt"); + } + + @TestMetadata("typeCast.kt") + public void testTypeCast() throws Exception { + runTest("nj2k/testData/inference/nullability/typeCast.kt"); + } + + @TestMetadata("typeParameters.kt") + public void testTypeParameters() throws Exception { + runTest("nj2k/testData/inference/nullability/typeParameters.kt"); + } + + @TestMetadata("typeParametersReturnType.kt") + public void testTypeParametersReturnType() throws Exception { + runTest("nj2k/testData/inference/nullability/typeParametersReturnType.kt"); + } + + @TestMetadata("typeParametersValueParams.kt") + public void testTypeParametersValueParams() throws Exception { + runTest("nj2k/testData/inference/nullability/typeParametersValueParams.kt"); + } + + @TestMetadata("useAsReceiver.kt") + public void testUseAsReceiver() throws Exception { + runTest("nj2k/testData/inference/nullability/useAsReceiver.kt"); + } + + @TestMetadata("whileCondition.kt") + public void testWhileCondition() throws Exception { + runTest("nj2k/testData/inference/nullability/whileCondition.kt"); + } +} diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/testUtils.kt b/nj2k/tests/org/jetbrains/kotlin/nj2k/testUtils.kt new file mode 100644 index 00000000000..dd3ee433c66 --- /dev/null +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/testUtils.kt @@ -0,0 +1,47 @@ +/* + * 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 + +import com.intellij.openapi.application.runWriteAction +import com.intellij.openapi.module.Module +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.projectRoots.SdkModificator +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl +import com.intellij.openapi.roots.LanguageLevelModuleExtension +import com.intellij.openapi.roots.ModifiableRootModel +import com.intellij.openapi.util.io.FileUtil +import com.intellij.pom.java.LanguageLevel +import com.intellij.testFramework.LightProjectDescriptor +import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.test.InTextDirectivesUtils +import java.io.File + +fun descriptorByFileDirective(testDataFile: File, isAllFilesPresentInTest: Boolean) = + object : KotlinWithJdkAndRuntimeLightProjectDescriptor() { + private fun projectDescriptorByFileDirective(): LightProjectDescriptor { + if (isAllFilesPresentInTest) return KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE + val fileText = FileUtil.loadFile(testDataFile, true) + return if (InTextDirectivesUtils.isDirectiveDefined(fileText, "RUNTIME_WITH_FULL_JDK")) + INSTANCE_FULL_JDK + else INSTANCE + } + + override fun getSdk(): Sdk? { + val sdk = projectDescriptorByFileDirective().sdk ?: return null + runWriteAction { + val modificator: SdkModificator = sdk.sdkModificator + JavaSdkImpl.attachJdkAnnotations(modificator) + modificator.commitChanges() + } + return sdk + } + + override fun configureModule(module: Module, model: ModifiableRootModel) { + super.configureModule(module, model) + model.getModuleExtension(LanguageLevelModuleExtension::class.java).languageLevel = LanguageLevel.JDK_1_8 + } + } +