6767import org .eclipse .jdt .core .dom .VariableDeclarationStatement ;
6868import org .eclipse .jdt .core .dom .rewrite .ASTRewrite ;
6969import org .eclipse .jdt .core .dom .rewrite .ImportRewrite ;
70+ import org .eclipse .jdt .core .dom .rewrite .ListRewrite ;
7071import org .eclipse .jdt .core .dom .rewrite .TargetSourceRangeComputer ;
7172import org .eclipse .jdt .core .formatter .DefaultCodeFormatterConstants ;
7273
@@ -509,6 +510,7 @@ private class CheckValidityVisitor extends ASTVisitor {
509510 private List <MethodInvocation > toStringList = new ArrayList <>();
510511 private List <MethodInvocation > indexOfList = new ArrayList <>();
511512 private List <SimpleName > argList = new ArrayList <>();
513+ private boolean passedAsArgument = false ;
512514
513515 public CheckValidityVisitor (int lastStatementEnd , IBinding varBinding ) {
514516 this .lastStatementEnd = lastStatementEnd ;
@@ -519,6 +521,10 @@ public boolean isValid() {
519521 return valid ;
520522 }
521523
524+ public boolean isPassedAsArgument () {
525+ return passedAsArgument ;
526+ }
527+
522528 public ExpressionStatement getNextAssignment () {
523529 return nextAssignment ;
524530 }
@@ -581,8 +587,11 @@ public boolean visit(SimpleName name) {
581587 paramType .getQualifiedName ().equals ("java.lang.CharSequence" )) { //$NON-NLS-1$
582588 argList .add (name );
583589 valid = true ;
590+ return true ;
584591 } else {
585- valid = false ;
592+ passedAsArgument = true ;
593+ valid = true ;
594+ return true ;
586595 }
587596 }
588597 } else {
@@ -739,9 +748,22 @@ public boolean visit(SimpleName simpleName) {
739748 } catch (AbortSearchException e ) {
740749 // do nothing
741750 }
742- if (!checkValidityVisitor .isValid () || (checkValidityVisitor .getToStringList ().isEmpty () && checkValidityVisitor .getArgList ().isEmpty ())) {
751+
752+ if (!checkValidityVisitor .isValid ()) {
753+ return failure ();
754+ } else if (checkValidityVisitor .isPassedAsArgument ()) {
755+ List <Statement > statements = new ArrayList <>(statementList );
756+ List <StringLiteral > literals = new ArrayList <>(fLiterals );
757+ ModifyStringBufferToUseTextBlock operation = new ModifyStringBufferToUseTextBlock (node , statements ,
758+ literals );
759+ fOperations .add (operation );
760+ statementList .clear ();
761+ fLiterals .clear ();
762+ return false ;
763+ } else if (checkValidityVisitor .getToStringList ().isEmpty () && checkValidityVisitor .getArgList ().isEmpty ()) {
743764 return failure ();
744765 }
766+
745767 ExpressionStatement assignmentToConvert = checkValidityVisitor .getNextAssignment ();
746768 List <Statement > statements = new ArrayList <>(statementList );
747769 List <StringLiteral > literals = new ArrayList <>(fLiterals );
@@ -884,14 +906,54 @@ private static boolean hasNLSMarker(ASTNode node, ICompilationUnit cu) throws Ab
884906 return hasNLS ;
885907 }
886908
909+ public static class ModifyStringBufferToUseTextBlock extends CompilationUnitRewriteOperation {
910+
911+ private final List <Statement > fStatements ;
912+ private final List <StringLiteral > fLiterals ;
913+ private final ClassInstanceCreation fConstructor ;
914+
915+ public ModifyStringBufferToUseTextBlock (final ClassInstanceCreation constructor , final List <Statement > statements , final List <StringLiteral > literals ) {
916+ fStatements = statements ;
917+ fLiterals = literals ;
918+ fConstructor = constructor ;
919+ }
920+
921+ @ Override
922+ public void rewriteAST (final CompilationUnitRewrite cuRewrite , final LinkedProposalModelCore linkedModel ) throws CoreException {
923+ ASTRewrite rewrite = cuRewrite .getASTRewrite ();
924+ TextEditGroup group = createTextEditGroup (MultiFixMessages .StringConcatToTextBlockCleanUp_description , cuRewrite );
925+ rewrite .setTargetSourceRangeComputer (new TargetSourceRangeComputer () {
926+ @ Override
927+ public SourceRange computeSourceRange (final ASTNode nodeWithComment ) {
928+ if (Boolean .TRUE .equals (nodeWithComment .getProperty (ASTNodes .UNTOUCH_COMMENT ))) {
929+ return new SourceRange (nodeWithComment .getStartPosition (), nodeWithComment .getLength ());
930+ }
931+
932+ return super .computeSourceRange (nodeWithComment );
933+ }
934+ });
935+
936+ StringBuilder buf = createTextBlockBuffer (fLiterals , cuRewrite );
937+ TextBlock textBlock = (TextBlock ) rewrite .createStringPlaceholder (buf .toString (), ASTNode .TEXT_BLOCK );
938+ ListRewrite argList = rewrite .getListRewrite (fConstructor , ClassInstanceCreation .ARGUMENTS_PROPERTY );
939+ List <ASTNode > original = argList .getOriginalList ();
940+ for (ASTNode node : original ) {
941+ rewrite .remove (node , group );
942+ }
943+ argList .insertFirst (textBlock , group );
944+ for (int i = 1 ; i < fStatements .size (); ++i ) {
945+ rewrite .remove (fStatements .get (i ), group );
946+ }
947+ }
948+ }
949+
887950 public static class ChangeStringBufferToTextBlock extends CompilationUnitRewriteOperation {
888951
889952 private final List <MethodInvocation > fToStringList ;
890953 private final List <MethodInvocation > fIndexOfList ;
891954 private final List <SimpleName > fArgList ;
892955 private final List <Statement > fStatements ;
893956 private final List <StringLiteral > fLiterals ;
894- private String fIndent ;
895957 private final Set <String > fExcludedNames ;
896958 private final BodyDeclaration fLastBodyDecl ;
897959 private final boolean fNonNLS ;
@@ -905,7 +967,6 @@ public ChangeStringBufferToTextBlock(final List<MethodInvocation> toStringList,
905967 this .fStatements = statements ;
906968 this .fLiterals = literals ;
907969 this .fAssignmentToConvert = assignmentToConvert ;
908- this .fIndent = "\t " ; //$NON-NLS-1$
909970 this .fExcludedNames = excludedNames ;
910971 this .fLastBodyDecl = lastBodyDecl ;
911972 this .fNonNLS = nonNLS ;
@@ -927,19 +988,6 @@ public void rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedPropo
927988 fExcludedNames .clear ();
928989 }
929990 ASTRewrite rewrite = cuRewrite .getASTRewrite ();
930- IJavaElement root = cuRewrite .getRoot ().getJavaElement ();
931- if (root != null ) {
932- IJavaProject project = root .getJavaProject ();
933- if (project != null ) {
934- String tab_option = project .getOption (DefaultCodeFormatterConstants .FORMATTER_TAB_CHAR , true );
935- if (JavaCore .SPACE .equals (tab_option )) {
936- fIndent = "" ; //$NON-NLS-1$
937- for (int i = 0 ; i < CodeFormatterUtil .getTabWidth (project ); ++i ) {
938- fIndent += " " ; //$NON-NLS-1$
939- }
940- }
941- }
942- }
943991 TextEditGroup group = createTextEditGroup (MultiFixMessages .StringConcatToTextBlockCleanUp_description , cuRewrite );
944992 rewrite .setTargetSourceRangeComputer (new TargetSourceRangeComputer () {
945993 @ Override
@@ -952,53 +1000,7 @@ public SourceRange computeSourceRange(final ASTNode nodeWithComment) {
9521000 }
9531001 });
9541002
955- StringBuilder buf = new StringBuilder ();
956-
957- List <String > parts = new ArrayList <>();
958- fLiterals .stream ().forEach ((t ) -> { String value = t .getEscapedValue (); parts .addAll (unescapeBlock (value .substring (1 , value .length () - 1 ))); });
959-
960-
961- buf .append ("\" \" \" \n " ); //$NON-NLS-1$
962- boolean newLine = false ;
963- boolean allWhiteSpaceStart = true ;
964- boolean allEmpty = true ;
965- for (String part : parts ) {
966- if (buf .length () > 4 ) {// the first part has been added after the text block delimiter and newline
967- if (!newLine ) {
968- // no line terminator in this part: merge the line by emitting a line continuation escape
969- buf .append ("\\ " ).append (System .lineSeparator ()); //$NON-NLS-1$
970- }
971- }
972- newLine = part .endsWith (System .lineSeparator ());
973- allWhiteSpaceStart = allWhiteSpaceStart && (part .isEmpty () || Character .isWhitespace (part .charAt (0 )));
974- allEmpty = allEmpty && part .isEmpty ();
975- buf .append (fIndent ).append (part );
976- }
977-
978- if (newLine || allEmpty ) {
979- buf .append (fIndent );
980- } else if (allWhiteSpaceStart ) {
981- buf .append ("\\ " ).append (System .lineSeparator ()); //$NON-NLS-1$
982- buf .append (fIndent );
983- } else {
984- // Replace trailing un-escaped quotes with escaped quotes before adding text block end
985- int readIndex = buf .length () - 1 ;
986- int count = 0 ;
987- while (readIndex >= 0 && buf .charAt (readIndex ) == '"' && count <= 3 ) {
988- --readIndex ;
989- ++count ;
990- }
991- if (readIndex >= 0 && buf .charAt (readIndex ) == '\\' ) {
992- --count ;
993- }
994- for (int i = count ; i > 0 ; --i ) {
995- buf .deleteCharAt (buf .length () - 1 );
996- }
997- for (int i = count ; i > 0 ; --i ) {
998- buf .append ("\\ \" " ); //$NON-NLS-1$
999- }
1000- }
1001- buf .append ("\" \" \" " ); //$NON-NLS-1$
1003+ StringBuilder buf = createTextBlockBuffer (fLiterals , cuRewrite );
10021004 AST ast = fStatements .get (0 ).getAST ();
10031005 if (fToStringList .size () == 1 &&
10041006 fIndexOfList .isEmpty () &&
@@ -1146,6 +1148,71 @@ public static StringConcatToTextBlockFixCore createStringConcatToTextBlockFix(AS
11461148 return new StringConcatToTextBlockFixCore (FixMessages .StringConcatToTextBlockFix_convert_msg , root , new CompilationUnitRewriteOperationsFixCore .CompilationUnitRewriteOperation [] { operations .get (0 ) });
11471149 }
11481150
1151+ private static StringBuilder createTextBlockBuffer (List <StringLiteral > literals , CompilationUnitRewrite cuRewrite ) {
1152+ IJavaElement root = cuRewrite .getRoot ().getJavaElement ();
1153+ String fIndent = "\t " ; //$NON-NLS-1$
1154+ if (root != null ) {
1155+ IJavaProject project = root .getJavaProject ();
1156+ if (project != null ) {
1157+ String tab_option = project .getOption (DefaultCodeFormatterConstants .FORMATTER_TAB_CHAR , true );
1158+ if (JavaCore .SPACE .equals (tab_option )) {
1159+ fIndent = "" ; //$NON-NLS-1$
1160+ for (int i = 0 ; i < CodeFormatterUtil .getTabWidth (project ); ++i ) {
1161+ fIndent += " " ; //$NON-NLS-1$
1162+ }
1163+ }
1164+ }
1165+ }
1166+
1167+ StringBuilder buf = new StringBuilder ();
1168+
1169+ List <String > parts = new ArrayList <>();
1170+ literals .stream ().forEach ((t ) -> { String value = t .getEscapedValue (); parts .addAll (unescapeBlock (value .substring (1 , value .length () - 1 ))); });
1171+
1172+ buf .append ("\" \" \" \n " ); //$NON-NLS-1$
1173+ boolean newLine = false ;
1174+ boolean allWhiteSpaceStart = true ;
1175+ boolean allEmpty = true ;
1176+ for (String part : parts ) {
1177+ if (buf .length () > 4 ) {// the first part has been added after the text block delimiter and newline
1178+ if (!newLine ) {
1179+ // no line terminator in this part: merge the line by emitting a line continuation escape
1180+ buf .append ("\\ " ).append (System .lineSeparator ()); //$NON-NLS-1$
1181+ }
1182+ }
1183+ newLine = part .endsWith (System .lineSeparator ());
1184+ allWhiteSpaceStart = allWhiteSpaceStart && (part .isEmpty () || Character .isWhitespace (part .charAt (0 )));
1185+ allEmpty = allEmpty && part .isEmpty ();
1186+ buf .append (fIndent ).append (part );
1187+ }
1188+
1189+ if (newLine || allEmpty ) {
1190+ buf .append (fIndent );
1191+ } else if (allWhiteSpaceStart ) {
1192+ buf .append ("\\ " ).append (System .lineSeparator ()); //$NON-NLS-1$
1193+ buf .append (fIndent );
1194+ } else {
1195+ // Replace trailing un-escaped quotes with escaped quotes before adding text block end
1196+ int readIndex = buf .length () - 1 ;
1197+ int count = 0 ;
1198+ while (readIndex >= 0 && buf .charAt (readIndex ) == '"' && count <= 3 ) {
1199+ --readIndex ;
1200+ ++count ;
1201+ }
1202+ if (readIndex >= 0 && buf .charAt (readIndex ) == '\\' ) {
1203+ --count ;
1204+ }
1205+ for (int i = count ; i > 0 ; --i ) {
1206+ buf .deleteCharAt (buf .length () - 1 );
1207+ }
1208+ for (int i = count ; i > 0 ; --i ) {
1209+ buf .append ("\\ \" " ); //$NON-NLS-1$
1210+ }
1211+ }
1212+ buf .append ("\" \" \" " ); //$NON-NLS-1$
1213+ return buf ;
1214+ }
1215+
11491216 protected StringConcatToTextBlockFixCore (final String name , final CompilationUnit compilationUnit , final CompilationUnitRewriteOperationsFixCore .CompilationUnitRewriteOperation [] fixRewriteOperations ) {
11501217 super (name , compilationUnit , fixRewriteOperations );
11511218 }
0 commit comments