Commit 4aaca7aa authored by Roman's avatar Roman
Browse files

create quickfix for EnumMap type migration

parent 18b8b734
Branches unavailable Tags unavailable
No related merge requests found
Showing with 139 additions and 3 deletions
+139 -3
......@@ -1041,6 +1041,8 @@ field.may.be.static.problem.descriptor=Field <code>#ref</code> may be 'static' #
method.may.be.static.problem.descriptor=Method <code>#ref()</code> may be 'static' #loc
class.initializer.may.be.static.problem.descriptor=Class initializer may be 'static' #loc
map.replaceable.by.enum.map.problem.descriptor=<code>#ref</code> replaceable with 'EnumMap' #loc
map.replaceable.by.enum.map.fix.name=Replace with 'EnumMap'
map.replaceable.by.enum.map.fix.family=Replace with 'EnumMap'
set.replaceable.by.enum.set.problem.descriptor=<code>#ref</code> replaceable with 'EnumSet' #loc
inner.class.may.be.static.problem.descriptor=Inner class <code>#ref</code> may be 'static' #loc
string.buffer.must.have.initial.capacity.problem.descriptor=<code>new #ref()</code> without initial capacity #loc
......
......@@ -82,7 +82,7 @@ abstract class CollectionReplaceableByEnumCollectionVisitor extends BaseInspecti
!isReplaceableType((PsiClassType)expectedType)) {
return;
}
registerNewExpressionError(expression);
registerNewExpressionError(expression, expression);
}
private boolean isReplaceableType(PsiClassType classType) {
......
......@@ -15,16 +15,27 @@
*/
package com.siyeh.ig.performance;
import com.intellij.psi.CommonClassNames;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.search.ProjectScope;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static com.intellij.util.ObjectUtils.tryCast;
public class MapReplaceableByEnumMapInspection extends BaseInspection {
@Override
......@@ -39,11 +50,70 @@ public class MapReplaceableByEnumMapInspection extends BaseInspection {
return InspectionGadgetsBundle.message("map.replaceable.by.enum.map.problem.descriptor");
}
@Nullable
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
PsiNewExpression newExpression = (PsiNewExpression)infos[0];
PsiLocalVariable localVariable = tryCast(newExpression.getParent(), PsiLocalVariable.class);
if (localVariable != null) {
PsiType type = localVariable.getType();
PsiClassReferenceType referenceType = tryCast(type, PsiClassReferenceType.class);
if (referenceType == null) return null;
PsiClass aClass = referenceType.resolve();
if(aClass == null) return null;
String qualifiedName = aClass.getQualifiedName();
if(qualifiedName == null) return null;
if (!qualifiedName.equals(CommonClassNames.JAVA_UTIL_MAP)) return null;
// Needed to perform type migration otherwise
}
return new ReplaceWithEnumMapFix();
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new MapReplaceableByEnumMapVisitor();
}
private static class ReplaceWithEnumMapFix extends InspectionGadgetsFix {
@Nls
@NotNull
@Override
public String getName() {
return InspectionGadgetsBundle.message("map.replaceable.by.enum.map.fix.name");
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return InspectionGadgetsBundle.message("map.replaceable.by.enum.map.fix.family");
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) {
PsiJavaCodeReferenceElement codeReferenceElement = tryCast(descriptor.getStartElement(), PsiJavaCodeReferenceElement.class);
if (codeReferenceElement == null) return;
PsiNewExpression newExpression = tryCast(codeReferenceElement.getParent(), PsiNewExpression.class);
if (newExpression == null) return;
PsiExpressionList argumentList = newExpression.getArgumentList();
if (argumentList == null) return;
PsiElement[] children = argumentList.getChildren();
if (children.length == 0) return;
PsiElement referenceNameElement = codeReferenceElement.getReferenceNameElement();
if (referenceNameElement == null) return;
PsiClassReferenceType referenceType = tryCast(newExpression.getType(), PsiClassReferenceType.class);
if (referenceType == null) return;
PsiType[] parameters = referenceType.getParameters();
if (parameters.length != 2) return;
String enumParameterText = parameters[0].getCanonicalText();
String valueParameterText = parameters[1].getCanonicalText();
String replacementText = "new java.util.EnumMap<" + enumParameterText + "," + valueParameterText + ">(" + enumParameterText + ".class)";
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
PsiElement result = newExpression.replace(factory.createExpressionFromText(replacementText, newExpression));
CodeStyleManager.getInstance(project).reformat(JavaCodeStyleManager.getInstance(project).shortenClassReferences(result));
}
}
private static class MapReplaceableByEnumMapVisitor extends CollectionReplaceableByEnumCollectionVisitor {
@Override
......@@ -56,7 +126,7 @@ public class MapReplaceableByEnumMapInspection extends BaseInspection {
@NotNull
@Override
protected List<String> getReplaceableCollectionNames() {
return Collections.singletonList(CommonClassNames.JAVA_UTIL_HASH_MAP);
return Arrays.asList(CommonClassNames.JAVA_UTIL_HASH_MAP, CommonClassNames.JAVA_UTIL_MAP);
}
@Override
......
// Copyright 2000-2017 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.igtest.performance.map_replaceable_by_enum_map;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.SortedMap;
public class MapReplaceableByEnumMap {
enum MyEnum {
A, B, C
}
public static void main(String[] args) {
final Map<MyEnum, Object> myEnums = new java.util.EnumMap<MyEnum, Object>(MyEnum.class);
}
}
// Copyright 2000-2017 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.igtest.performance.map_replaceable_by_enum_map;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.SortedMap;
public class MapReplaceableByEnumMap {
enum MyEnum {
A, B, C
}
public static void main(String[] args) {
final Map<MyEnum, Object> myEnums = new Has<caret>hMap<> ();
}
}
// Copyright 2000-2017 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.performance;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.IGQuickFixesTestCase;
/**
* @author Bas Leijdekkers
*/
public class MapReplaceableByEnumMapFixTest extends IGQuickFixesTestCase {
public void testMapReplaceableByEnumMapFix() {
doTest(InspectionGadgetsBundle.message("map.replaceable.by.enum.map.fix.name"));
}
@Override
protected String getRelativePath() {
return "performance/map_replaceable_by_enum_map";
}
@Override
protected BaseInspection getInspection() {
return new MapReplaceableByEnumMapInspection();
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment