Skip to content

Commit

Permalink
fix: fix imprecise inspection for MethodHandles.constant (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
SirYwell committed Jun 24, 2023
1 parent 6d3c760 commit a1a9334
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,29 @@ class MethodHandleCreationInspection: LocalInspectionTool() {
private fun checkConstant(expression: PsiMethodCallExpression, type: MhExactType) {
val parameters = expression.argumentList.expressionTypes
if (parameters.size != 2) return
// TODO this method does not match the actual behavior
if (!TypeConversionUtil.areTypesConvertible(type.signature.returnType, parameters[1])) {
// TODO fix message
if (!returnTypesAreCompatible(type, parameters[1])) {
problemsHolder.registerProblem(
expression.methodExpression as PsiExpression,
MethodHandleBundle.message("problem.invocation.arguments.wrong.types",
type.signature.parameters.map { it.presentableText },
expression.argumentList.expressionTypes.map { it.presentableText }
MethodHandleBundle.message("problem.creation.arguments.expected.type",
type.signature.returnType.presentableText,
parameters[1].presentableText
),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING
)
}
checkParamNotVoidAt(expression, 0)
}

private fun returnTypesAreCompatible(
type: MhExactType,
parameter: PsiType
): Boolean {
if (type.signature.returnType is PsiPrimitiveType) {
return TypeConversionUtil.isAssignable(type.signature.returnType, parameter)
}
return TypeConversionUtil.areTypesConvertible(type.signature.returnType, parameter)
}

private fun checkParamNotVoidAt(expression: PsiMethodCallExpression, index: Int) {
val parameters = expression.argumentList.expressions
if (parameters.size <= index) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ problem.invocation.arguments.wrong.types=There are arguments with wrong static t
displayname.dataflow.analysis.methodhandle.creation=MethodHandle creation issues
displayname.dataflow.analysis.methodhandle.merge=MethodHandle merge issues
problem.creation.arguments.invalid.type=Parameter must not be of type {0}.
problem.creation.arguments.expected.type=Expected parameter of type {0} but got {1}.
problem.merging.catchException.missingException=Argument 'handler' is missing leading exception parameter {0} or supertype.
problem.merging.general.incompatibleReturnType=Incompatible return types: {0} != {1}
problem.merging.general.otherReturnTypeExpected=Unexpected return type {0}, must be {1}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ class MethodHandleInspectionsTest : LightJavaCodeInsightFixtureTestCase() {

fun testVoidInIdentity() = doTest()

fun testWrongArgumentTypeInConstant() = doTest()

}
13 changes: 13 additions & 0 deletions src/test/testData/WrongArgumentTypeInConstant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;

class WrongArgumentTypeInConstant {
private static final MethodHandle a = <warning descr="Expected parameter of type byte but got int.">MethodHandles.constant</warning>(byte.class, 0);
private static final MethodHandle b = <warning descr="Expected parameter of type int but got String.">MethodHandles.constant</warning>(int.class, "Hello World"); // CCE
private static final MethodHandle c = <warning descr="Expected parameter of type byte but got int.">MethodHandles.constant</warning>(byte.class, 0); // CCE
private static final MethodHandle d = MethodHandles.constant(byte.class, (byte) 0); // fine
private static final MethodHandle e = MethodHandles.constant(int.class, (byte) 0); // fine
private static final MethodHandle f = MethodHandles.constant(CharSequence.class, "Hello"); // fine
private static final MethodHandle g = MethodHandles.constant(String.class, (CharSequence) "a"); // fine
private static final MethodHandle h = <warning descr="Expected parameter of type String but got Integer.">MethodHandles.constant</warning>(String.class, Integer.valueOf(1)); // CCE
}

0 comments on commit a1a9334

Please sign in to comment.