Skip to content

Commit

Permalink
issue #20: Add options for 'Replace +' hint - see the checkboxes in t…
Browse files Browse the repository at this point in the history
…he hint options
  • Loading branch information
markiewb committed Apr 24, 2014
1 parent 1638d5b commit 0df8eba
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@
*/
package de.markiewb.netbeans.plugins.hints.replaceplus;

import de.markiewb.netbeans.plugins.hints.literals.joinliterals.JoinLiteralsFix;
import com.sun.source.util.TreePath;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
Expand All @@ -55,7 +53,6 @@
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.TreePathHandle;
import org.netbeans.spi.editor.hints.ErrorDescription;
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
import org.netbeans.spi.editor.hints.Fix;
import org.netbeans.spi.editor.hints.Severity;
import org.netbeans.spi.java.hints.Hint;
Expand All @@ -64,6 +61,7 @@
import com.sun.source.tree.Tree.Kind;
import de.markiewb.netbeans.plugins.hints.common.NonNullArrayList;
import de.markiewb.netbeans.plugins.hints.literals.BuildArgumentsVisitor;
import org.netbeans.spi.java.hints.BooleanOption;
import org.netbeans.spi.java.hints.HintContext;
import org.netbeans.spi.java.hints.TriggerTreeKind;
import org.openide.util.NbBundle.Messages;
Expand All @@ -90,19 +88,58 @@
+ "<li><tt>String.format(\"Found %s entries\", variable)</tt> or</li>"
+ "<li><tt>new StringBuilder().append(\"Found \").append(variable).append(\" entries\").toString()</tt></li>"
+ "</ul>"
+ "<p>Provided by <a href=\"https://github.com/markiewb/nb-additional-hints\">nb-additional-hints</a> plugin</p>"})
+ "<p>Provided by <a href=\"https://github.com/markiewb/nb-additional-hints\">nb-additional-hints</a> plugin</p>",
"OPTNAME_SupportMessageFormat=<html>support <tt>Message.format()</tt>",
"OPTDESC_SupportMessageFormat=",
"OPTNAME_SupportStringFormat=<html>support <tt>String.format()</tt>",
"OPTDESC_SupportStringFormat=",
"OPTNAME_SupportStringBuilder=<html>support <tt>StringBuilder().append()</tt>",
"OPTDESC_SupportStringBuilder="
})
public class ReplacePlusHint {

private static final boolean DEFAULT_SUPPORTMESSAGEFORMAT = true;
@BooleanOption(displayName = "#OPTNAME_SupportMessageFormat",tooltip = "#OPTDESC_SupportMessageFormat",defaultValue = DEFAULT_SUPPORTMESSAGEFORMAT)
public static final String OPTION_SUPPORTMESSAGEFORMAT = "support.messageformat";

private static final boolean DEFAULT_SUPPORTSTRINGFORMAT = true;
@BooleanOption(displayName = "#OPTNAME_SupportStringFormat",tooltip = "#OPTDESC_SupportStringFormat",defaultValue = DEFAULT_SUPPORTSTRINGFORMAT)
public static final String OPTION_SUPPORTSTRINGFORMAT = "support.stringformat";

private static final boolean DEFAULT_SUPPORTSTRINGBUILDER = true;
@BooleanOption(displayName = "#OPTNAME_SupportStringBuilder",tooltip = "#OPTDESC_SupportStringBuilder",defaultValue = DEFAULT_SUPPORTSTRINGBUILDER)
public static final String OPTION_SUPPORTSTRINGBUILDER = "support.stringbuilder";

public static final EnumSet<Kind> TREEKINDS = EnumSet.of(Kind.STRING_LITERAL, Kind.PLUS);


private HintContext ctx;

public ReplacePlusHint(HintContext ctx) {
this.ctx = ctx;
}


// @UseOptions({OPTION_SUPPORTMESSAGEFORMAT})
@TriggerTreeKind(value = {Kind.STRING_LITERAL, Kind.PLUS})
public static ErrorDescription computeHint(HintContext ctx) {
ErrorDescription run = new ReplacePlusHint().run(ctx.getInfo(), ctx.getPath());
Config config = new Config();
config.supportMessageFormat = ctx.getPreferences().getBoolean(OPTION_SUPPORTMESSAGEFORMAT, DEFAULT_SUPPORTMESSAGEFORMAT);
config.supportStringFormat = ctx.getPreferences().getBoolean(OPTION_SUPPORTSTRINGFORMAT, DEFAULT_SUPPORTSTRINGFORMAT);
config.supportStringBuilder = ctx.getPreferences().getBoolean(OPTION_SUPPORTSTRINGBUILDER, DEFAULT_SUPPORTSTRINGBUILDER);

ErrorDescription run = new ReplacePlusHint(ctx).run(config);
return run;
}
static Logger LOG = Logger.getLogger(ReplacePlusHint.class.getName());
private AtomicBoolean cancelled = new AtomicBoolean(false);

static class Config{
boolean supportMessageFormat;
boolean supportStringFormat;
boolean supportStringBuilder;
}

public void cancel() {
cancelled.set(true);
}
Expand All @@ -120,8 +157,10 @@ private static boolean checkParentKind(TreePath tp, int parentIndex, Kind requir
getKind() == requiredKind;
}

public ErrorDescription run(CompilationInfo compilationInfo, TreePath treePath) {
public ErrorDescription run(Config config) {

TreePath treePath = ctx.getPath();
CompilationInfo compilationInfo = ctx.getInfo();
try {
final DataObject od = DataObject.find(compilationInfo.getFileObject());
final Document doc = compilationInfo.getDocument();
Expand Down Expand Up @@ -160,32 +199,33 @@ public ErrorDescription run(CompilationInfo compilationInfo, TreePath treePath)
return null;
}

final long hardCodedOffset = compilationInfo.getTrees().
getSourcePositions().
getStartPosition(compilationInfo.getCompilationUnit(), treePath.getLeaf());
final long hardCodedOffsetEnd = compilationInfo.getTrees().
getSourcePositions().
getEndPosition(compilationInfo.getCompilationUnit(), treePath.getLeaf());
BuildArgumentsVisitor v = new BuildArgumentsVisitor(compilationInfo);

v.scan(treePath, null);
BuildArgumentsVisitor.Result data = v.toResult();

if (data.getArguments().isEmpty()) {
//only literals like "A"+"B" is not supported
//only literals like "A"+"B" (without variable) is not supported
return null;
}
//only join joinable terms, at least 2 terms are required
if (data.get().size() >= 2) {
List<Fix> fixes = new NonNullArrayList();
fixes.add(ReplaceWithMessageFormatFix.create(od, TreePathHandle.create(treePath, compilationInfo), data));
fixes.add(ReplaceWithStringFormatFix.create(od, TreePathHandle.create(treePath, compilationInfo), data));
fixes.add(ReplaceWithStringBuilderFix.create(od, TreePathHandle.create(treePath, compilationInfo), data));
if (config.supportMessageFormat) {
fixes.add(ReplaceWithMessageFormatFix.create(od, TreePathHandle.create(treePath, compilationInfo), data));
}
if (config.supportStringFormat) {

fixes.add(ReplaceWithStringFormatFix.create(od, TreePathHandle.create(treePath, compilationInfo), data));
}
if (config.supportStringBuilder) {

fixes.add(ReplaceWithStringBuilderFix.create(od, TreePathHandle.create(treePath, compilationInfo), data));
}
if (!fixes.isEmpty()) {
return ErrorDescriptionFactory.
createErrorDescription(Severity.HINT, Bundle.DN_ReplacePlus(), fixes, compilationInfo.
getFileObject(), (int) hardCodedOffset, (int) hardCodedOffsetEnd);
Fix[] fixs = fixes.toArray(new Fix[fixes.size()]);
return org.netbeans.spi.java.hints.ErrorDescriptionFactory.forName(ctx, treePath, Bundle.DN_ReplacePlus(), fixs);
}
}
} catch (IndexOutOfBoundsException ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ public class ReplaceWithMessageFormatFixTest {

@Test
public void testFixWorkingMixedA() throws Exception {
HintTest.create().
HintTest.create().setCaretMarker('|').
input("package test;\n"
+ "public class Test {\n"
+ " public static void main(String[] args) {\n"
+ " String foo=\"Output contains \"+4+\" entries\";\n"
+ " String foo=\"Output contains \"|+4+\" entries\";\n"
+ " }\n"
+ "}\n").
run(ReplacePlusHint.class).
findWarning("3:19-3:50:hint:" + Bundle.DN_ReplacePlus()).
findWarning("3:37-3:37:hint:" + Bundle.DN_ReplacePlus()).
applyFix(Bundle.LBL_ReplaceWithMessageFormatFix()).
assertCompilable().
assertOutput("package test;\n"
Expand All @@ -81,15 +81,15 @@ public void testFixWorkingMixedA() throws Exception {
}
@Test
public void testFixWorkingWithLineBreaks() throws Exception {
HintTest.create().
HintTest.create().setCaretMarker('|').
input("package test;\n"
+ "public class Test {\n"
+ " public static void main(String[] args) {\n"
+ " String foo=\"ABC\\nDEF\\r\"+4+\"GHI\";\n"
+ " String foo=\"ABC\\nDEF\\r\"|+4+\"GHI\";\n"
+ " }\n"
+ "}\n").
run(ReplacePlusHint.class).
findWarning("3:19-3:39:hint:" + Bundle.DN_ReplacePlus()).
findWarning("3:31-3:31:hint:" + Bundle.DN_ReplacePlus()).
applyFix(Bundle.LBL_ReplaceWithMessageFormatFix()).
assertCompilable().
assertOutput("package test;\n"
Expand All @@ -103,15 +103,15 @@ public void testFixWorkingWithLineBreaks() throws Exception {

@Test
public void testFixWorkingLiteralPrefix() throws Exception {
HintTest.create().
HintTest.create().setCaretMarker('|').
input("package test;\n"
+ "public class Test {\n"
+ " public static void main(String[] args) {\n"
+ " String foo=\"A\"+4;\n"
+ " String foo=\"A\"|+4;\n"
+ " }\n"
+ "}\n").
run(ReplacePlusHint.class).
findWarning("3:19-3:24:hint:" + Bundle.DN_ReplacePlus()).
findWarning("3:22-3:22:hint:" + Bundle.DN_ReplacePlus()).
applyFix(Bundle.LBL_ReplaceWithMessageFormatFix()).
assertCompilable().
assertOutput("package test;\n"
Expand All @@ -125,15 +125,15 @@ public void testFixWorkingLiteralPrefix() throws Exception {

@Test
public void testFixWorkingLiteralPostfix() throws Exception {
HintTest.create().
HintTest.create().setCaretMarker('|').
input("package test;\n"
+ "public class Test {\n"
+ " public static void main(String[] args) {\n"
+ " String foo=4+\"A\";\n"
+ " String foo=4|+\"A\";\n"
+ " }\n"
+ "}\n").
run(ReplacePlusHint.class).
findWarning("3:19-3:24:hint:" + Bundle.DN_ReplacePlus()).
findWarning("3:20-3:20:hint:" + Bundle.DN_ReplacePlus()).
applyFix(Bundle.LBL_ReplaceWithMessageFormatFix()).
assertCompilable().
assertOutput("package test;\n"
Expand All @@ -146,11 +146,11 @@ public void testFixWorkingLiteralPostfix() throws Exception {
}
@Test
public void testSingleLiteral() throws Exception {
HintTest.create().
HintTest.create().setCaretMarker('|').
input("package test;\n"
+ "public class Test {\n"
+ " public static void main(String[] args) {\n"
+ " String foo=\"A\";\n"
+ " String foo=\"|A\";\n"
+ " }\n"
+ "}\n").
run(ReplacePlusHint.class).
Expand All @@ -159,11 +159,11 @@ public void testSingleLiteral() throws Exception {

@Test
public void testOnlyLiterals() throws Exception {
HintTest.create().
HintTest.create().setCaretMarker('|').
input("package test;\n"
+ "public class Test {\n"
+ " public static void main(String[] args) {\n"
+ " String foo=\"A\"+\"B\"+\"C\";\n"
+ " String foo=\"A\"|+\"B\"+\"C\";\n"
+ " }\n"
+ "}\n").
run(ReplacePlusHint.class).
Expand All @@ -172,15 +172,15 @@ public void testOnlyLiterals() throws Exception {

@Test
public void testFixWorkingMixedB() throws Exception {
HintTest.create().
HintTest.create().setCaretMarker('|').
input("package test;\n"
+ "public class Test {\n"
+ " public static void main(String[] args) {\n"
+ " String foo=\"Output contains \" + 4 + \" entries\" + \" and more at \" + new java.util.Date();\n"
+ " String foo=\"Output contains \" |+ 4 + \" entries\" + \" and more at \" + new java.util.Date();\n"
+ " }\n"
+ "}\n").
run(ReplacePlusHint.class).
findWarning("3:19-3:95:hint:" + Bundle.DN_ReplacePlus()).
findWarning("3:38-3:38:hint:" + Bundle.DN_ReplacePlus()).
applyFix(Bundle.LBL_ReplaceWithMessageFormatFix()).
assertCompilable().
assertOutput("package test;\n"
Expand All @@ -200,15 +200,15 @@ public void testFixWorkingMixedB() throws Exception {
*/
@Test
public void testFixWorkingQuotedStrings1() throws Exception {
HintTest.create().
HintTest.create().setCaretMarker('|').
input("package test;\n"
+ "public class Test {\n"
+ " public static void main(String[] args) {\n"
+ " String b = \"Hello \\\"\"+42+\"\\\"\";"
+ " String b = \"Hello \\\"\"+|42+\"\\\"\";"
+ " }\n"
+ "}\n").
run(ReplacePlusHint.class).
findWarning("3:12-3:30:hint:" + Bundle.DN_ReplacePlus()).
findWarning("3:23-3:23:hint:" + Bundle.DN_ReplacePlus()).
applyFix(Bundle.LBL_ReplaceWithMessageFormatFix()).
assertCompilable().
assertOutput("package test;\n"
Expand Down
Loading

0 comments on commit 0df8eba

Please sign in to comment.