2525import com .siyeh .ig .psiutils .ExpressionUtils ;
2626import com .siyeh .localize .InspectionGadgetsLocalize ;
2727import consulo .annotation .component .ExtensionImpl ;
28+ import consulo .localize .LocalizeValue ;
2829import jakarta .annotation .Nonnull ;
2930
3031@ ExtensionImpl
3132public class MalformedFormatStringInspection extends BaseInspection {
32-
33- @ Override
34- @ Nonnull
35- public String getDisplayName () {
36- return InspectionGadgetsLocalize .malformedFormatStringDisplayName ().get ();
37- }
38-
39- @ Override
40- @ Nonnull
41- public String buildErrorString (Object ... infos ) {
42- final Object value = infos [0 ];
43- if (value instanceof Exception ) {
44- return InspectionGadgetsLocalize .malformedFormatStringProblemDescriptorMalformed ().get ();
45- }
46- final Validator [] validators = (Validator [])value ;
47- final int argumentCount = ((Integer )infos [1 ]).intValue ();
48- if (validators .length < argumentCount ) {
49- return InspectionGadgetsBundle .message ("malformed.format.string.problem.descriptor.too.many.arguments" );
33+ @ Nonnull
34+ @ Override
35+ public LocalizeValue getDisplayName () {
36+ return InspectionGadgetsLocalize .malformedFormatStringDisplayName ();
5037 }
51- if (validators .length > argumentCount ) {
52- return InspectionGadgetsBundle .message ("malformed.format.string.problem.descriptor.too.few.arguments" );
38+
39+ @ Override
40+ @ Nonnull
41+ public String buildErrorString (Object ... infos ) {
42+ final Object value = infos [0 ];
43+ if (value instanceof Exception ) {
44+ return InspectionGadgetsLocalize .malformedFormatStringProblemDescriptorMalformed ().get ();
45+ }
46+ final Validator [] validators = (Validator []) value ;
47+ final int argumentCount = ((Integer ) infos [1 ]).intValue ();
48+ if (validators .length < argumentCount ) {
49+ return InspectionGadgetsBundle .message ("malformed.format.string.problem.descriptor.too.many.arguments" );
50+ }
51+ if (validators .length > argumentCount ) {
52+ return InspectionGadgetsBundle .message ("malformed.format.string.problem.descriptor.too.few.arguments" );
53+ }
54+ return InspectionGadgetsBundle .message ("malformed.format.string.problem.descriptor.arguments.do.not.match.type" );
5355 }
54- return InspectionGadgetsBundle .message ("malformed.format.string.problem.descriptor.arguments.do.not.match.type" );
55- }
5656
57- @ Override
58- public boolean isEnabledByDefault () {
59- return true ;
60- }
57+ @ Override
58+ public boolean isEnabledByDefault () {
59+ return true ;
60+ }
6161
62- @ Override
63- public BaseInspectionVisitor buildVisitor () {
64- return new MalformedFormatStringVisitor ();
65- }
62+ @ Override
63+ public BaseInspectionVisitor buildVisitor () {
64+ return new MalformedFormatStringVisitor ();
65+ }
6666
67- private static class MalformedFormatStringVisitor extends BaseInspectionVisitor {
67+ private static class MalformedFormatStringVisitor extends BaseInspectionVisitor {
6868
69- @ Override
70- public void visitMethodCallExpression (@ Nonnull PsiMethodCallExpression expression ) {
71- super .visitMethodCallExpression (expression );
72- if (!FormatUtils .isFormatCall (expression )) {
73- return ;
74- }
75- final PsiExpressionList argumentList = expression .getArgumentList ();
76- final PsiExpression [] arguments = argumentList .getExpressions ();
77- if (arguments .length == 0 ) {
78- return ;
79- }
80- final PsiExpression firstArgument = arguments [0 ];
81- final PsiType type = firstArgument .getType ();
82- if (type == null ) {
83- return ;
84- }
85- final int formatArgumentIndex ;
86- if ("java.util.Locale" .equals (type .getCanonicalText ()) && arguments .length > 1 ) {
87- formatArgumentIndex = 1 ;
88- }
89- else {
90- formatArgumentIndex = 0 ;
91- }
92- final PsiExpression formatArgument = arguments [formatArgumentIndex ];
93- if (!ExpressionUtils .hasStringType (formatArgument )) {
94- return ;
95- }
96- if (!PsiUtil .isConstantExpression (formatArgument )) {
97- return ;
98- }
99- final PsiType formatType = formatArgument .getType ();
100- if (formatType == null ) {
101- return ;
102- }
103- final String value = (String )ConstantExpressionUtil .computeCastTo (formatArgument , formatType );
104- if (value == null ) {
105- return ;
106- }
107- final int argumentCount = arguments .length - (formatArgumentIndex + 1 );
108- final Validator [] validators ;
109- try {
110- validators = FormatDecode .decode (value , argumentCount );
111- }
112- catch (Exception e ) {
113- registerError (formatArgument , e );
114- return ;
115- }
116- if (validators .length != argumentCount ) {
117- if (argumentCount == 1 ) {
118- final PsiExpression argument = arguments [formatArgumentIndex + 1 ];
119- final PsiType argumentType = argument .getType ();
120- if (argumentType instanceof PsiArrayType ) {
121- return ;
122- }
123- }
124- registerError (formatArgument , validators , Integer .valueOf (argumentCount ));
125- return ;
126- }
127- for (int i = 0 ; i < validators .length ; i ++) {
128- final Validator validator = validators [i ];
129- final PsiType argumentType = arguments [i + formatArgumentIndex + 1 ].getType ();
130- if (argumentType == null ) {
131- continue ;
132- }
133- if (!validator .valid (argumentType )) {
134- registerError (formatArgument , validators , Integer .valueOf (argumentCount ));
135- return ;
69+ @ Override
70+ public void visitMethodCallExpression (@ Nonnull PsiMethodCallExpression expression ) {
71+ super .visitMethodCallExpression (expression );
72+ if (!FormatUtils .isFormatCall (expression )) {
73+ return ;
74+ }
75+ final PsiExpressionList argumentList = expression .getArgumentList ();
76+ final PsiExpression [] arguments = argumentList .getExpressions ();
77+ if (arguments .length == 0 ) {
78+ return ;
79+ }
80+ final PsiExpression firstArgument = arguments [0 ];
81+ final PsiType type = firstArgument .getType ();
82+ if (type == null ) {
83+ return ;
84+ }
85+ final int formatArgumentIndex ;
86+ if ("java.util.Locale" .equals (type .getCanonicalText ()) && arguments .length > 1 ) {
87+ formatArgumentIndex = 1 ;
88+ }
89+ else {
90+ formatArgumentIndex = 0 ;
91+ }
92+ final PsiExpression formatArgument = arguments [formatArgumentIndex ];
93+ if (!ExpressionUtils .hasStringType (formatArgument )) {
94+ return ;
95+ }
96+ if (!PsiUtil .isConstantExpression (formatArgument )) {
97+ return ;
98+ }
99+ final PsiType formatType = formatArgument .getType ();
100+ if (formatType == null ) {
101+ return ;
102+ }
103+ final String value = (String ) ConstantExpressionUtil .computeCastTo (formatArgument , formatType );
104+ if (value == null ) {
105+ return ;
106+ }
107+ final int argumentCount = arguments .length - (formatArgumentIndex + 1 );
108+ final Validator [] validators ;
109+ try {
110+ validators = FormatDecode .decode (value , argumentCount );
111+ }
112+ catch (Exception e ) {
113+ registerError (formatArgument , e );
114+ return ;
115+ }
116+ if (validators .length != argumentCount ) {
117+ if (argumentCount == 1 ) {
118+ final PsiExpression argument = arguments [formatArgumentIndex + 1 ];
119+ final PsiType argumentType = argument .getType ();
120+ if (argumentType instanceof PsiArrayType ) {
121+ return ;
122+ }
123+ }
124+ registerError (formatArgument , validators , Integer .valueOf (argumentCount ));
125+ return ;
126+ }
127+ for (int i = 0 ; i < validators .length ; i ++) {
128+ final Validator validator = validators [i ];
129+ final PsiType argumentType = arguments [i + formatArgumentIndex + 1 ].getType ();
130+ if (argumentType == null ) {
131+ continue ;
132+ }
133+ if (!validator .valid (argumentType )) {
134+ registerError (formatArgument , validators , Integer .valueOf (argumentCount ));
135+ return ;
136+ }
137+ }
136138 }
137- }
138139 }
139- }
140140}
0 commit comments