diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspectionBase.java index 907555f8a1b6..684d035efffc 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MalformedFormatStringInspectionBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2016 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2017 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.FormatUtils; +import com.siyeh.ig.psiutils.ParenthesesUtils; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -130,12 +131,13 @@ public class MalformedFormatStringInspectionBase extends BaseInspection { return; } final PsiExpressionList argumentList = expression.getArgumentList(); - final PsiExpression[] arguments = argumentList.getExpressions(); - final int formatArgumentIndex = findFirstStringArgumentIndex(arguments); + PsiExpression[] arguments = argumentList.getExpressions(); + int formatArgumentIndex = findFirstStringArgumentIndex(arguments); if (formatArgumentIndex < 0) { return; } final PsiExpression formatArgument = arguments[formatArgumentIndex]; + formatArgumentIndex++; if (!ExpressionUtils.hasStringType(formatArgument) || !PsiUtil.isConstantExpression(formatArgument)) { return; } @@ -147,7 +149,7 @@ public class MalformedFormatStringInspectionBase extends BaseInspection { if (value == null) { return; } - final int argumentCount = arguments.length - (formatArgumentIndex + 1); + int argumentCount = arguments.length - (formatArgumentIndex); final FormatDecode.Validator[] validators; try { validators = FormatDecode.decode(value, argumentCount); @@ -156,20 +158,36 @@ public class MalformedFormatStringInspectionBase extends BaseInspection { registerError(formatArgument, e); return; } - if (validators.length != argumentCount) { - if (argumentCount == 1) { - final PsiExpression argument = arguments[formatArgumentIndex + 1]; - final PsiType argumentType = argument.getType(); - if (argumentType instanceof PsiArrayType) { + if (argumentCount == 1) { + final PsiExpression argument = resolveIfPossible(arguments[formatArgumentIndex]); + final PsiType argumentType = argument.getType(); + if (argumentType instanceof PsiArrayType) { + final PsiArrayInitializerExpression arrayInitializer; + if (argument instanceof PsiNewExpression) { + final PsiNewExpression newExpression = (PsiNewExpression)argument; + arrayInitializer = newExpression.getArrayInitializer(); + } + else if (argument instanceof PsiArrayInitializerExpression) { + arrayInitializer = (PsiArrayInitializerExpression)argument; + } + else { return; } + if (arrayInitializer == null) { + return; + } + arguments = arrayInitializer.getInitializers(); + argumentCount = arguments.length; + formatArgumentIndex = 0; } + } + if (validators.length != argumentCount) { registerMethodCallError(expression, validators, Integer.valueOf(argumentCount)); return; } for (int i = 0; i < validators.length; i++) { final FormatDecode.Validator validator = validators[i]; - final PsiExpression argument = arguments[i + formatArgumentIndex + 1]; + final PsiExpression argument = arguments[i + formatArgumentIndex]; final PsiType argumentType = argument.getType(); if (argumentType == null) { continue; @@ -179,5 +197,21 @@ public class MalformedFormatStringInspectionBase extends BaseInspection { } } } + + private PsiExpression resolveIfPossible(PsiExpression expression) { + expression = ParenthesesUtils.stripParentheses(expression); + if (expression instanceof PsiReferenceExpression) { + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression; + final PsiElement target = referenceExpression.resolve(); + if (target instanceof PsiVariable && target.getContainingFile() == expression.getContainingFile()) { + final PsiVariable variable = (PsiVariable)target; + final PsiExpression initializer = variable.getInitializer(); + if (initializer != null) { + return initializer; + } + } + } + return expression; + } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java index 383176e969b8..ee50bbfe8df2 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java @@ -124,6 +124,16 @@ public class MalformedFormatString { public String highlightBothArguments() { return String.format("count 1: %f, count 2: %f", count1, count2); } + + void arrayArguments() { + String.format("%c", new Object[]{'a'}); + String.format("%c", new Object[]{'a', 'b'}); + String.format("%c %c", new Object[]{'a'}); + Object[] array = new Object[]{"the void"}; + String.format("%#s", array); + Object[] array2 = {"the void"}; + String.format("%#s", array2); + } } class A { void m(Formattable f) {