From 88ddab68b2157fefc6fa22dfdbc73ce019f3478a Mon Sep 17 00:00:00 2001 From: Akshay-Gupta-Oracle Date: Thu, 21 Nov 2019 12:05:55 +0530 Subject: [PATCH 1/4] [NETBEANS-3311] Providing support convert text block to string --- .../hints/jdk/ConvertTextBlockToString.java | 106 ++++++ .../jdk/ConvertTextBlockToStringTest.java | 307 ++++++++++++++++++ 2 files changed, 413 insertions(+) create mode 100644 java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java create mode 100644 java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToStringTest.java diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java new file mode 100644 index 000000000000..23075bfcdc4f --- /dev/null +++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.netbeans.modules.java.hints.jdk; + +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.Tree; +import com.sun.source.util.TreePath; +import org.netbeans.api.java.lexer.JavaTokenId; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.api.lexer.TokenSequence; +import org.netbeans.spi.editor.hints.ErrorDescription; +import org.netbeans.spi.editor.hints.Fix; +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.Messages; + +@Hint(displayName = "#DN_ConvertTextBlockToString", description = "#DESC_ConvertTextBlockToString", category = "general", minSourceVersion = "13") +@Messages({ + "DN_ConvertTextBlockToString=Convert Text block to String", + "DESC_ConvertTextBlockToString=Text Block may not be supported in older versions of java older then 13" +}) +public class ConvertTextBlockToString { + + @TriggerTreeKind(Tree.Kind.STRING_LITERAL) + @Messages("ERR_ConvertTextBlockToString=Text block may not be supported")//NOI18N + public static ErrorDescription computeWarning(HintContext ctx) { + TokenSequence ts = ctx.getInfo().getTokenHierarchy().tokenSequence(); + ts.move((int) ctx.getInfo().getTrees().getSourcePositions().getStartPosition(ctx.getPath().getCompilationUnit(), ctx.getPath().getLeaf())); + boolean moveNext = ts.moveNext(); + if (!moveNext || ts.token().id() != JavaTokenId.MULTILINE_STRING_LITERAL) { + return null; + } + + String orignalString = ctx.getPath().getLeaf().toString(); + String orignalStringArr[] = textBlockToStringArr(orignalString.substring(1, orignalString.length() - 1)); + Fix fix = new FixImpl(ctx.getInfo(), ctx.getPath(), orignalStringArr).toEditorFix(); + return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.ERR_ConvertTextBlockToString(), fix); + } + + private static String[] textBlockToStringArr(String textBlock) { + String oneLine[] = textBlock.split("\\\\n", -1); // NOI18N + return oneLine; + } + + private static final class FixImpl extends JavaFix { + + String orignalStringArr[]; + + public FixImpl(CompilationInfo info, TreePath tp, String orignalStringArr[]) { + super(info, tp); + this.orignalStringArr = orignalStringArr; + } + + @Override + @Messages("FIX_ConvertTextBlockToString=Convert to String") + protected String getText() { + return Bundle.FIX_ConvertTextBlockToString(); + } + + @Override + protected void performRewrite(TransformationContext ctx) { + ExpressionTree ext = buildTree(orignalStringArr, orignalStringArr.length - 1, ctx); + ctx.getWorkingCopy().rewrite(ctx.getPath().getLeaf(), ext); + + } + + static private ExpressionTree buildTree(String arr[], int li, TransformationContext ctx) { + for (int i = 0; i < arr.length; i++) { + arr[i] = arr[i].replaceAll("\\Q\\\"\\E", "\""); // NOI18N + arr[i] = arr[i].replaceAll("\\Q\\\'\\E", "\'"); // NOI18N + } + if (arr.length == 1) { + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(arr[0]), ctx.getWorkingCopy().getTreeMaker().Literal("")); + } + if (li == 1) { + if (li == arr.length - 1) { + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(arr[li - 1] + "\n"), ctx.getWorkingCopy().getTreeMaker().Literal(arr[li])); + } + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(arr[li - 1] + "\n"), ctx.getWorkingCopy().getTreeMaker().Literal(arr[li] + "\n")); + } + if (li == arr.length - 1) { + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, buildTree(arr, li - 1, ctx), ctx.getWorkingCopy().getTreeMaker().Literal(arr[li])); + } + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, buildTree(arr, li - 1, ctx), ctx.getWorkingCopy().getTreeMaker().Literal(arr[li] + "\n")); + } + } +} diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToStringTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToStringTest.java new file mode 100644 index 000000000000..d1d56d29b526 --- /dev/null +++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToStringTest.java @@ -0,0 +1,307 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.netbeans.modules.java.hints.jdk; + +import org.junit.Test; +import org.netbeans.modules.java.hints.test.api.HintTest; +import javax.lang.model.SourceVersion; + +/* TODO to make this test work: + - to ensure that the newest Java language features supported by the IDE are available, + regardless of which JDK you build the module with: + -- for Ant-based modules, add "requires.nb.javac=true" into nbproject/project.properties + -- for Maven-based modules, use dependency:copy in validate phase to create + target/endorsed/org-netbeans-libs-javacapi-*.jar and add to endorseddirs + in maven-compiler-plugin and maven-surefire-plugin configuration + See: http://wiki.netbeans.org/JavaHintsTestMaven + */ +public class ConvertTextBlockToStringTest { + + @Test + public void newLineAtEnd() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " abc\n" + + " def\n" + + " hij\n" + + " \"\"\";\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"abc\\n\" + \"def\\n\" + \"hij\\n\" + \"\";\n" + + " }\n" + + "}"); + } + + @Test + public void simpleTest() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " abc\"\"\";\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"abc\" + \"\";\n" + + " }\n" + + "}"); + } + + @Test + public void multipleNewLine() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " abc\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \"\"\";\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"abc\\n\" + \"\\n\" + \"\\n\" + \"\\n\" + \"\\n\" + \"\\n\" + \"\";\n" + + " }\n" + + "}"); + } + + @Test + public void newLineAfter() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " abc\n" + + " def\"\"\"\n" + + " \n" + + " \n" + + " \n" + + " ;\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\" abc\\n\" + \"def\"\n" + + " \n" + + " \n" + + " \n" + + " ;\n" + + " }\n" + + "}"); + } + + @Test + public void manyLineTextBlock() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " abc\n" + + " def\n" + + " ghi\n" + + " jkl\n" + + " mno\n" + + " pqrs\n" + + " tuv\n" + + " wxyz\"\"\";\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"abc\\n\" + \"def\\n\" + \"ghi\\n\" + \"jkl\\n\" + \"mno\\n\" + \"pqrs\\n\" + \"tuv\\n\" + \"wxyz\";\n" + + " }\n" + + "}"); + } + + @Test + public void twoLineTextBlock() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " abc\n" + + " def\"\"\";\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"abc\\n\" + \"def\";\n" + + " }\n" + + "}"); + } + + @Test + public void escapeCharTextBlock() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " abc\n" + + " \"def\"\"\";\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"abc\\n\" + \"\\\"def\";\n" + + " }\n" + + "}"); + } + + @Test + public void escapeCharTextBlock2() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " abc\n" + + " \"def\n" + + " ghi\n" + + " 'lmn'\n" + + " opq\n" + + " \"\"\";\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"abc\\n\" + \"\\\"def\\n\" + \"ghi\\n\" + \"'lmn'\\n\" + \"opq\\n\" + \"\";\n" + + " }\n" + + "}"); + } +} From 6efeb73c5f29957d00f221f50d0aa96c65e44338 Mon Sep 17 00:00:00 2001 From: Akshay-Gupta-Oracle Date: Wed, 4 Dec 2019 14:15:40 +0530 Subject: [PATCH 2/4] [NETBEANS-3311] Providing support convert text block to string --- .../hints/jdk/ConvertTextBlockToString.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java index 23075bfcdc4f..24466ae23f51 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java +++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java @@ -44,9 +44,9 @@ public class ConvertTextBlockToString { @Messages("ERR_ConvertTextBlockToString=Text block may not be supported")//NOI18N public static ErrorDescription computeWarning(HintContext ctx) { TokenSequence ts = ctx.getInfo().getTokenHierarchy().tokenSequence(); + if(ts==null)return null; ts.move((int) ctx.getInfo().getTrees().getSourcePositions().getStartPosition(ctx.getPath().getCompilationUnit(), ctx.getPath().getLeaf())); - boolean moveNext = ts.moveNext(); - if (!moveNext || ts.token().id() != JavaTokenId.MULTILINE_STRING_LITERAL) { + if (!ts.moveNext() || ts.token().id() != JavaTokenId.MULTILINE_STRING_LITERAL) { return null; } @@ -83,24 +83,24 @@ protected void performRewrite(TransformationContext ctx) { } - static private ExpressionTree buildTree(String arr[], int li, TransformationContext ctx) { - for (int i = 0; i < arr.length; i++) { - arr[i] = arr[i].replaceAll("\\Q\\\"\\E", "\""); // NOI18N - arr[i] = arr[i].replaceAll("\\Q\\\'\\E", "\'"); // NOI18N + static private ExpressionTree buildTree(String textBlockLines[], int currentLine, TransformationContext ctx) { + for (int i = 0; i < textBlockLines.length; i++) { + textBlockLines[i] = textBlockLines[i].replaceAll("\\Q\\\"\\E", "\""); // NOI18N + textBlockLines[i] = textBlockLines[i].replaceAll("\\Q\\\'\\E", "\'"); // NOI18N } - if (arr.length == 1) { - return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(arr[0]), ctx.getWorkingCopy().getTreeMaker().Literal("")); + if (textBlockLines.length == 1) { + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[0]), ctx.getWorkingCopy().getTreeMaker().Literal(""));// NOI18N } - if (li == 1) { - if (li == arr.length - 1) { - return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(arr[li - 1] + "\n"), ctx.getWorkingCopy().getTreeMaker().Literal(arr[li])); + if (currentLine == 1) { + if (currentLine == textBlockLines.length - 1) { + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine - 1] + "\n"), ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine]));// NOI18N } - return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(arr[li - 1] + "\n"), ctx.getWorkingCopy().getTreeMaker().Literal(arr[li] + "\n")); + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine - 1] + "\n"), ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine] + "\n"));// NOI18N } - if (li == arr.length - 1) { - return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, buildTree(arr, li - 1, ctx), ctx.getWorkingCopy().getTreeMaker().Literal(arr[li])); + if (currentLine == textBlockLines.length - 1) { + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, buildTree(textBlockLines, currentLine - 1, ctx), ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine])); } - return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, buildTree(arr, li - 1, ctx), ctx.getWorkingCopy().getTreeMaker().Literal(arr[li] + "\n")); + return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, buildTree(textBlockLines, currentLine - 1, ctx), ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine] + "\n"));// NOI18N } } } From 6e06e0f8e67e364bfbdb7947f7cd7f8f9ad70043 Mon Sep 17 00:00:00 2001 From: Akshay-Gupta-Oracle Date: Tue, 24 Dec 2019 15:28:38 +0530 Subject: [PATCH 3/4] [NETBEANS-3311] Providing support convert text block to string --- .../hints/jdk/ConvertTextBlockToString.java | 45 ++++++------ .../jdk/ConvertTextBlockToStringTest.java | 71 +++++++++++++++++-- .../modules/java/source/save/CasualDiff.java | 14 +++- 3 files changed, 101 insertions(+), 29 deletions(-) diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java index 24466ae23f51..837a3aa9c495 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java +++ b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToString.java @@ -18,7 +18,9 @@ */ package org.netbeans.modules.java.hints.jdk; +import com.sun.source.tree.BinaryTree; import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.LiteralTree; import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; import org.netbeans.api.java.lexer.JavaTokenId; @@ -44,20 +46,27 @@ public class ConvertTextBlockToString { @Messages("ERR_ConvertTextBlockToString=Text block may not be supported")//NOI18N public static ErrorDescription computeWarning(HintContext ctx) { TokenSequence ts = ctx.getInfo().getTokenHierarchy().tokenSequence(); - if(ts==null)return null; - ts.move((int) ctx.getInfo().getTrees().getSourcePositions().getStartPosition(ctx.getPath().getCompilationUnit(), ctx.getPath().getLeaf())); + if (ts == null) { + return null; + } + int textBlockIndex = (int) ctx.getInfo().getTrees().getSourcePositions().getStartPosition(ctx.getPath().getCompilationUnit(), ctx.getPath().getLeaf()); + if (textBlockIndex == -1) { + return null; + } + ts.move(textBlockIndex); + if (!ts.moveNext() || ts.token().id() != JavaTokenId.MULTILINE_STRING_LITERAL) { return null; } - String orignalString = ctx.getPath().getLeaf().toString(); - String orignalStringArr[] = textBlockToStringArr(orignalString.substring(1, orignalString.length() - 1)); + String orignalString = (String) ((LiteralTree) ctx.getPath().getLeaf()).getValue(); + String orignalStringArr[] = textBlockToStringArr(orignalString); Fix fix = new FixImpl(ctx.getInfo(), ctx.getPath(), orignalStringArr).toEditorFix(); return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.ERR_ConvertTextBlockToString(), fix); } private static String[] textBlockToStringArr(String textBlock) { - String oneLine[] = textBlock.split("\\\\n", -1); // NOI18N + String oneLine[] = textBlock.split("\n", -1); // NOI18N return oneLine; } @@ -78,27 +87,19 @@ protected String getText() { @Override protected void performRewrite(TransformationContext ctx) { - ExpressionTree ext = buildTree(orignalStringArr, orignalStringArr.length - 1, ctx); + ExpressionTree ext = ctx.getWorkingCopy().getTreeMaker().Literal(orignalStringArr[orignalStringArr.length - 1]); + if (orignalStringArr.length > 1) { + ext = ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, buildTree(orignalStringArr, orignalStringArr.length - 2, ctx), (ExpressionTree) ext); + if (orignalStringArr[orignalStringArr.length - 1].equals("")) { + ext = (((BinaryTree) ext).getLeftOperand()); + } + } ctx.getWorkingCopy().rewrite(ctx.getPath().getLeaf(), ext); - } static private ExpressionTree buildTree(String textBlockLines[], int currentLine, TransformationContext ctx) { - for (int i = 0; i < textBlockLines.length; i++) { - textBlockLines[i] = textBlockLines[i].replaceAll("\\Q\\\"\\E", "\""); // NOI18N - textBlockLines[i] = textBlockLines[i].replaceAll("\\Q\\\'\\E", "\'"); // NOI18N - } - if (textBlockLines.length == 1) { - return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[0]), ctx.getWorkingCopy().getTreeMaker().Literal(""));// NOI18N - } - if (currentLine == 1) { - if (currentLine == textBlockLines.length - 1) { - return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine - 1] + "\n"), ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine]));// NOI18N - } - return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine - 1] + "\n"), ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine] + "\n"));// NOI18N - } - if (currentLine == textBlockLines.length - 1) { - return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, buildTree(textBlockLines, currentLine - 1, ctx), ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine])); + if (currentLine == 0) { + return ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[0] + "\n");// NOI18N } return ctx.getWorkingCopy().getTreeMaker().Binary(Tree.Kind.PLUS, buildTree(textBlockLines, currentLine - 1, ctx), ctx.getWorkingCopy().getTreeMaker().Literal(textBlockLines[currentLine] + "\n"));// NOI18N } diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToStringTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToStringTest.java index d1d56d29b526..5d11ade9e9b0 100644 --- a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToStringTest.java +++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertTextBlockToStringTest.java @@ -61,7 +61,7 @@ public void newLineAtEnd() throws Exception { .assertOutput("package helloworld;\n" + "public class Test {\n" + " public static void main(String[] args) {\n" - + " String a =\"abc\\n\" + \"def\\n\" + \"hij\\n\" + \"\";\n" + + " String a =\"abc\\n\" + \"def\\n\" + \"hij\\n\";\n" + " }\n" + "}"); } @@ -91,7 +91,7 @@ public void simpleTest() throws Exception { .assertOutput("package helloworld;\n" + "public class Test {\n" + " public static void main(String[] args) {\n" - + " String a =\"abc\" + \"\";\n" + + " String a =\"abc\";\n" + " }\n" + "}"); } @@ -127,7 +127,7 @@ public void multipleNewLine() throws Exception { .assertOutput("package helloworld;\n" + "public class Test {\n" + " public static void main(String[] args) {\n" - + " String a =\"abc\\n\" + \"\\n\" + \"\\n\" + \"\\n\" + \"\\n\" + \"\\n\" + \"\";\n" + + " String a =\"abc\\n\" + \"\\n\" + \"\\n\" + \"\\n\" + \"\\n\" + \"\\n\";\n" + " }\n" + "}"); } @@ -239,6 +239,69 @@ public void twoLineTextBlock() throws Exception { + "}"); } + @Test + public void twoNewLines() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " \n" + + " \n" + + " \"\"\";\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\\n\" + \"\\n\";\n" + + " }\n" + + "}"); + } + + @Test + public void slashConvert() throws Exception { + try { + SourceVersion.valueOf("RELEASE_13"); + } catch (IllegalArgumentException ex) { + //OK, skip test + return; + } + HintTest.create() + .input("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\"\"\n" + + " \\\\\"\"\";\n" + + " }\n" + + "}") + .sourceLevel(SourceVersion.latest().name()) + .options("--enable-preview") + .run(ConvertTextBlockToString.class) + .findWarning("3:18-3:21:verifier:" + Bundle.ERR_ConvertTextBlockToString()) + .applyFix() + .assertCompilable() + .assertOutput("package helloworld;\n" + + "public class Test {\n" + + " public static void main(String[] args) {\n" + + " String a =\"\\\\\";\n" + + " }\n" + + "}"); + } + + @Test public void escapeCharTextBlock() throws Exception { try { @@ -300,7 +363,7 @@ public void escapeCharTextBlock2() throws Exception { .assertOutput("package helloworld;\n" + "public class Test {\n" + " public static void main(String[] args) {\n" - + " String a =\"abc\\n\" + \"\\\"def\\n\" + \"ghi\\n\" + \"'lmn'\\n\" + \"opq\\n\" + \"\";\n" + + " String a =\"abc\\n\" + \"\\\"def\\n\" + \"ghi\\n\" + \"'lmn'\\n\" + \"opq\\n\";\n" + " }\n" + "}"); } diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java b/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java index b1754820238d..a32f8e03222f 100644 --- a/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java +++ b/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java @@ -2715,9 +2715,17 @@ protected int diffIdent(JCIdent oldT, JCIdent newT, int[] bounds) { } protected int diffLiteral(JCLiteral oldT, JCLiteral newT, int[] bounds) { - if (oldT.typetag != newT.typetag || - (oldT.value != null && !oldT.value.equals(newT.value))) - { + boolean doesMove=true; + if (tokenSequence.offset() != bounds[0] && oldT.getKind()==Tree.Kind.STRING_LITERAL) {//correcting bounds when old tree litral is text block + tokenSequence.move(bounds[0]); + doesMove= tokenSequence.moveNext(); + while (doesMove && tokenSequence.token().id() != JavaTokenId.MULTILINE_STRING_LITERAL) { + doesMove &= tokenSequence.moveNext(); + } + bounds[0]=tokenSequence.offset(); + } + if (oldT.typetag != newT.typetag + || (oldT.value != null && !oldT.value.equals(newT.value)) || (tokenSequence.token().id() == JavaTokenId.MULTILINE_STRING_LITERAL && newT.getKind()==Tree.Kind.STRING_LITERAL && doesMove)) { int localPointer = bounds[0]; // literal int[] literalBounds = getBounds(oldT); From e5944ed84b1ea537629252aea57ed741e7af8341 Mon Sep 17 00:00:00 2001 From: Akshay-Gupta-Oracle Date: Tue, 21 Jan 2020 11:28:49 +0530 Subject: [PATCH 4/4] [NETBEANS-3311] Providing support convert text block to string --- .../netbeans/modules/java/source/save/CasualDiff.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java b/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java index a32f8e03222f..1185b9861023 100644 --- a/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java +++ b/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java @@ -2715,17 +2715,8 @@ protected int diffIdent(JCIdent oldT, JCIdent newT, int[] bounds) { } protected int diffLiteral(JCLiteral oldT, JCLiteral newT, int[] bounds) { - boolean doesMove=true; - if (tokenSequence.offset() != bounds[0] && oldT.getKind()==Tree.Kind.STRING_LITERAL) {//correcting bounds when old tree litral is text block - tokenSequence.move(bounds[0]); - doesMove= tokenSequence.moveNext(); - while (doesMove && tokenSequence.token().id() != JavaTokenId.MULTILINE_STRING_LITERAL) { - doesMove &= tokenSequence.moveNext(); - } - bounds[0]=tokenSequence.offset(); - } if (oldT.typetag != newT.typetag - || (oldT.value != null && !oldT.value.equals(newT.value)) || (tokenSequence.token().id() == JavaTokenId.MULTILINE_STRING_LITERAL && newT.getKind()==Tree.Kind.STRING_LITERAL && doesMove)) { + || (oldT.value != null && !oldT.value.equals(newT.value)) || (oldT.getKind() == Tree.Kind.STRING_LITERAL && newT.getKind() == Tree.Kind.STRING_LITERAL)) { int localPointer = bounds[0]; // literal int[] literalBounds = getBounds(oldT);