// ===================================================================== // // Copyright (C) 2012 - 2016, Philip Graf // // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // which accompanies this distribution, and is available at // http://www.eclipse.org/legal/epl-v10.html // // ===================================================================== package ch.acanda.eclipse.pmd.java.resolution.stringandstringbuffer; import static ch.acanda.eclipse.pmd.java.resolution.ASTUtil.copy; import static ch.acanda.eclipse.pmd.java.resolution.ASTUtil.replace; import static java.text.MessageFormat.format; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.Position; import ch.acanda.eclipse.pmd.java.resolution.ASTQuickFix; import ch.acanda.eclipse.pmd.java.resolution.Finders; import ch.acanda.eclipse.pmd.java.resolution.NodeFinder; import ch.acanda.eclipse.pmd.marker.PMDMarker; import ch.acanda.eclipse.pmd.ui.util.PMDPluginImages; /** * Quick fix for the rule * <a href="http://pmd.sourceforge.net/rules/java/strings.html#UnnecessaryCaseChange">UnnecessaryCaseChange</a>. It * replaces the <code>.toUpperCase().equals(...)</code> with <code>.equalsIgnoreCase(...)</code> and * <code>.toUpperCase().equalsIgnoreCase(...)</code> with <code>.equalsIgnoreCase(...)</code>. * * @author Philip Graf */ public class UnnecessaryCaseChangeQuickFix extends ASTQuickFix<MethodInvocation> { private final boolean containsEqualsIgnoreCase; public UnnecessaryCaseChangeQuickFix(final PMDMarker marker) { super(marker); final String markerText = marker.getMarkerText(); containsEqualsIgnoreCase = markerText != null && markerText.contains("equalsIgnoreCase"); } @Override protected ImageDescriptor getImageDescriptor() { return containsEqualsIgnoreCase ? PMDPluginImages.QUICKFIX_REMOVE : PMDPluginImages.QUICKFIX_CHANGE; } @Override public String getLabel() { if (containsEqualsIgnoreCase) { final String markerText = marker.getMarkerText(); if (markerText.contains("toLowerCase")) { return "Remove .toLowerCase()"; } if (markerText.contains("toUpperCase()")) { return "Remove .toUpperCase()"; } } return "Replace with .equalsIgnoreCase()"; } @Override public String getDescription() { final String markerText = marker.getMarkerText(); if (markerText != null) { String replacement = markerText; if (!containsEqualsIgnoreCase) { replacement = replacement.replaceFirst("\\.equals", ".equalsIgnoreCase"); } replacement = replacement.replaceFirst("\\.to(Upper|Lower)Case\\s*\\(\\s*\\)", ""); return format("Replaces <b>{0}</b> with <b>{1}</b>.", markerText, replacement); } return "Replaces the expression with .equalsIgnoreCase()."; } @Override protected NodeFinder<CompilationUnit, MethodInvocation> getNodeFinder(final Position position) { return Finders.positionWithinNode(position, getNodeType()); } /** * Removes the <code>.toString()</code> from <code>"foo".toString()</code> if the expression is only a part of an * statement. Removes the expression completely if it is the whole statement. */ @Override @SuppressWarnings("unchecked") protected boolean apply(final MethodInvocation node) { final AST ast = node.getAST(); final MethodInvocation invocation = ast.newMethodInvocation(); if (node.getExpression().getNodeType() == ASTNode.METHOD_INVOCATION) { invocation.setExpression(removeCaseChange((MethodInvocation) node.getExpression())); invocation.setName(ast.newSimpleName("equalsIgnoreCase")); invocation.arguments().add(copy((Expression) node.arguments().get(0))); return replace(node, invocation); } return false; } private Expression removeCaseChange(final MethodInvocation withCaseChange) { final String identifier = withCaseChange.getName().getIdentifier(); if ("toUpperCase".equals(identifier) || "toLowerCase".equals(identifier)) { return copy(withCaseChange.getExpression()); } return copy(withCaseChange); } }