IDEA-122624 @Contract fails on vararg methods

This commit is contained in:
peter
2014-03-28 19:12:00 +01:00
parent 6199ff61af
commit 87a2944e37
3 changed files with 49 additions and 1 deletions
@@ -1414,11 +1414,22 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
return false;
}
PsiMethod method = expression.resolveMethod();
if (method == null) {
return false;
}
final int paramCount = method.getParameterList().getParametersCount();
boolean varArgs = method.isVarArgs();
final PsiExpression[] args = expression.getArgumentList().getExpressions();
if (varArgs && args.length < paramCount - 1 || !varArgs && args.length != paramCount) {
return false;
}
List<MethodContract> contracts = ContainerUtil.findAll(_contracts, new Condition<MethodContract>() {
@Override
public boolean value(MethodContract contract) {
return args.length == contract.arguments.length;
return paramCount == contract.arguments.length;
}
});
if (contracts.isEmpty()) {
@@ -1428,6 +1439,12 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
for (PsiExpression arg : args) {
arg.accept(this);
}
if (varArgs) {
for (int i = 0; i < args.length - paramCount + 1; i++) {
addInstruction(new PopInstruction());
}
pushUnknown();
}
if (contracts.size() > 1) {
addInstruction(new DupInstruction(args.length, contracts.size() - 1));
@@ -0,0 +1,30 @@
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class Contracts {
public void simpleFail(@Nullable String message) {
notBlank(message);
log(message);
}
@Contract("_->fail")
private void notBlank(@Nullable Object message) {
}
@Contract("_,_,_->fail")
private void notBlank(@Nullable Object o, String message, Object... args) {
}
public void varargFail(@Nullable String message) {
notBlank(message, "Message should not be blank");
log(message); // highlighted
}
public void log(@NotNull String message) {
System.out.println(message);
}
}
@@ -274,6 +274,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testContractWithNullable() { doTest(); }
public void testContractPreservesUnknownNullability() { doTest(); }
public void testContractSeveralClauses() { doTest(); }
public void testContractVarargs() { doTest(); }
public void testBoxingImpliesNotNull() { doTest(); }
public void testLargeIntegersAreNotEqualWhenBoxed() { doTest(); }