diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java index 5aa125b330fc..255d695d201e 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2018 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2019 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. @@ -18,59 +18,107 @@ package com.siyeh.ig.fixes; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.JavaSharedImplUtil; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.InspectionGadgetsFix; +import com.siyeh.ig.psiutils.DeclarationSearchUtils; import org.jetbrains.annotations.NotNull; public class NormalizeDeclarationFix extends InspectionGadgetsFix { + private final boolean myCStyleDeclaration; + + public NormalizeDeclarationFix(boolean cStyleDeclaration) { + myCStyleDeclaration = cStyleDeclaration; + } + @Override @NotNull public String getFamilyName() { - return InspectionGadgetsBundle.message("normalize.declaration.quickfix"); + return myCStyleDeclaration + ? InspectionGadgetsBundle.message("c.style.array.declaration.replace.quickfix") + : InspectionGadgetsBundle.message("normalize.declaration.quickfix"); } @Override public void doFix(Project project, ProblemDescriptor descriptor) { - final PsiElement variableNameElement = descriptor.getPsiElement(); - final PsiVariable parent = - (PsiVariable)variableNameElement.getParent(); - if (parent == null) { - return; + PsiElement element = descriptor.getPsiElement(); + if (!(element instanceof PsiVariable) && !(element instanceof PsiMethod)) { + element = element.getParent(); } - if (parent instanceof PsiField) { - parent.normalizeDeclaration(); - return; + if (element instanceof PsiLocalVariable) { + final PsiElement parent = element.getParent(); + if (!(parent instanceof PsiDeclarationStatement)) { + return; + } + PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)parent; + final PsiElement grandParent = parent.getParent(); + if (grandParent instanceof PsiForStatement) { + splitMultipleDeclarationInForStatementInitialization(declarationStatement); + return; + } + final PsiElement[] elements = declarationStatement.getDeclaredElements(); + final PsiVariable variable = (PsiVariable)elements[0]; + variable.normalizeDeclaration(); + for (int i = 1; i < elements.length; i++) { + declarationStatement = PsiTreeUtil.getNextSiblingOfType(declarationStatement, PsiDeclarationStatement.class); + assert declarationStatement != null; + JavaSharedImplUtil.normalizeBrackets((PsiVariable)declarationStatement.getDeclaredElements()[0]); + } } - final PsiElement grandParent = parent.getParent(); - if (!(grandParent instanceof PsiDeclarationStatement)) { - return; + else if (element instanceof PsiField) { + PsiField field = DeclarationSearchUtils.findFirstFieldInDeclaration((PsiField)element); + PsiField nextField = field; + int count = 0; + while (nextField != null) { + count++; + nextField = DeclarationSearchUtils.findNextFieldInDeclaration(nextField); + } + field.normalizeDeclaration(); + for (int i = 1; i < count; i++) { + field = PsiTreeUtil.getNextSiblingOfType(field, PsiField.class); + assert field != null; + JavaSharedImplUtil.normalizeBrackets(field); + } } - final PsiElement greatGrandParent = grandParent.getParent(); - if (greatGrandParent instanceof PsiForStatement) { - final PsiDeclarationStatement declarationStatement = - (PsiDeclarationStatement)grandParent; - splitMultipleDeclarationInForStatementInitialization( - declarationStatement); - return; + else if (element instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)element; + final PsiTypeElement returnTypeElement = method.getReturnTypeElement(); + if (returnTypeElement == null) { + return; + } + final PsiType returnType = method.getReturnType(); + if (returnType == null) { + return; + } + PsiElement child = method.getParameterList(); + while (!(child instanceof PsiCodeBlock)) { + final PsiElement elementToDelete = child; + child = child.getNextSibling(); + if (elementToDelete instanceof PsiJavaToken) { + final IElementType tokenType = ((PsiJavaToken)elementToDelete).getTokenType(); + if (JavaTokenType.LBRACKET.equals(tokenType) || JavaTokenType.RBRACKET.equals(tokenType)) { + elementToDelete.delete(); + } + } + } + final PsiTypeElement typeElement = JavaPsiFacade.getElementFactory(project).createTypeElement(returnType); + returnTypeElement.replace(typeElement); } - parent.normalizeDeclaration(); } - private static void splitMultipleDeclarationInForStatementInitialization( - PsiDeclarationStatement declarationStatement) { + private static void splitMultipleDeclarationInForStatementInitialization(PsiDeclarationStatement declarationStatement) { final PsiElement forStatement = declarationStatement.getParent(); - final PsiElement[] declaredElements = - declarationStatement.getDeclaredElements(); + final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); final Project project = forStatement.getProject(); - final PsiElementFactory factory = - JavaPsiFacade.getElementFactory(project); + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); final PsiElement greatGreatGrandParent = forStatement.getParent(); final PsiBlockStatement blockStatement; final PsiCodeBlock codeBlock; if (!(greatGreatGrandParent instanceof PsiCodeBlock)) { - blockStatement = (PsiBlockStatement) - factory.createStatementFromText("{}", forStatement); + blockStatement = (PsiBlockStatement)factory.createStatementFromText("{}", forStatement); codeBlock = blockStatement.getCodeBlock(); } else { @@ -85,19 +133,14 @@ public class NormalizeDeclarationFix extends InspectionGadgetsFix { final PsiVariable variable = (PsiVariable)declaredElement; final PsiType type = variable.getType(); final String typeText = type.getCanonicalText(); - final StringBuilder newStatementText = - new StringBuilder(typeText); - newStatementText.append(' '); - newStatementText.append(variable.getName()); + final StringBuilder newStatementText = new StringBuilder(typeText); + newStatementText.append(' ').append(variable.getName()); final PsiExpression initializer = variable.getInitializer(); if (initializer != null) { - newStatementText.append('='); - newStatementText.append(initializer.getText()); + newStatementText.append('=').append(initializer.getText()); } newStatementText.append(';'); - final PsiStatement newStatement = - factory.createStatementFromText( - newStatementText.toString(), forStatement); + final PsiStatement newStatement = factory.createStatementFromText(newStatementText.toString(), forStatement); if (codeBlock == null) { greatGreatGrandParent.addBefore(newStatement, forStatement); } @@ -105,12 +148,17 @@ public class NormalizeDeclarationFix extends InspectionGadgetsFix { codeBlock.add(newStatement); } } - for (int i = 1; i < declaredElements.length; i++) { + for (int i = 0; i < declaredElements.length; i++) { final PsiElement declaredElement = declaredElements[i]; if (!(declaredElement instanceof PsiVariable)) { continue; } - declaredElement.delete(); + if (i == 0) { + ((PsiVariable)declaredElement).normalizeDeclaration(); + } + else { + declaredElement.delete(); + } } if (codeBlock != null) { codeBlock.add(forStatement); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DeclarationSearchUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DeclarationSearchUtils.java index 62735bef3cdd..a467056f59fb 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DeclarationSearchUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DeclarationSearchUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2017 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2019 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. @@ -30,16 +30,12 @@ public class DeclarationSearchUtils { private DeclarationSearchUtils() {} - public static boolean variableNameResolvesToTarget( - @NotNull String variableName, @NotNull PsiVariable target, - @NotNull PsiElement context) { - + public static boolean variableNameResolvesToTarget(@NotNull String variableName, @NotNull PsiVariable target, + @NotNull PsiElement context) { final Project project = context.getProject(); final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final PsiResolveHelper resolveHelper = psiFacade.getResolveHelper(); - final PsiVariable variable = - resolveHelper.resolveAccessibleReferencedVariable( - variableName, context); + final PsiVariable variable = resolveHelper.resolveAccessibleReferencedVariable(variableName, context); return target.equals(variable); } @@ -98,4 +94,15 @@ public class DeclarationSearchUtils { } return cost == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES; } + + public static PsiField findFirstFieldInDeclaration(PsiField field) { + final PsiTypeElement typeElement = field.getTypeElement(); + if (typeElement == null) return field; // e.g. enum constant + return (PsiField)typeElement.getParent(); + } + + public static PsiField findNextFieldInDeclaration(PsiField field) { + final PsiField nextField = PsiTreeUtil.getNextSiblingOfType(field, PsiField.class); + return nextField != null && field.getTypeElement() == nextField.getTypeElement() ? nextField : null; + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CStyleArrayDeclarationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CStyleArrayDeclarationInspection.java index 67774db788f9..f7e8c90f8834 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CStyleArrayDeclarationInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CStyleArrayDeclarationInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2018 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2019 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. @@ -16,16 +16,15 @@ package com.siyeh.ig.style; import com.intellij.codeInspection.CleanupLocalInspectionTool; -import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; -import com.intellij.openapi.project.Project; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.tree.IElementType; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; +import com.siyeh.ig.fixes.NormalizeDeclarationFix; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -61,53 +60,7 @@ public class CStyleArrayDeclarationInspection extends BaseInspection implements @Override public InspectionGadgetsFix buildFix(Object... infos) { - return new CStyleArrayDeclarationFix(); - } - - private static class CStyleArrayDeclarationFix - extends InspectionGadgetsFix { - - @Override - @NotNull - public String getFamilyName() { - return InspectionGadgetsBundle.message( - "c.style.array.declaration.replace.quickfix"); - } - - @Override - public void doFix(Project project, ProblemDescriptor descriptor) { - final PsiElement element = descriptor.getPsiElement().getParent(); - if (element instanceof PsiVariable) { - final PsiVariable variable = (PsiVariable)element; - variable.normalizeDeclaration(); - CodeStyleManager.getInstance(project).reformat(variable); - } - else if (element instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)element; - final PsiTypeElement returnTypeElement = method.getReturnTypeElement(); - if (returnTypeElement == null) { - return; - } - final PsiType returnType = method.getReturnType(); - if (returnType == null) { - return; - } - PsiElement child = method.getParameterList(); - while (!(child instanceof PsiCodeBlock)) { - final PsiElement element1 = child; - child = child.getNextSibling(); - if (element1 instanceof PsiJavaToken) { - final PsiJavaToken token = (PsiJavaToken)element1; - final IElementType tokenType = token.getTokenType(); - if (JavaTokenType.LBRACKET.equals(tokenType) || JavaTokenType.RBRACKET.equals(tokenType)) { - token.delete(); - } - } - } - final PsiTypeElement typeElement = JavaPsiFacade.getElementFactory(project).createTypeElement(returnType); - returnTypeElement.replace(typeElement); - } - } + return new NormalizeDeclarationFix(true); } @Override @@ -135,7 +88,12 @@ public class CStyleArrayDeclarationInspection extends BaseInspection implements if (elementType.equals(declaredType)) { return; } - registerVariableError(variable, variable); + if (InspectionProjectProfileManager.isInformationLevel(getShortName(), variable)) { + registerError(variable, variable); + } + else { + registerVariableError(variable, variable); + } } @Override @@ -153,6 +111,24 @@ public class CStyleArrayDeclarationInspection extends BaseInspection implements if (type.equals(returnType)) { return; } + if (InspectionProjectProfileManager.isInformationLevel(getShortName(), method)) { + registerError(typeElement, method); + PsiElement child = method.getParameterList(); + PsiJavaToken first = null; + PsiJavaToken last = null; + while (!(child instanceof PsiCodeBlock)) { + if (child instanceof PsiJavaToken) { + PsiJavaToken token = (PsiJavaToken)child; + final IElementType tokenType = token.getTokenType(); + if (JavaTokenType.LBRACKET.equals(tokenType) || JavaTokenType.RBRACKET.equals(tokenType)) { + if (first == null) first = token; + last = token; + } + } + child = child.getNextSibling(); + } + if (first != null) registerErrorAtRange(first, last, method); + } registerMethodError(method, method); } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/FieldWithWhitespace.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/FieldWithWhitespace.after.java index 3a3984b1a64c..7cf4b9af7c52 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/FieldWithWhitespace.after.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/FieldWithWhitespace.after.java @@ -1,4 +1,4 @@ class FieldWithWhitespace { - String[] s; + String[] s; } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/InForLoop.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/InForLoop.after.java new file mode 100644 index 000000000000..7507fc01f1d6 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/InForLoop.after.java @@ -0,0 +1,7 @@ +class InForLoop { + void x(int i) { + if (true) { + int[] is = {}; + for (int[] ii = {0}; i < 10; i++) {} + } +}} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/InForLoop.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/InForLoop.java new file mode 100644 index 000000000000..6362ef6ddbf9 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/InForLoop.java @@ -0,0 +1,4 @@ +class InForLoop { + void x(int i) { + if (true) for (int ii[] = {0}, is[] = {}; i < 10; i++) {} +}} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleFieldsSingleDeclaration.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleFieldsSingleDeclaration.after.java new file mode 100644 index 000000000000..bd82048fa81b --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleFieldsSingleDeclaration.after.java @@ -0,0 +1,6 @@ +class X { + + int[] array; + int[][] array2; + int[][][] array3; +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleFieldsSingleDeclaration.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleFieldsSingleDeclaration.java new file mode 100644 index 000000000000..5c3f6ccbd10a --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleFieldsSingleDeclaration.java @@ -0,0 +1,4 @@ +class X { + + int[] array, array2[], array3[][]; +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleVariablesSingleDeclaration.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleVariablesSingleDeclaration.after.java new file mode 100644 index 000000000000..eee157335b0b --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleVariablesSingleDeclaration.after.java @@ -0,0 +1,6 @@ +class X {{ + + int[] array; + int[][] array2; + int[][][] array3; +}} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleVariablesSingleDeclaration.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleVariablesSingleDeclaration.java new file mode 100644 index 000000000000..395e7310f186 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/MultipleVariablesSingleDeclaration.java @@ -0,0 +1,4 @@ +class X {{ + + int[] array, array2[], array3[][]; +}} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/SimpleMethod.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/SimpleMethod.after.java index 0b918a955215..204fc138309e 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/SimpleMethod.after.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/SimpleMethod.after.java @@ -1,6 +1,6 @@ public class SimpleMethod { - public String[] ohGod(String[] a) { + public String[]/*2*/ ohGod(String[] a)/*1*/ { return a; } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/SimpleMethod.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/SimpleMethod.java index 22519cadc06f..9f5a4c45e799 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/SimpleMethod.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/cstyle_array_declaration/SimpleMethod.java @@ -1,6 +1,6 @@ public class SimpleMethod { - public String ohGod(String[] a)[] { + public String/*2*/ ohGod(String[] a)/*1*/[] { return a; } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/CStyleArrayDeclarationFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/CStyleArrayDeclarationFixTest.java index 85a07f8e08c3..72fa939a41b5 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/CStyleArrayDeclarationFixTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/CStyleArrayDeclarationFixTest.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2014 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 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.siyeh.ig.fixes.style; import com.siyeh.InspectionGadgetsBundle; @@ -26,6 +12,9 @@ public class CStyleArrayDeclarationFixTest extends IGQuickFixesTestCase { public void testSimpleMethod() { doTest(); } public void testFieldWithWhitespace() { doTest(); } + public void testInForLoop() { doTest(); } + public void testMultipleVariablesSingleDeclaration() { doTest(); } + public void testMultipleFieldsSingleDeclaration() { doTest(); } @Override public void setUp() throws Exception {