1616
1717import java .util .ArrayList ;
1818import java .util .List ;
19+ import java .util .regex .Matcher ;
20+ import java .util .regex .Pattern ;
1921
2022import org .eclipse .core .runtime .CoreException ;
2123
2224import org .eclipse .text .edits .TextEditGroup ;
2325
2426import org .eclipse .jdt .core .IBuffer ;
27+ import org .eclipse .jdt .core .ICompilationUnit ;
28+ import org .eclipse .jdt .core .IJavaElement ;
2529import org .eclipse .jdt .core .JavaCore ;
30+ import org .eclipse .jdt .core .JavaModelException ;
2631import org .eclipse .jdt .core .dom .ASTNode ;
32+ import org .eclipse .jdt .core .dom .ASTVisitor ;
2733import org .eclipse .jdt .core .dom .Block ;
2834import org .eclipse .jdt .core .dom .ChildPropertyDescriptor ;
2935import org .eclipse .jdt .core .dom .Comment ;
3036import org .eclipse .jdt .core .dom .CompilationUnit ;
3137import org .eclipse .jdt .core .dom .DoStatement ;
3238import org .eclipse .jdt .core .dom .EnhancedForStatement ;
39+ import org .eclipse .jdt .core .dom .Expression ;
3340import org .eclipse .jdt .core .dom .ForStatement ;
3441import org .eclipse .jdt .core .dom .IfStatement ;
3542import org .eclipse .jdt .core .dom .ReturnStatement ;
3643import org .eclipse .jdt .core .dom .Statement ;
44+ import org .eclipse .jdt .core .dom .StringLiteral ;
3745import org .eclipse .jdt .core .dom .ThrowStatement ;
3846import org .eclipse .jdt .core .dom .WhileStatement ;
3947import org .eclipse .jdt .core .dom .rewrite .ASTRewrite ;
@@ -186,9 +194,10 @@ public AddBlockOperation(ChildPropertyDescriptor bodyProperty, Statement body, S
186194 public void rewriteASTInternal (CompilationUnitRewrite cuRewrite , LinkedProposalModelCore model ) throws CoreException {
187195 ASTRewrite rewrite = cuRewrite .getASTRewrite ();
188196 String label ;
189- ASTNode expression = null ;
197+ Expression expression = null ;
190198 int statementType = -1 ;
191199 int defaultStartPosition = fControlStatement .getStartPosition ();
200+ CompilationUnit cuRoot = cuRewrite .getRoot ();
192201 if (fBodyProperty == IfStatement .THEN_STATEMENT_PROPERTY ) {
193202 label = FixMessages .CodeStyleFix_ChangeIfToBlock_desription ;
194203 expression = ((IfStatement )fControlStatement ).getExpression ();
@@ -198,7 +207,7 @@ public void rewriteASTInternal(CompilationUnitRewrite cuRewrite, LinkedProposalM
198207 } else if (fBodyProperty == IfStatement .ELSE_STATEMENT_PROPERTY ) {
199208 label = FixMessages .CodeStyleFix_ChangeElseToBlock_description ;
200209 Statement thenStatement = ((IfStatement )fControlStatement ).getThenStatement ();
201- defaultStartPosition = thenStatement . getStartPosition ( ) + thenStatement . getLength ( );
210+ defaultStartPosition = cuRoot . getExtendedStartPosition ( thenStatement ) + cuRoot . getExtendedLength ( thenStatement );
202211 } else {
203212 label = FixMessages .CodeStyleFix_ChangeControlToBlock_description ;
204213 if (fBodyProperty == WhileStatement .BODY_PROPERTY ) {
@@ -215,9 +224,14 @@ public void rewriteASTInternal(CompilationUnitRewrite cuRewrite, LinkedProposalM
215224
216225 TextEditGroup group = createTextEditGroup (label , cuRewrite );
217226 List <Comment > commentsToPreserve = new ArrayList <>();
218- CompilationUnit cuRoot = cuRewrite .getRoot ();
219227 int controlStatementLine = cuRoot .getLineNumber (fControlStatement .getStartPosition ());
220228 int bodyLine = cuRoot .getLineNumber (fBody .getStartPosition ());
229+ IBuffer cuBuffer = cuRewrite .getCu ().getBuffer ();
230+ // Get extended body text and convert multiple indent tabs to be just one tab as they will be relative to control statement
231+ String bodyString = cuBuffer .getText (cuRoot .getExtendedStartPosition (fBody ), cuRoot .getExtendedLength (fBody ))
232+ .replaceAll ("\\ r\\ n|\\ r|\\ n(\\ t|\\ s)*" , System .lineSeparator () + "\t " ); //$NON-NLS-1$ //$NON-NLS-2$
233+ String commentString = "" ; //$NON-NLS-1$
234+ boolean needToManuallyAddNLS = false ;
221235 // If single body statement is on next line, we need to preserve any comments pertaining to the
222236 // control statement (e.g. NLS comment for if expression)
223237 if (controlStatementLine != bodyLine ) {
@@ -228,31 +242,75 @@ public void rewriteASTInternal(CompilationUnitRewrite cuRewrite, LinkedProposalM
228242 if (commentLine == controlStatementLine && comment .getStartPosition () > startPosition &&
229243 comment .getStartPosition () < fBody .getStartPosition ()) {
230244 commentsToPreserve .add (comment );
245+ String commentText = cuBuffer .getText (comment .getStartPosition (), comment .getLength ());
246+ commentString += " " + commentText ; //$NON-NLS-1$
247+ }
248+ }
249+ } else {
250+ // single body statement is on same line...we might have to keep an NLS comment on same line
251+ if (expression != null ) {
252+ List <String > nlsList = fBodyProperty == IfStatement .ELSE_STATEMENT_PROPERTY ?
253+ getLineNLSComments (defaultStartPosition , expression ) :
254+ getLineNLSComments (expression .getStartPosition () + expression .getLength (), expression );
255+ if (!nlsList .isEmpty ()) {
256+ needToManuallyAddNLS = true ;
257+ class Counter {
258+ public int count = 0 ;
259+ }
260+ final Counter counter = new Counter ();
261+ ASTVisitor literalVisitor = new ASTVisitor () {
262+ @ Override
263+ public boolean visit (StringLiteral node ) {
264+ counter .count ++;
265+ return false ;
266+ }
267+ };
268+ expression .accept (literalVisitor );
269+ bodyString = cuBuffer .getText (cuRoot .getExtendedStartPosition (fBody ),
270+ fBody .getStartPosition () - cuRoot .getExtendedStartPosition (fBody ) + fBody .getLength ());
271+ int lastNLSIndex = 0 ;
272+ for (String nlsString : nlsList ) {
273+ int start = nlsString .indexOf ("$NON-NLS-" ) + 9 ; //$NON-NLS-1$
274+ int index = start ;
275+ while (Character .isDigit (nlsString .charAt (index ))) {
276+ ++index ;
277+ }
278+ int nlsIndex = Integer .parseInt (nlsString .substring (start , index ));
279+ if (nlsIndex <= counter .count ) {
280+ commentString += " " + nlsString ; //$NON-NLS-1$
281+ lastNLSIndex = nlsIndex ;
282+ } else {
283+ bodyString += " " + "//$NON-NLS-" + (nlsIndex - lastNLSIndex ) + "$" ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
284+ }
285+ }
231286 }
232287 }
233288 }
234- String blockString = "{" ; //$NON-NLS-1$
235- IBuffer cuBuffer = cuRewrite .getCu ().getBuffer ();
236289 Block replacingBody = null ;
237290 String blockPosition = JavaCore .getOption (DefaultCodeFormatterConstants .FORMATTER_BRACE_POSITION_FOR_BLOCK );
238291 boolean blockEndOfLine = blockPosition .equals (DefaultCodeFormatterConstants .END_OF_LINE );
239- if (!commentsToPreserve .isEmpty ()) {
240- // Get extended body text and convert multiple indent tabs to be just one tab as they will be relative to control statement
241- String bodyString = cuBuffer .getText (cuRoot .getExtendedStartPosition (fBody ), cuRoot .getExtendedLength (fBody ))
242- .replaceAll ("\\ r\\ n|\\ r|\\ n(\\ t|\\ s)*" , System .lineSeparator () + "\t " ); //$NON-NLS-1$ //$NON-NLS-2$
292+ String blockString = "{" ; //$NON-NLS-1$
293+ if (!commentsToPreserve .isEmpty () || needToManuallyAddNLS ) {
243294 if (blockEndOfLine || statementType == -1 ) {
244- // To ensure the comments to preserve end up on same line as the control statement, we need
245- // to build the block manually as a string and then create a Block placeholder from it
246- for (Comment comment : commentsToPreserve ) {
247- String commentString = cuBuffer .getText (comment .getStartPosition (), comment .getLength ());
248- blockString += " " + commentString ; //$NON-NLS-1$
295+ if (statementType == -1 && !blockEndOfLine ) {
296+ if (commentString .contains ("$NON-NLS-" )) { //$NON-NLS-1$
297+ return ; // we cannot handle non-block-end-of-line and NLS comment on if
298+ }
299+ blockString = commentString .trim () + System .lineSeparator () + blockString + System .lineSeparator () + "\t " + bodyString + System .lineSeparator () + "}" ; //$NON-NLS-1$ //$NON-NLS-2$
300+ } else {
301+ blockString += commentString + System .lineSeparator () + "\t " + bodyString + System .lineSeparator () + "}" ; //$NON-NLS-1$ //$NON-NLS-2$
249302 }
250- blockString += System .lineSeparator () + "\t " + bodyString + System .lineSeparator () + "}" ; //$NON-NLS-1$ //$NON-NLS-2$
251303 replacingBody = (Block )rewrite .createStringPlaceholder (blockString , ASTNode .BLOCK );
252304 } else {
253- Comment lastComment = commentsToPreserve .get (commentsToPreserve .size ()-1 );
254- String newControlStatement = cuBuffer .getText (cuRoot .getExtendedStartPosition (fControlStatement ),
255- lastComment .getStartPosition () + lastComment .getLength () - cuRoot .getExtendedStartPosition (fControlStatement ));
305+ String newControlStatement = "" ; //$NON-NLS-1$
306+ if (needToManuallyAddNLS ) {
307+ newControlStatement = cuBuffer .getText (cuRoot .getExtendedStartPosition (fControlStatement ),
308+ fBody .getStartPosition () - cuRoot .getExtendedStartPosition (fControlStatement )) + commentString ;
309+ } else {
310+ Comment lastComment = commentsToPreserve .get (commentsToPreserve .size ()-1 );
311+ newControlStatement = cuBuffer .getText (cuRoot .getExtendedStartPosition (fControlStatement ),
312+ lastComment .getStartPosition () + lastComment .getLength () - cuRoot .getExtendedStartPosition (fControlStatement ));
313+ }
256314 newControlStatement += System .lineSeparator () + "{" + System .lineSeparator (); //$NON-NLS-1$
257315 newControlStatement += "\t " + bodyString + System .lineSeparator () + "}" ; //$NON-NLS-1$ //$NON-NLS-2$
258316 Statement newStatement = (Statement )rewrite .createStringPlaceholder (newControlStatement , statementType );
@@ -267,6 +325,31 @@ public void rewriteASTInternal(CompilationUnitRewrite cuRewrite, LinkedProposalM
267325 rewrite .set (fControlStatement , fBodyProperty , replacingBody , group );
268326 }
269327
328+ private static Pattern nlsPattern = Pattern .compile ("//\\ s*\\ $NON-NLS-(\\ d+)\\ $" ); //$NON-NLS-1$
329+ private List <String > getLineNLSComments (int start , ASTNode node ) {
330+ ASTNode root = node .getRoot ();
331+ List <String > nlsList = new ArrayList <>();
332+ if (root instanceof CompilationUnit ) {
333+ CompilationUnit unit = (CompilationUnit )root ;
334+ int line = unit .getLineNumber (start );
335+ int endPosition = unit .getPosition (line + 1 , 0 );
336+ int length = endPosition - start ;
337+ IJavaElement element = unit .getJavaElement ();
338+ if (element != null && element instanceof ICompilationUnit icu ) {
339+ try {
340+ String statement = icu .getBuffer ().getText (start , length );
341+ Matcher m = nlsPattern .matcher (statement );
342+ while (m .find ()) {
343+ nlsList .add (m .group ());
344+ }
345+ } catch (IndexOutOfBoundsException | JavaModelException e ) {
346+ // do nothing
347+ }
348+ }
349+ }
350+ return nlsList ;
351+ }
352+
270353 }
271354
272355 static class RemoveBlockOperation extends CompilationUnitRewriteOperationWithSourceRange {
0 commit comments