Skip to content

Commit

Permalink
issue #24: Remove redundant modifiers from fields within inner classes
Browse files Browse the repository at this point in the history
  • Loading branch information
markiewb committed Dec 7, 2013
1 parent d503322 commit b25ab47
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 5 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@
<h3>1.2.0:</h3>
<ul>
<li>[<a href="https://github.com/markiewb/nb-additional-hints/pull/22">New Hint</a>]: Change the modifier of a class/method/field to public/package protected/protected/private (by <a href="https://github.com/rasa-silva">rasa-silva</a>)</li>
<li>[<a href="https://github.com/markiewb/nb-additional-hints/issues/24">New Hint</a>]: Remove public/abstract/final modifiers from field declarations within interfaces</li>
</ul>

<h3>1.1.0:</h3>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*
* "Portions Copyrighted 2013 Benno Markiewicz"
*/
package de.markiewb.netbeans.plugins.hints.structure;

import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import de.markiewb.netbeans.plugins.hints.common.StringUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Modifier;
import org.netbeans.api.java.source.TreeMaker;
import org.netbeans.api.java.source.TreePathHandle;
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.spi.editor.hints.ErrorDescription;
import org.netbeans.spi.editor.hints.Fix;
import org.netbeans.spi.editor.hints.Severity;
import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
import org.netbeans.spi.java.hints.Hint;
import org.netbeans.spi.java.hints.HintContext;
import org.netbeans.spi.java.hints.JavaFix;
import org.netbeans.spi.java.hints.TriggerTreeKind;
import org.openide.util.NbBundle;

/**
* Removes superfluous modifiers (public, abstract, final) from field declarations within interfaces.
*
* @author markiewb
*/
@NbBundle.Messages({
"# {0} - modifiers ",
"# {1} - number of modifiers",
"ERR_RemoveModsFromFieldParam=Remove {0} {1,choice,0#modifiers|1#modifier|1<modifiers}",
"ERR_RemoveModsFromField=Remove public/abstract/final modifiers",
"DN_RemoveModsFromField=Remove public/abstract/final modifiers from field declarations within interfaces",
"DESC_RemoveModsFromField=Remove public/abstract/final modifiers from field declarations within interfaces. <p>Provided by <a href=\"https://github.com/markiewb/nb-additional-hints\">nb-additional-hints</a> plugin</p>",})
public class RemoveFieldModsFromIntf {

@Hint(displayName = "#DN_RemoveModsFromField", description = "#DESC_RemoveModsFromField", category = "suggestions", hintKind = Hint.Kind.INSPECTION, severity = Severity.HINT)
@TriggerTreeKind(Tree.Kind.VARIABLE)
public static ErrorDescription convert(HintContext ctx) {

TreePath path = ctx.getPath();

if (path.getLeaf().getKind() != Tree.Kind.VARIABLE) {
return null;
}
if (path.getParentPath().getLeaf().getKind() != Tree.Kind.INTERFACE) {
return null;
}

ModifiersTree modifiers = ((VariableTree) path.getLeaf()).getModifiers();

Set<Modifier> toBeRemoved = new HashSet<Modifier>();
final Set<Modifier> flags = modifiers.getFlags();
if (flags.contains(Modifier.PUBLIC)) {
toBeRemoved.add(Modifier.PUBLIC);
}
if (flags.contains(Modifier.STATIC)) {
toBeRemoved.add(Modifier.STATIC);
}
if (flags.contains(Modifier.FINAL)) {
toBeRemoved.add(Modifier.FINAL);
}
Fix fix;
if (!toBeRemoved.isEmpty()) {
fix = new RemoveFieldModsFromIntfFix(TreePathHandle.create(ctx.getPath(), ctx.getInfo()), toBeRemoved).toEditorFix();
return ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), Bundle.ERR_RemoveModsFromField(), fix);
} else {
return null;
}
}

}

class RemoveFieldModsFromIntfFix extends JavaFix {

private final Set<Modifier> modifiers;

RemoveFieldModsFromIntfFix(TreePathHandle handle, Set<Modifier> modifiers) {
super(handle);
this.modifiers = modifiers;
}

@Override
protected String getText() {
List<String> list = new ArrayList<String>();
for (Modifier modifier : modifiers) {
list.add(modifier.toString());
}

return Bundle.ERR_RemoveModsFromFieldParam(StringUtils.join(list, ", "), modifiers.size());
}

@Override
protected void performRewrite(JavaFix.TransformationContext ctx) throws Exception {
TreePath path = ctx.getPath();

WorkingCopy copy = ctx.getWorkingCopy();
TreeMaker make = ctx.getWorkingCopy().getTreeMaker();
ModifiersTree oldModifiersTree = ((VariableTree) path.getLeaf()).getModifiers();

ModifiersTree newModifiersTree = oldModifiersTree;
for (Modifier modifier : modifiers) {
newModifiersTree = make.removeModifiersModifier(newModifiersTree, modifier);
}

copy.rewrite(oldModifiersTree, newModifiersTree);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,146 @@ public void testMatchInterfaces_abstract() throws Exception {

}

@Test
public void testMatchFields_publicstaticfinal() throws Exception {
HintTest.create()
.input(
"package example;\n"
+ "public interface Test {\n"
+ " public static final String FOO=\"XXX\";\n"
+ "}"
)
.run(RemoveFieldModsFromIntf.class)
.findWarning("2:4-2:41:hint:" + Bundle.ERR_RemoveModsFromField())
.applyFix()
.assertCompilable()
.assertOutput("package example;\n"
+ "public interface Test {\n"
+ " String FOO=\"XXX\";\n"
+ "}");

}

@Test
public void testMatchFields_publicstatic() throws Exception {
HintTest.create()
.input(
"package example;\n"
+ "public interface Test {\n"
+ " public static String FOO=\"XXX\";\n"
+ "}"
)
.run(RemoveFieldModsFromIntf.class)
.findWarning("2:4-2:35:hint:" + Bundle.ERR_RemoveModsFromField())
.applyFix()
.assertCompilable()
.assertOutput("package example;\n"
+ "public interface Test {\n"
+ " String FOO=\"XXX\";\n"
+ "}");

}

@Test
public void testMatchFields_publicfinal() throws Exception {
HintTest.create()
.input(
"package example;\n"
+ "public interface Test {\n"
+ " public final String FOO=\"XXX\";\n"
+ "}"
)
.run(RemoveFieldModsFromIntf.class)
.findWarning("2:4-2:34:hint:" + Bundle.ERR_RemoveModsFromField())
.applyFix()
.assertCompilable()
.assertOutput("package example;\n"
+ "public interface Test {\n"
+ " String FOO=\"XXX\";\n"
+ "}");

}

@Test
public void testMatchFields_staticfinal() throws Exception {
HintTest.create()
.input(
"package example;\n"
+ "public interface Test {\n"
+ " static final String FOO=\"XXX\";\n"
+ "}"
)
.run(RemoveFieldModsFromIntf.class)
.findWarning("2:4-2:34:hint:" + Bundle.ERR_RemoveModsFromField())
.applyFix()
.assertCompilable()
.assertOutput("package example;\n"
+ "public interface Test {\n"
+ " String FOO=\"XXX\";\n"
+ "}");

}

@Test
public void testMatchFields_static() throws Exception {
HintTest.create()
.input(
"package example;\n"
+ "public interface Test {\n"
+ " static String FOO=\"XXX\";\n"
+ "}"
)
.run(RemoveFieldModsFromIntf.class)
.findWarning("2:4-2:28:hint:" + Bundle.ERR_RemoveModsFromField())
.applyFix()
.assertCompilable()
.assertOutput("package example;\n"
+ "public interface Test {\n"
+ " String FOO=\"XXX\";\n"
+ "}");

}

@Test
public void testMatchFields_public() throws Exception {
HintTest.create()
.input(
"package example;\n"
+ "public interface Test {\n"
+ " public String FOO=\"XXX\";\n"
+ "}"
)
.run(RemoveFieldModsFromIntf.class)
.findWarning("2:4-2:28:hint:" + Bundle.ERR_RemoveModsFromField())
.applyFix()
.assertCompilable()
.assertOutput("package example;\n"
+ "public interface Test {\n"
+ " String FOO=\"XXX\";\n"
+ "}");

}

@Test
public void testMatchFields_final() throws Exception {
HintTest.create()
.input(
"package example;\n"
+ "public interface Test {\n"
+ " final String FOO=\"XXX\";\n"
+ "}"
)
.run(RemoveFieldModsFromIntf.class)
.findWarning("2:4-2:27:hint:" + Bundle.ERR_RemoveModsFromField())
.applyFix()
.assertCompilable()
.assertOutput("package example;\n"
+ "public interface Test {\n"
+ " String FOO=\"XXX\";\n"
+ "}");

}

@Test
public void testMatchInterfaces_public() throws Exception {
HintTest.create()
Expand Down Expand Up @@ -84,7 +224,7 @@ public void testMatchInterfaces_public_abstract() throws Exception {
+ "}");

}

@Test
public void testShouldNotMatchClasses_public_abstract() throws Exception {
HintTest.create()
Expand All @@ -98,6 +238,7 @@ public void testShouldNotMatchClasses_public_abstract() throws Exception {
.assertWarnings();

}

@Test
public void testShouldNotMatchClasses_abstract_public() throws Exception {
HintTest.create()
Expand All @@ -111,6 +252,7 @@ public void testShouldNotMatchClasses_abstract_public() throws Exception {
.assertWarnings();

}

@Test
public void testShouldNotMatchClasses_public() throws Exception {
HintTest.create()
Expand All @@ -124,6 +266,7 @@ public void testShouldNotMatchClasses_public() throws Exception {
.assertWarnings();

}

@Test
public void testShouldNotMatchClasses_abstract() throws Exception {
HintTest.create()
Expand Down
13 changes: 9 additions & 4 deletions src/test/java/example/IFoo.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

public interface IFoo {

/**
*
*/
public static final String _publicstaticfinal = "XXX";
public static String _publicstatic = "XXX";
public final String _publicfinal = "XXX";
public String _public = "XXX";
static final String _staticfinal = "XXX";
static String _static = "XXX";
final String _final = "XXX";

public abstract void getFooA();

public void getFooB();

abstract void getFooC();

void getFooD();
}

0 comments on commit b25ab47

Please sign in to comment.