KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > save > Commit


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.java.source.save;
20
21 import com.sun.source.tree.Tree;
22 import java.util.prefs.Preferences JavaDoc;
23 import javax.swing.text.BadLocationException JavaDoc;
24 import org.netbeans.api.java.lexer.JavaTokenId;
25 import org.netbeans.api.java.source.WorkingCopy;
26 import org.netbeans.api.lexer.TokenSequence;
27 import org.netbeans.modules.java.source.engine.EngineEnvironment;
28 import org.netbeans.modules.java.source.engine.ExternalModificationException;
29 import org.netbeans.modules.java.source.engine.ReadOnlyFilesException;
30 import org.netbeans.modules.java.source.engine.SourceReader;
31 import org.netbeans.modules.java.source.engine.SourceRewriter;
32 import org.netbeans.modules.java.source.save.SourceBuffer;
33 import org.netbeans.api.java.source.query.QueryEnvironment;
34 import org.netbeans.api.java.source.query.Query;
35 import org.netbeans.modules.java.source.engine.JavaFormatOptions;
36 import org.netbeans.modules.java.source.pretty.VeryPretty;
37 import org.netbeans.modules.java.source.pretty.ImportAnalysis;
38 import org.netbeans.modules.java.source.engine.PropertySheetInfo;
39
40 import com.sun.source.tree.CompilationUnitTree;
41
42 import com.sun.tools.javac.code.*;
43 import com.sun.tools.javac.tree.JCTree;
44 import com.sun.tools.javac.tree.JCTree.*;
45 import com.sun.tools.javac.tree.TreeInfo;
46 import com.sun.tools.javac.util.*;
47
48 import java.io.*;
49 import java.util.ArrayList JavaDoc;
50 import java.util.Set JavaDoc;
51 import java.util.logging.*;
52 import org.netbeans.modules.java.source.engine.ASTModel;
53 import org.netbeans.modules.java.source.engine.RootTree;
54
55 import static org.netbeans.modules.java.source.save.TreeDiff.ListType.*;
56 import static org.netbeans.modules.java.source.save.TreeDiff.DiffTypes.*;
57 import static org.netbeans.modules.java.source.save.TreeDiff.LineInsertionType.*;
58
59 /**
60  * Saves any modified class nodes as source files, with a goal of
61  * making the smallest delta to the original source file.
62  */

63 public class Commit extends Query<Void JavaDoc,Object JavaDoc> {
64     boolean displayedError;
65     Context context;
66     ASTModel model;
67     Symtab symtab;
68     Types types;
69     int lastMargin;
70     private EngineEnvironment ee;
71     private boolean fixImports;
72     private boolean forceReformat;
73     private static final int POSITION_OFFSET = 1;
74     private ArrayList JavaDoc<String JavaDoc> readOnlyFiles = new ArrayList JavaDoc<String JavaDoc>();
75
76     private static final Logger logger = Logger.getLogger("org.netbeans.modules.java.source");
77     private WorkingCopy workingCopy;
78     private TokenSequence<JavaTokenId> tokenSequence;
79
80     public Commit() {
81         displayedError = false;
82                Preferences JavaDoc prefs =
83             Preferences.userRoot().node(getClass().getName().replace('.','/'));
84         fixImports = prefs.getBoolean("fixImports", false);
85         forceReformat = prefs.getBoolean("forceReformat", false);
86     }
87     
88     public Commit(WorkingCopy workingCopy) {
89         this();
90         this.workingCopy = workingCopy;
91         this.tokenSequence = workingCopy.getTokenHierarchy().tokenSequence();
92     }
93
94     public boolean isEnabled(QueryEnvironment env) {
95         return env.getUndoList().getOld(env.getRootNode()) != null;
96     }
97
98     @Override JavaDoc
99     public void attach(QueryEnvironment env) {
100         super.attach(env);
101         ee = (EngineEnvironment)env;
102         context = ee.getContext();
103         symtab = ee.getSymbolTable();
104         types = Types.instance(context);
105         model = ((EngineEnvironment)env).getModel();
106     }
107     
108     public void apply() {
109         throw new AssertionError JavaDoc("use commit() instead");
110     }
111
112     public void commit() throws IOException {
113         if (getOriginalRoot() != getRootNode()) {
114             PropertySheetInfo.find(Commit.class).loadValues(this);
115             Options options = Options.instance(context);
116             apply(getRootNode());
117             if (readOnlyFiles.size() > 0)
118                 throwReadOnlyFilesException();
119         }
120     }
121     
122     private void throwReadOnlyFilesException() throws IOException {
123         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
124         for (String JavaDoc s : readOnlyFiles) {
125             sb.append(s);
126             sb.append('\n');
127         }
128         throw new ReadOnlyFilesException(sb.toString());
129     }
130     
131     private RootTree getOriginalRoot() {
132         RootTree root = (RootTree)getRootNode();
133         for (;;) {
134             RootTree oldRoot = (RootTree)env.getUndoList().getOld(root);
135             if (oldRoot != null)
136                 root = oldRoot;
137             else
138                 break;
139         }
140         return root;
141     }
142     
143     @Override JavaDoc
144     public Void JavaDoc visitCompilationUnit(CompilationUnitTree node, Object JavaDoc p) {
145         JCCompilationUnit topLevel = (JCCompilationUnit)node;
146         if (!isModified(topLevel))
147             return null;
148         
149         SourceRewriter out = null;
150         String JavaDoc srcFile = topLevel.sourcefile.toString();
151         boolean doReformat = forceReformat;
152         doReformat = false; //FIXME: remove line after reformat is working
153
boolean shouldSave = true;
154         try {
155             out = ((EngineEnvironment)env).getSourceRewriter(node.getSourceFile());
156         } catch (FileNotFoundException e) {
157             logger.warning("couldn\'t open original file: " + srcFile);
158             doReformat = true;
159         } catch (ExternalModificationException e) {
160             note("source file modified, reformatting: " + srcFile);
161             doReformat = true;
162         } catch (IOException e) {
163             logger.warning("couldn\'t write to original file: " + srcFile);
164             readOnlyFiles.add(srcFile);
165             return null;
166         }
167         logger.fine("original file: " + srcFile);
168
169         try {
170             if (doReformat)
171                 reformat(topLevel, out);
172             else
173                 commit(topLevel, out);
174             logger.info("Saved " + srcFile);
175         }
176         catch (IOException e) {
177             logError(e, topLevel);
178             displayedError = true;
179             shouldSave = false;
180         }
181         catch (Throwable JavaDoc err) {
182             error(err);
183         }
184         finally {
185             if (out != null)
186                 try {
187                     out.close(shouldSave);
188                 } catch (IOException e) {
189                     if (!displayedError)
190                         logError(e, topLevel);
191                 }
192         }
193         return null;
194     }
195     
196     private void logError(IOException e, JCCompilationUnit topLevel) {
197         Throwable JavaDoc err = (Throwable JavaDoc)(e.getCause() == null ? ((Throwable JavaDoc)(e))
198                                                          : e.getCause());
199         err.printStackTrace();
200         String JavaDoc msg = "Error writing " + getSourceFileName(topLevel) + ": " + err;
201         try {
202             logger.severe(msg);
203             msg = null;
204         }
205         catch (Throwable JavaDoc t) {
206         }
207         if (msg != null)
208             error(msg);
209     }
210
211     /**
212      * Pretty-print a specified compilation unit.
213      */

214     public void reformat(JCCompilationUnit topLevel, SourceRewriter out) throws IOException, BadLocationException JavaDoc {
215         PrettyPrinter pretty = new PrettyPrinter(context);
216         ImportAnalysis imports = new ImportAnalysis(pretty.options.starThreshold,
217                                                     pretty.options.useThreshold,
218                                                     topLevel, symtab, types);
219         imports.decideImports();
220         pretty.setImports(imports);
221         if (imports.containingClass != null)
222             pretty.enclClassName = imports.containingClass.name;
223         pretty.printUnit(topLevel);
224         out.writeTo(pretty.toString());
225     }
226
227     /**
228      * Commit a specified compilation unit's changes.
229      */

230     public void commit(CompilationUnitTree unit, SourceRewriter out) throws IOException, BadLocationException JavaDoc {
231         JCCompilationUnit topLevel = (JCCompilationUnit)unit;
232         SourceReader in = null;
233         try {
234             String JavaDoc srcFile = topLevel.sourcefile.toString();
235             SourceBuffer srcBuffer = new SourceBuffer(topLevel.sourcefile);
236             in = new SourceReader(srcBuffer.getChars());
237             JCCompilationUnit oldTL = (JCCompilationUnit)getOriginalTree(topLevel);
238             List JavaDoc<TreeDiff.Diff> diffs;
239             if ("jackpot-orig".equals(System.getProperty("generatorType"))) {
240                 diffs = TreeDiff.diff(context, workingCopy, oldTL, topLevel);
241             } else {
242                 diffs = CasualDiff.diff(context, workingCopy, oldTL, topLevel);
243             }
244             TokenList tokenList = TokenList.scan(context, srcFile, srcBuffer);
245
246             PrettyPrinter pretty = new PrettyPrinter(context);
247             // Copy any leading comments.
248
List JavaDoc<JCTree> defs = oldTL.defs;
249             while (diffs.nonEmpty() &&
250                    (defs.head == null || diffs.head.pos < defs.head.pos ||
251                     diffs.head.oldTree instanceof JCCompilationUnit)) {
252                 TreeDiff.Diff d = diffs.head;
253                 if (d.type != INSERT_COMMENT && d.type != MODIFY_COMMENT &&
254                     d.type != DELETE_COMMENT)
255                     break;
256                 applyCommentDiff(d, in, out, pretty, oldTL, srcBuffer);
257                 diffs = diffs.tail; // discard diff from list
258
}
259             for (; diffs.nonEmpty(); diffs = diffs.tail) {
260                 pretty.reset(0);
261                 TreeDiff.Diff d = (TreeDiff.Diff)diffs.head;
262                 if (shouldApplyDiff(d))
263                     switch (d.type) {
264                         case INSERT:
265                             out.copyTo(in, d.getPos());
266                             insertNewTree(d, in, out, pretty, d.pos, srcBuffer);
267                             break;
268                         case MODIFY:
269                             applyModifyDiff(d, in, out, pretty, oldTL, srcBuffer);
270                             break;
271                         case DELETE:
272                             removeOldTree(d, in, out, oldTL, srcBuffer);
273                             break;
274                         case NAME:
275                             changeName((TreeDiff.NameDiff)d, in, out);
276                             break;
277                         case FLAGS:
278                             changeFlags((TreeDiff.FlagsDiff)d, in, out, tokenList);
279                             break;
280                         case INSERT_OFFSET:
281                             TreeDiff.OffsetDiff od = (TreeDiff.OffsetDiff) d;
282                             out.copyTo(in, od.getStartOffset());
283                             if (od.getHead() != null) out.writeTo(od.getHead());
284                             if (d.getNew() != null) {
285                                 insertNewTree(d, in, out, pretty, d.pos, srcBuffer);
286                             }
287                             if (od.getTail() != null) out.writeTo(od.getTail());
288                             break;
289                         case DELETE_OFFSET:
290                             od = (TreeDiff.OffsetDiff) d;
291                             out.copyTo(in, od.getStartOffset());
292                             out.skipThrough(in, od.getEndOffset());
293                             break;
294                         case INSERT_TOKEN: {
295                             out.copyTo(in, d.getPos());
296                             TreeDiff.TokenDiff td = (TreeDiff.TokenDiff) d;
297                             if (td.getPreceding() != null) {
298                                 out.writeTo(td.getPreceding());
299                             }
300                             if (PARAMETER == td.getItemType()) {
301                                 pretty.printExpr(d.getNew(), TreeInfo.noPrec);
302                                 out.writeTo(pretty.toString());
303                             } else {
304                                 insertNewTree(d, in, out, pretty, d.pos, srcBuffer);
305                             }
306                             if (td.getTail() != null) {
307                                 out.writeTo(td.getTail());
308                             }
309                             break;
310                         }
311                         case DELETE_TOKEN: {
312                             int startPos = d.getOld().getStartPosition();
313                             int endPos = getOldEndPos(d.getOld(), oldTL, srcBuffer);
314                             TreeDiff.TokenDiff td = (TreeDiff.TokenDiff) d;
315                             if (td.getPreceding() != null) {
316                                 int pos = TokenUtilities.moveBackToToken(tokenSequence, startPos, td.getPreceding());
317                                 if (pos > 0) startPos = pos;
318                             }
319                             if (td.getTail() != null) {
320                                 int pos = TokenUtilities.moveFwdToToken(tokenSequence, endPos, td.getTail());
321                                 if (pos > 0) endPos = pos + tokenSequence.token().length();
322                             }
323                             if (in.getPos() < startPos) {
324                                 out.copyTo(in, startPos);
325                             }
326                             out.skipThrough(in, endPos);
327                             break;
328                         }
329                         case MODIFY_TOKEN:
330                             // apply just tree diff
331
if (d.getNew() != null && d.getOld() != null) {
332                                 int oldStartPos = removeOldTree(d, in, out, oldTL, srcBuffer);
333                                 if (PARAMETER == ((TreeDiff.TokenDiff) d).getItemType()) {
334                                     pretty.printExpr(d.getNew(), TreeInfo.noPrec);
335                                     out.writeTo(pretty.toString());
336                                 } else {
337                                     insertNewTree(d, in, out, pretty, oldStartPos, srcBuffer);
338                                 }
339                             } else {
340                                 TreeDiff.TokenDiff td = (TreeDiff.TokenDiff) d;
341                                 if (td.getNew() == null && td.getOld() != null) {
342                                     if (td.getPreceding() != null) {
343                                         TokenUtilities.movePrevious(tokenSequence, td.getOld().getStartPosition());
344                                     }
345                                     out.copyTo(in, tokenSequence.offset());
346                                     if (td.getTail() != null) {
347                                         TokenUtilities.moveNext(tokenSequence, d.getPos());
348                                         // hack - remove after TokenListUpdate
349
// will be fixed
350
tokenSequence.moveNext();
351                                         tokenSequence.movePrevious();
352                                         // end hack
353

354                                     }
355                                     out.skipThrough(in, tokenSequence.offset() + tokenSequence.token().length());
356                                 } else {
357                                     // print also package keyword
358
out.copyTo(in, d.getPos());
359                                     pretty.print(td.getPreceding());
360                                     pretty.print(td.getNew());
361                                     pretty.print(";\n\n");
362                                     out.writeTo(pretty.toString());
363                                 }
364                             }
365                             break;
366                         case INSERT_COMMENT:
367                         case MODIFY_COMMENT:
368                         case DELETE_COMMENT:
369                             applyCommentDiff(d, in, out, pretty, oldTL, srcBuffer);
370                             break;
371                         default:
372                             throw new AssertionError JavaDoc("unknown TreeDiff type: " + d.type);
373                     }
374             }
375             out.copyRest(in);
376         } finally {
377             if (in != null)
378                 in.close();
379         }
380     }
381
382     private void applyModifyDiff(TreeDiff.Diff d, SourceReader in, SourceRewriter out,
383                                   PrettyPrinter pretty, JCCompilationUnit oldTL,
384                                   SourceBuffer srcBuffer) throws IOException, BadLocationException JavaDoc {
385         // special handling for case where an else clause is added or removed.
386
if (d.oldTree.getKind() == Tree.Kind.IF && d.newTree.getKind() == Tree.Kind.IF) {
387             JCIf oldT = (JCIf)d.oldTree;
388             JCIf newT = (JCIf)d.newTree;
389             if (oldT.elsepart == null && newT.elsepart != null) {
390                 // add else clause
391
int endPos = getOldEndPos(oldT, oldTL, srcBuffer);
392                 out.copyTo(in, endPos);
393                 setIndent(pretty, endPos, srcBuffer);
394                 if (newT.elsepart.getKind() == Tree.Kind.BLOCK && pretty.options.cuddleElse)
395                     pretty.print(' ');
396                 else {
397                     pretty.blankline();
398                     pretty.toLeftMargin();
399                 }
400                 pretty.print("else ");
401                 newT.elsepart.accept(pretty);
402                 out.writeTo(pretty.toString());
403                 return;
404             }
405             else if (oldT.elsepart != null && newT.elsepart == null) {
406                 // remove else clause
407
int endPos = getOldEndPos(oldT.thenpart, oldTL, srcBuffer);
408                 out.copyTo(in, endPos);
409                 out.skipThrough(in, getOldEndPos(oldT, oldTL, srcBuffer));
410                 return;
411             }
412             // else fall-through
413
}
414         int oldStartPos = removeOldTree(d, in, out, oldTL, srcBuffer);
415         insertNewTree(d, in, out, pretty, oldStartPos, srcBuffer);
416     }
417
418     private void applyCommentDiff(TreeDiff.Diff d, SourceReader in, SourceRewriter out,
419                                   PrettyPrinter pretty, JCCompilationUnit oldTL,
420                                   SourceBuffer srcBuffer) throws IOException, BadLocationException JavaDoc {
421         int pos = d.oldComment != null ? d.oldComment.pos() :
422             getOldPos(d.oldTree);
423         int endPos = d.oldComment != null ? d.oldComment.endPos() :
424             getOldEndPos(d.oldTree, oldTL, srcBuffer);
425         out.copyTo(in, pos);
426         if (d.type == INSERT_COMMENT)
427             out.writeTo(d.newComment.getText());
428         else if (d.type == MODIFY_COMMENT) {
429             out.skipThrough(in, endPos);
430             out.writeTo(d.newComment.getText());
431         }
432         else if (d.type == DELETE_COMMENT)
433             out.skipThrough(in, endPos);
434         if (d.newLine == BEFORE) {
435             setIndent(pretty, pos, srcBuffer);
436             pretty.blankline();
437             pretty.toLeftMargin();
438             out.writeTo(pretty.toString());
439         }
440     }
441     
442     private boolean shouldApplyDiff(TreeDiff.Diff d) {
443         JCTree t = d.getOld();
444         if (t == null)
445             t = d.getNew();
446         return !fixImports || d.type == FLAGS || t.tag != JCTree.IMPORT;
447     }
448
449     private void insertNewTree(TreeDiff.Diff d, SourceReader in, SourceRewriter out,
450                                PrettyPrinter pretty, int oldStartPos, SourceBuffer srcBuffer)
451       throws IOException, BadLocationException JavaDoc {
452         /** Don't print class or method bodies if the
453          * change is in their declaration header. If there are
454          * changed child trees, separate diffs will handle them.
455          */

456         boolean printBody = d.type != NAME && d.type != FLAGS;
457         pretty.setPrintBody(printBody);
458         setIndent(pretty, oldStartPos, srcBuffer);
459         if (d.newLine == BEFORE) {
460             pretty.blankline();
461             pretty.toLeftMargin();
462         }
463         Name oldOwning = pretty.enclClassName;
464         
465         try {
466             if (d.owningClassName != null)
467                 pretty.enclClassName = d.owningClassName;
468             
469                 d.getNew().accept(pretty);
470         } finally {
471             pretty.enclClassName = oldOwning;
472         }
473         
474         if (d.newLine == AFTER) {
475             pretty.newline();
476             pretty.toLeftMargin();
477         }
478         out.writeTo(pretty.toString());
479     }
480
481     private int removeOldTree(TreeDiff.Diff d, SourceReader in, SourceRewriter out,
482                               JCCompilationUnit oldTL, SourceBuffer srcBuffer)
483       throws IOException, BadLocationException JavaDoc {
484         JCTree oldT = d.getOld();
485         int oldStartPos = getOldPos(oldT);
486         out.copyTo(in, oldStartPos);
487         out.skipThrough(in, getOldEndPos(oldT, oldTL, srcBuffer));
488         return oldStartPos;
489     }
490
491     private static void changeName(TreeDiff.NameDiff d, SourceReader in, SourceRewriter out)
492       throws IOException, BadLocationException JavaDoc {
493         out.copyTo(in, d.getPos());
494         out.skipThrough(in, d.getPos() + d.getOldName().length());
495         out.writeTo(d.getNewName());
496     }
497     
498     private void changeFlags(TreeDiff.FlagsDiff d, SourceReader in, SourceRewriter out,
499                              TokenList tokenList) throws IOException, BadLocationException JavaDoc {
500         int startPos = d.getPos();
501         out.copyTo(in, startPos);
502         
503         // if any old flags or annotations exist, delete just the flags
504
boolean hasOldFlags = (d.getOldEndPos() - startPos) > 0;
505         if (hasOldFlags) {
506             int first = tokenList.indexOf(startPos);
507             int last = tokenList.indexOfEndPos(d.getOldEndPos());
508             assert first != -1 && last != -1;
509             boolean hadAnnotation = false;
510             for (int i = first; i <= last; i++) {
511                 // remove all flags, but leave any annotations or import keyword
512
TokenList.Token tok = tokenList.get(i);
513                 if (tok.isFlag()) {
514                     if (hadAnnotation) {
515                         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
516                         while (true) {
517                             int c = in.read();
518                             if (c != -1 && Character.isWhitespace(c))
519                                 sb.append((char)c);
520                             else
521                                 break;
522                         }
523                         if (sb.length() > 0)
524                             out.writeTo(sb.toString());
525                     }
526                     out.skipThrough(in, tok.getEndPos());
527                 }
528                 else
529                     out.copyTo(in, tok.getEndPos());
530                 hadAnnotation = tok.isIdentifier();
531             }
532             out.skipThrough(in, tokenList.get(last + 1).getPos());
533         }
534         
535         // append the new flags
536
String JavaDoc s = TreeInfo.flagNames(d.getNewFlags());
537         if (s.length() > 0) {
538             out.writeTo(s);
539             out.writeTo(" ");
540         }
541     }
542
543     static String JavaDoc getSourceFileName(JCCompilationUnit topLevel) {
544         JCClassDecl mainClass = getMainClassDef(topLevel);
545         return mainClass.sym.fullname.toString().replace('.', File.separatorChar)
546             + ".java";
547     }
548     
549     /**
550      * Either return the public ClassDef defined in a JCCompilationUnit, or the
551      * first non-public class if none are public.
552      */

553     static JCClassDecl getMainClassDef(JCCompilationUnit topLevel) {
554         List JavaDoc<JCTree> defs = topLevel.defs;
555         JCClassDecl topClass = null;
556         while(defs.nonEmpty()) {
557             if (defs.head.tag == JCTree.CLASSDEF) {
558                 JCClassDecl tree = (JCClassDecl)defs.head;
559                 if ((tree.mods.flags & Flags.PUBLIC) != 0)
560                     return tree;
561                 topClass = tree;
562             }
563             defs = defs.tail;
564         }
565         return topClass;
566     }
567
568     int getOldEndPos(JCTree oldT, JCCompilationUnit oldTL, SourceBuffer srcbuf) {
569         if (oldT == null || oldTL == null)
570             return Query.NOPOS;
571         int pos = model.getEndPos(oldT, oldTL);
572         assert pos != Query.NOPOS;
573         if (oldT.tag == JCTree.VARDEF && srcbuf.src[pos-1] == ';')
574             // workaround for parser end-position bug
575
pos--;
576         if (false) { // debugging aid
577
String JavaDoc kind = ((com.sun.source.tree.Tree)oldT).getKind().toString();
578             if (pos == oldT.pos && oldT.tag != JCTree.SKIP)
579                 logger.info("no endPos for " + kind + " \"" + oldT.toString() + "\"");
580             else
581                 logger.finer("endPos for " + kind + ": " + pos);
582         }
583         return pos;
584     }
585
586     /**
587      * Guess-timate what the margin for an inserted tree should be.
588      * If it's a replacement, use the margin from the old tree.
589      * Otherwise, get the lastMargin read from the original source.
590      */

591     void setIndent(PrettyPrinter pretty, int oldStartPos, SourceBuffer srcBuffer) {
592         if (oldStartPos != Query.NOPOS) {
593             int lineNo = srcBuffer.getLineNumber(oldStartPos);
594             char[] line = srcBuffer.getLine(lineNo);
595             lastMargin = getMargin(line);
596         }
597         pretty.reset(lastMargin);
598     }
599
600     CompilationUnitTree getOriginalTree(final CompilationUnitTree t) {
601         RootTree oldRoot = getOriginalRoot();
602         for (CompilationUnitTree unit : oldRoot.getCompilationUnits())
603             if (unit.getSourceFile() == t.getSourceFile())
604                     return unit;
605         return t;
606     }
607
608     private int getOldPos(JCTree oldT) {
609         return TreeDiff.getOldPos(oldT, model, env.getUndoList());
610     }
611
612     private static boolean isDefaultConstructor(JCMethodDecl tree) {
613         return tree.sym.isConstructor() && tree.params.isEmpty();
614     }
615
616     // FIXME: add options for sorting preferences.
617
protected void printSortedImports(boolean fixImports,
618                                       PrettyPrinter pretty,
619                                       Set JavaDoc<Symbol> missingImports,
620                                       SourceRewriter out) throws IOException, BadLocationException JavaDoc {
621         if (fixImports)
622             pretty.printImports(false); // don't print package statement
623
else
624             pretty.printImports(missingImports);
625         StringWriter sw = new StringWriter();
626         pretty.writeTo(sw);
627         String JavaDoc unsortedImports = sw.toString();
628         BufferedReader br =
629             new BufferedReader(new StringReader(unsortedImports));
630         java.util.TreeSet JavaDoc<String JavaDoc> sorter = new java.util.TreeSet JavaDoc<String JavaDoc>();
631         String JavaDoc line;
632         while ((line = br.readLine()) != null && line.length() > 0)
633             sorter.add(line);
634         java.util.Iterator JavaDoc<String JavaDoc> iter = sorter.iterator();
635         while (iter.hasNext())
636             out.writeTo(iter.next() + '\n');
637     }
638     
639     private int getMargin(char[] line) {
640         int margin = 0;
641         int i = 0;
642         while (i < line.length) {
643             char c = line[i];
644             if (c != ' ' && c != '\t')
645                 break;
646             margin = calculateColumn(margin, c);
647             i++;
648         }
649         return margin;
650     }
651
652     /**
653      * Given a current column position and a character, return the
654      * new column position. One-based column positions are used,
655      * like javac.
656      */

657     private int calculateColumn(int curCol, char ch) {
658         if (ch == '\f' || ch == '\n')
659             return POSITION_OFFSET;
660         else if (ch == '\t')
661             return (((curCol - 1) / 8 * 8) + 8) + POSITION_OFFSET;
662         return curCol + POSITION_OFFSET;
663     }
664
665     public boolean isModified(JCCompilationUnit tree) {
666         return getOriginalTree(tree) != tree;
667     }
668
669     static class PrettyPrinter extends VeryPretty {
670         boolean printBody;
671         
672         PrettyPrinter(Context context) {
673             super(context);
674             printBody = true;
675         }
676         
677         public void toLeftMargin() {
678             super.toLeftMargin();
679         }
680
681         void setPrintBody(boolean b) {
682             printBody = b;
683         }
684
685         protected void printClassBody(JCClassDecl tree) {
686             if (printBody)
687                 super.printClassBody(tree);
688         }
689
690         protected void printMethodBody(JCMethodDecl tree) {
691             if (printBody)
692                 super.printMethodBody(tree);
693         }
694
695         protected void printVarBody(JCVariableDecl tree) {
696             if (printBody)
697                 super.printVarBody(tree);
698         }
699     }
700     
701 }
702
Popular Tags