Lines 46-52
Link Here
|
46 |
|
46 |
|
47 |
import com.sun.source.tree.AnnotatedTypeTree; |
47 |
import com.sun.source.tree.AnnotatedTypeTree; |
48 |
import com.sun.source.tree.AnnotationTree; |
48 |
import com.sun.source.tree.AnnotationTree; |
49 |
import com.sun.source.tree.ArrayAccessTree; |
|
|
50 |
import com.sun.source.tree.ArrayTypeTree; |
49 |
import com.sun.source.tree.ArrayTypeTree; |
51 |
import com.sun.source.tree.AssignmentTree; |
50 |
import com.sun.source.tree.AssignmentTree; |
52 |
import com.sun.source.tree.BlockTree; |
51 |
import com.sun.source.tree.BlockTree; |
Lines 54-60
Link Here
|
54 |
import com.sun.source.tree.CaseTree; |
53 |
import com.sun.source.tree.CaseTree; |
55 |
import com.sun.source.tree.ClassTree; |
54 |
import com.sun.source.tree.ClassTree; |
56 |
import com.sun.source.tree.CompilationUnitTree; |
55 |
import com.sun.source.tree.CompilationUnitTree; |
57 |
import com.sun.source.tree.CompoundAssignmentTree; |
|
|
58 |
import com.sun.source.tree.ErroneousTree; |
56 |
import com.sun.source.tree.ErroneousTree; |
59 |
import com.sun.source.tree.ExpressionTree; |
57 |
import com.sun.source.tree.ExpressionTree; |
60 |
import com.sun.source.tree.IdentifierTree; |
58 |
import com.sun.source.tree.IdentifierTree; |
Lines 62-70
Link Here
|
62 |
import com.sun.source.tree.InstanceOfTree; |
60 |
import com.sun.source.tree.InstanceOfTree; |
63 |
import com.sun.source.tree.LabeledStatementTree; |
61 |
import com.sun.source.tree.LabeledStatementTree; |
64 |
import com.sun.source.tree.LiteralTree; |
62 |
import com.sun.source.tree.LiteralTree; |
65 |
import com.sun.source.tree.MemberReferenceTree; |
|
|
66 |
import com.sun.source.tree.MemberSelectTree; |
63 |
import com.sun.source.tree.MemberSelectTree; |
67 |
import com.sun.source.tree.MethodInvocationTree; |
|
|
68 |
import com.sun.source.tree.MethodTree; |
64 |
import com.sun.source.tree.MethodTree; |
69 |
import com.sun.source.tree.ModifiersTree; |
65 |
import com.sun.source.tree.ModifiersTree; |
70 |
import com.sun.source.tree.NewArrayTree; |
66 |
import com.sun.source.tree.NewArrayTree; |
Lines 144-149
Link Here
|
144 |
import org.netbeans.api.lexer.TokenHierarchy; |
140 |
import org.netbeans.api.lexer.TokenHierarchy; |
145 |
import org.netbeans.api.lexer.TokenSequence; |
141 |
import org.netbeans.api.lexer.TokenSequence; |
146 |
import org.netbeans.api.queries.FileEncodingQuery; |
142 |
import org.netbeans.api.queries.FileEncodingQuery; |
|
|
143 |
import org.netbeans.editor.GuardedDocument; |
147 |
import org.netbeans.modules.java.source.builder.CommentHandlerService; |
144 |
import org.netbeans.modules.java.source.builder.CommentHandlerService; |
148 |
import org.netbeans.modules.java.source.builder.CommentSetImpl; |
145 |
import org.netbeans.modules.java.source.builder.CommentSetImpl; |
149 |
import org.netbeans.modules.java.source.parsing.AbstractSourceFileObject; |
146 |
import org.netbeans.modules.java.source.parsing.AbstractSourceFileObject; |
Lines 334-339
Link Here
|
334 |
} |
331 |
} |
335 |
return copy.getTreeMaker().insertClassMember(clazz, idx, member); |
332 |
return copy.getTreeMaker().insertClassMember(clazz, idx, member); |
336 |
} |
333 |
} |
|
|
334 |
|
335 |
/** |
336 |
* Inserts members to a class. Using the rules specified in the {@link CodeStyle} |
337 |
* it finds the proper place for each of the members and calls {@link TreeMaker.insertClassMember} |
338 |
* |
339 |
* @param clazz the class to insert the members to |
340 |
* @param members the members to insert |
341 |
* @param offset the caret location to use for {@code CodeStyle.InsertionPoint.CARET_LOCATION} |
342 |
* @return the modified class |
343 |
* @since 2.9 |
344 |
*/ |
345 |
public ClassTree insertClassMembers(ClassTree clazz, List<? extends Tree> members, int offset) { |
346 |
if (members.isEmpty()) { |
347 |
return clazz; |
348 |
} |
349 |
CodeStyle codeStyle = DiffContext.getCodeStyle(copy); |
350 |
if (offset < 0 || codeStyle.getClassMemberInsertionPoint() != CodeStyle.InsertionPoint.CARET_LOCATION) { |
351 |
return GeneratorUtilities.get(copy).insertClassMembers(clazz, members); |
352 |
} |
353 |
int index = 0; |
354 |
SourcePositions sp = copy.getTrees().getSourcePositions(); |
355 |
GuardedDocument gdoc = null; |
356 |
try { |
357 |
Document doc = copy.getDocument(); |
358 |
if (doc != null && doc instanceof GuardedDocument) { |
359 |
gdoc = (GuardedDocument)doc; |
360 |
} |
361 |
} catch (IOException ioe) {} |
362 |
Tree lastMember = null; |
363 |
Tree nextMember = null; |
364 |
for (Tree tree : clazz.getMembers()) { |
365 |
if (offset <= sp.getStartPosition(copy.getCompilationUnit(), tree)) { |
366 |
if (gdoc == null) { |
367 |
nextMember = tree; |
368 |
break; |
369 |
} |
370 |
int pos = (int)(lastMember != null ? sp.getEndPosition(copy.getCompilationUnit(), lastMember) : sp.getStartPosition(copy.getCompilationUnit(), clazz)); |
371 |
pos = gdoc.getGuardedBlockChain().adjustToBlockEnd(pos); |
372 |
if (pos <= sp.getStartPosition(copy.getCompilationUnit(), tree)) { |
373 |
nextMember = tree; |
374 |
break; |
375 |
} |
376 |
} |
377 |
index++; |
378 |
lastMember = tree; |
379 |
} |
380 |
if (lastMember != null) { |
381 |
// do not move the comments tied to last member in guarded block: |
382 |
moveCommentsAfterOffset(copy, lastMember, members.get(0), offset, gdoc); |
383 |
} |
384 |
if (nextMember != null) { |
385 |
moveCommentsBeforeOffset(copy, nextMember, members.get(members.size() - 1), offset, gdoc); |
386 |
} |
387 |
TreeMaker tm = copy.getTreeMaker(); |
388 |
ClassTree newClazz = clazz; |
389 |
for (int i = members.size() - 1; i >= 0; i--) { |
390 |
newClazz = tm.insertClassMember(newClazz, index, members.get(i)); |
391 |
} |
392 |
return newClazz; |
393 |
} |
394 |
|
395 |
/** |
396 |
* Inserts a member to a class. Using the rules specified in the {@link CodeStyle} |
397 |
* it finds the proper place for the member and calls {@link TreeMaker.insertClassMember} |
398 |
* |
399 |
* @param clazz the class to insert the member to |
400 |
* @param member the member to add |
401 |
* @param offset the caret location to use for {@code CodeStyle.InsertionPoint.CARET_LOCATION} |
402 |
* @return the modified class |
403 |
* @since 2.9 |
404 |
*/ |
405 |
public ClassTree insertClassMember(ClassTree clazz, Tree member, int offset) { |
406 |
return insertClassMembers(clazz, Collections.singletonList(member), offset); |
407 |
} |
408 |
|
409 |
/** |
410 |
* Reparents comments that follow `from' tree and would be separated from that tree by insertion to `offset' position. |
411 |
* The comments are removed from the original tree, and attached to the `to' inserted tree. |
412 |
* @param wc the working copy |
413 |
* @param from the current owner of the comments |
414 |
* @param to the generated code |
415 |
* @param offset the offset where the new code will be inserted |
416 |
* @param gdoc guarded document instance or {@code null} |
417 |
* @return |
418 |
*/ |
419 |
private void moveCommentsAfterOffset(WorkingCopy wc, Tree from, Tree to, int offset, GuardedDocument gdoc) { |
420 |
List<Comment> toMove = new LinkedList<>(); |
421 |
int idx = 0; |
422 |
int firstToRemove = -1; |
423 |
for (Comment comment : wc.getTreeUtilities().getComments(from, false)) { |
424 |
if (comment.endPos() <= offset) { |
425 |
// not affected by insertion |
426 |
idx++; |
427 |
continue; |
428 |
} |
429 |
if (gdoc != null) { |
430 |
int epAfterBlock = gdoc.getGuardedBlockChain().adjustToBlockEnd(comment.endPos()); |
431 |
// comment that ends exactly at the GB boundary cannot be really |
432 |
// reassigned from the previous member. |
433 |
if (epAfterBlock >= comment.endPos()) { |
434 |
// set new offset, after the guarded block |
435 |
idx++; |
436 |
continue; |
437 |
} |
438 |
} |
439 |
toMove.add(comment); |
440 |
if (firstToRemove == -1) { |
441 |
firstToRemove = idx; |
442 |
} |
443 |
idx++; |
444 |
} |
445 |
if (toMove.isEmpty()) { |
446 |
return; |
447 |
} |
448 |
doMoveComments(wc, from, to, offset, toMove, firstToRemove, idx); |
449 |
} |
450 |
|
451 |
private static void doMoveComments(WorkingCopy wc, Tree from, Tree to, int offset, List<Comment> comments, int fromIdx, int toIdx) { |
452 |
if (comments.isEmpty()) { |
453 |
return; |
454 |
} |
455 |
TreeMaker tm = wc.getTreeMaker(); |
456 |
Tree tree = from; |
457 |
switch (from.getKind()) { |
458 |
case METHOD: |
459 |
tree = tm.setLabel(from, ((MethodTree)from).getName()); |
460 |
break; |
461 |
case VARIABLE: |
462 |
tree = tm.setLabel(from, ((VariableTree)from).getName()); |
463 |
break; |
464 |
case BLOCK: |
465 |
tree = tm.Block(((BlockTree)from).getStatements(), ((BlockTree)from).isStatic()); |
466 |
GeneratorUtilities gu = GeneratorUtilities.get(wc); |
467 |
gu.copyComments(from, tree, true); |
468 |
gu.copyComments(from, tree, false); |
469 |
break; |
470 |
} |
471 |
boolean before = (int)wc.getTrees().getSourcePositions().getStartPosition(wc.getCompilationUnit(), from) >= offset; |
472 |
if (fromIdx >=0 && toIdx >= 0 && toIdx - fromIdx > 0) { |
473 |
for (int i = toIdx - 1; i >= fromIdx; i--) { |
474 |
tm.removeComment(tree, i, before); |
475 |
} |
476 |
} |
477 |
wc.rewrite(from, tree); |
478 |
for (Comment comment : comments) { |
479 |
tm.addComment(to, comment, comment.pos() <= offset); |
480 |
} |
481 |
} |
482 |
|
483 |
private static void moveCommentsBeforeOffset(WorkingCopy wc, Tree from, Tree to, int offset, GuardedDocument gdoc) { |
484 |
List<Comment> toMove = new LinkedList<Comment>(); |
485 |
int idx = 0; |
486 |
for (Comment comment : wc.getTreeUtilities().getComments(from, true)) { |
487 |
if (comment.pos() >= offset || comment.endPos() > offset) |
488 |
break; |
489 |
|
490 |
if (gdoc != null) { |
491 |
int epAfterBlock = gdoc.getGuardedBlockChain().adjustToBlockEnd(comment.pos()); |
492 |
// comment that ends exactly at the GB boundary cannot be really |
493 |
// reassigned from the previous member. |
494 |
if (epAfterBlock >= comment.endPos()) { |
495 |
// set new offset, after the guarded block |
496 |
break; |
497 |
} |
498 |
} |
499 |
toMove.add(comment); |
500 |
idx++; |
501 |
} |
502 |
if (toMove.size() > 0) { |
503 |
doMoveComments(wc, from, to, offset, toMove, 0, idx); |
504 |
} |
505 |
} |
337 |
|
506 |
|
338 |
/** |
507 |
/** |
339 |
* Visitor which collects references to class' members. It operates in two modes: |
508 |
* Visitor which collects references to class' members. It operates in two modes: |