This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 255214
Collapse All | Expand All

(-)a/java.source.base/nbproject/project.properties (-1 / +1 lines)
Lines 47-53 Link Here
47
javadoc.title=Java Source Base
47
javadoc.title=Java Source Base
48
javadoc.arch=${basedir}/arch.xml
48
javadoc.arch=${basedir}/arch.xml
49
javadoc.apichanges=${basedir}/apichanges.xml
49
javadoc.apichanges=${basedir}/apichanges.xml
50
spec.version.base=2.8.0
50
spec.version.base=2.9.0
51
test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar
51
test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar
52
test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\
52
test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\
53
    ${o.n.core.dir}/lib/boot.jar:\
53
    ${o.n.core.dir}/lib/boot.jar:\
(-)a/java.source.base/nbproject/project.xml (+9 lines)
Lines 154-159 Link Here
154
                    </run-dependency>
154
                    </run-dependency>
155
                </dependency>
155
                </dependency>
156
                <dependency>
156
                <dependency>
157
                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
158
                    <build-prerequisite/>
159
                    <compile-dependency/>
160
                    <run-dependency>
161
                        <release-version>3</release-version>
162
                        <specification-version>4.3</specification-version>
163
                    </run-dependency>
164
                </dependency>
165
                <dependency>
157
                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
166
                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
158
                    <build-prerequisite/>
167
                    <build-prerequisite/>
159
                    <compile-dependency/>
168
                    <compile-dependency/>
(-)a/java.source.base/src/org/netbeans/api/java/source/GeneratorUtilities.java (-4 / +173 lines)
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:

Return to bug 255214