~ubuntu-branches/ubuntu/trusty/netbeans/trusty

« back to all changes in this revision

Viewing changes to java/hints/src/org/netbeans/modules/java/hints/Braces.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * Portions Copyrighted 2007 Sun Microsystems, Inc.
 
27
 */
 
28
package org.netbeans.modules.java.hints;
 
29
 
 
30
import com.sun.source.tree.BlockTree;
 
31
import com.sun.source.tree.DoWhileLoopTree;
 
32
import com.sun.source.tree.EnhancedForLoopTree;
 
33
import com.sun.source.tree.ExpressionStatementTree;
 
34
import com.sun.source.tree.ForLoopTree;
 
35
import com.sun.source.tree.IfTree;
 
36
import com.sun.source.tree.IfTree;
 
37
import com.sun.source.tree.StatementTree;
 
38
import com.sun.source.tree.Tree;
 
39
import com.sun.source.tree.Tree.Kind;
 
40
import com.sun.source.tree.WhileLoopTree;
 
41
import com.sun.source.util.TreePath;
 
42
import java.io.IOException;
 
43
import java.util.ArrayList;
 
44
import java.util.Collections;
 
45
import java.util.EnumSet;
 
46
import java.util.List;
 
47
import java.util.Set;
 
48
import org.netbeans.api.java.lexer.JavaTokenId;
 
49
import org.netbeans.api.java.source.Task;
 
50
import org.netbeans.api.java.source.CompilationInfo;
 
51
import org.netbeans.api.java.source.JavaSource;
 
52
import org.netbeans.api.java.source.TreeMaker;
 
53
import org.netbeans.api.java.source.TreePathHandle;
 
54
import org.netbeans.api.java.source.WorkingCopy;
 
55
import org.netbeans.modules.java.hints.spi.AbstractHint;
 
56
import org.netbeans.spi.editor.hints.ChangeInfo;
 
57
import org.netbeans.spi.editor.hints.ErrorDescription;
 
58
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
 
59
import org.netbeans.spi.editor.hints.Fix;
 
60
import org.openide.filesystems.FileObject;
 
61
import org.openide.util.Exceptions;
 
62
import org.openide.util.NbBundle;
 
63
 
 
64
/**
 
65
 *
 
66
 * @author phrebejk
 
67
 */
 
68
public class Braces extends AbstractHint {
 
69
 
 
70
    static final EnumSet<JavaTokenId> nonRelevant = EnumSet.<JavaTokenId>of(
 
71
            JavaTokenId.LINE_COMMENT, 
 
72
            JavaTokenId.BLOCK_COMMENT,
 
73
            JavaTokenId.JAVADOC_COMMENT,
 
74
            JavaTokenId.WHITESPACE
 
75
    );
 
76
    
 
77
    private static final List<Fix> NO_FIXES = Collections.<Fix>emptyList();
 
78
    
 
79
    private String BRACES_ID = "Braces_"; // NOI18N
 
80
    
 
81
    private Tree.Kind treeKind;
 
82
    private Set<Tree.Kind> treeKinds;
 
83
    
 
84
    private Braces( Tree.Kind treeKind ) {
 
85
        super( false, true, HintSeverity.WARNING );
 
86
        this.treeKind = treeKind;
 
87
        if ( treeKind == Tree.Kind.FOR_LOOP ) {
 
88
            this.treeKinds = EnumSet.<Tree.Kind>of(treeKind, Tree.Kind.ENHANCED_FOR_LOOP);
 
89
        } 
 
90
        else {
 
91
            this.treeKinds = Collections.<Tree.Kind>singleton(treeKind);
 
92
        }
 
93
    }
 
94
 
 
95
    public static Braces createFor() {
 
96
        return new Braces( Tree.Kind.FOR_LOOP );
 
97
    }
 
98
    
 
99
    public static Braces createWhile() {
 
100
        return new Braces( Tree.Kind.WHILE_LOOP );
 
101
    }
 
102
    
 
103
    public static Braces createDoWhile() {
 
104
        return new Braces( Tree.Kind.DO_WHILE_LOOP );
 
105
    }
 
106
    
 
107
    public static Braces createIf() {
 
108
        return new Braces( Tree.Kind.IF );
 
109
    }
 
110
    
 
111
    public Set<Kind> getTreeKinds() {
 
112
        return treeKinds;
 
113
    }
 
114
 
 
115
    public List<ErrorDescription> run(CompilationInfo compilationInfo, TreePath treePath) {
 
116
        
 
117
        Tree tree = treePath.getLeaf();
 
118
        
 
119
        ErrorDescription ed = null;
 
120
                
 
121
        switch( tree.getKind() ) {
 
122
            case FOR_LOOP:
 
123
                ForLoopTree flt = (ForLoopTree) tree;
 
124
                ed = checkStatement(flt.getStatement(), treePath, compilationInfo);
 
125
                if ( ed != null ) {                    
 
126
                    return Collections.singletonList(ed);
 
127
                }
 
128
                break;
 
129
            case ENHANCED_FOR_LOOP:
 
130
                EnhancedForLoopTree eflt = (EnhancedForLoopTree) tree;
 
131
                ed = checkStatement( eflt.getStatement(), treePath, compilationInfo );
 
132
                if ( ed != null ) {                    
 
133
                    return Collections.singletonList(ed);
 
134
                }
 
135
                break;
 
136
            case WHILE_LOOP:
 
137
                WhileLoopTree wlt = (WhileLoopTree) tree;
 
138
                ed = checkStatement( wlt.getStatement(), treePath, compilationInfo);
 
139
                if ( ed != null ) {                    
 
140
                    return Collections.singletonList(ed);
 
141
                }
 
142
                break;
 
143
            case DO_WHILE_LOOP:
 
144
                DoWhileLoopTree dwlt = (DoWhileLoopTree) tree;
 
145
                ed = checkStatement( dwlt.getStatement(), treePath, compilationInfo);
 
146
                if ( ed != null ) {                    
 
147
                    return Collections.singletonList(ed);  
 
148
                }
 
149
                break;
 
150
            case IF:
 
151
                IfTree it = (IfTree)tree;
 
152
                List<ErrorDescription> eds = checkifStatements(it.getThenStatement(), it.getElseStatement(), treePath, compilationInfo );
 
153
                return eds;
 
154
        }
 
155
        
 
156
        return Collections.<ErrorDescription>emptyList();
 
157
    }
 
158
        
 
159
    public void cancel() {
 
160
        
 
161
    }
 
162
 
 
163
    public String getId() {
 
164
        return BRACES_ID + treeKind;
 
165
    }
 
166
    
 
167
    public String getDisplayName() {
 
168
        switch( treeKind ) {
 
169
            case FOR_LOOP:
 
170
                return NbBundle.getMessage(Braces.class, "LBL_Braces_For"); // NOI18N
 
171
            case WHILE_LOOP:
 
172
                return NbBundle.getMessage(Braces.class, "LBL_Braces_While"); // NOI18N
 
173
            case DO_WHILE_LOOP:
 
174
                return NbBundle.getMessage(Braces.class, "LBL_Braces_DoWhile"); // NOI18N
 
175
            case IF:
 
176
                return NbBundle.getMessage(Braces.class, "LBL_Braces_If"); // NOI18N
 
177
            default:
 
178
                return "No Name"; // NOI18N
 
179
        }        
 
180
    }
 
181
 
 
182
    public String getDescription() {
 
183
        switch( treeKind ) {
 
184
            case FOR_LOOP:
 
185
                return NbBundle.getMessage(Braces.class, "DSC_Braces_For"); // NOI18N
 
186
            case WHILE_LOOP:
 
187
                return NbBundle.getMessage(Braces.class, "DSC_Braces_While"); // NOI18N
 
188
            case DO_WHILE_LOOP:
 
189
                return NbBundle.getMessage(Braces.class, "DSC_Braces_DoWhile"); // NOI18N
 
190
            case IF:
 
191
                return NbBundle.getMessage(Braces.class, "DSC_Braces_If"); // NOI18N
 
192
            default:
 
193
                return "No Description"; // NOI18N
 
194
        }            
 
195
    }
 
196
    
 
197
    // Private methods ---------------------------------------------------------
 
198
    
 
199
    private ErrorDescription checkStatement( StatementTree statement, TreePath tp, CompilationInfo info )  {
 
200
                
 
201
        if ( statement != null && 
 
202
             statement.getKind() != Tree.Kind.EMPTY_STATEMENT && 
 
203
             statement.getKind() != Tree.Kind.BLOCK &&
 
204
             statement.getKind() != Tree.Kind.ERRONEOUS &&
 
205
             !isErroneousExpression( statement ) ) {
 
206
            return ErrorDescriptionFactory.createErrorDescription(
 
207
                        getSeverity().toEditorSeverity(), 
 
208
                        getDisplayName(), 
 
209
                        Collections.<Fix>singletonList(new BracesFix( info.getFileObject(), TreePathHandle.create(tp, info) ) ), 
 
210
                        info.getFileObject(),
 
211
                        (int)info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), statement ),
 
212
                        (int)info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), statement ) );
 
213
                    
 
214
        }        
 
215
        return null;
 
216
    }
 
217
    
 
218
    
 
219
    private List<ErrorDescription> checkifStatements( StatementTree thenSt, StatementTree elseSt, TreePath tp, CompilationInfo info )  {
 
220
        
 
221
        boolean fixThen = false;
 
222
        boolean fixElse = false;
 
223
        
 
224
        if ( thenSt != null && 
 
225
             thenSt.getKind() != Tree.Kind.EMPTY_STATEMENT && 
 
226
             thenSt.getKind() != Tree.Kind.BLOCK &&
 
227
             thenSt.getKind() != Tree.Kind.ERRONEOUS &&
 
228
             !isErroneousExpression( thenSt )) {
 
229
            fixThen = true;
 
230
        }
 
231
        
 
232
        if ( elseSt != null && 
 
233
             elseSt.getKind() != Tree.Kind.EMPTY_STATEMENT && 
 
234
             elseSt.getKind() != Tree.Kind.BLOCK &&
 
235
             elseSt.getKind() != Tree.Kind.ERRONEOUS &&
 
236
             elseSt.getKind() != Tree.Kind.IF &&
 
237
             !isErroneousExpression( elseSt )) {
 
238
            fixElse = true;
 
239
        }
 
240
        
 
241
        List<ErrorDescription> result = new ArrayList<ErrorDescription>();
 
242
        
 
243
        if ( fixThen ) {
 
244
            BracesFix bf  = new BracesFix( info.getFileObject(), TreePathHandle.create(tp, info));
 
245
            bf.fixThen = fixThen;
 
246
            bf.fixElse = fixElse;
 
247
            result.add( ErrorDescriptionFactory.createErrorDescription(
 
248
                getSeverity().toEditorSeverity(), 
 
249
                getDisplayName(), 
 
250
                Collections.<Fix>singletonList( bf ), 
 
251
                info.getFileObject(),
 
252
                (int)info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), thenSt ),
 
253
                (int)info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), thenSt ) ) ); 
 
254
        }
 
255
        
 
256
        if ( fixElse ) {
 
257
            BracesFix bf  = new BracesFix( info.getFileObject(), TreePathHandle.create(tp, info));
 
258
            bf.fixThen = fixThen;
 
259
            bf.fixElse = fixElse;
 
260
            result.add( ErrorDescriptionFactory.createErrorDescription(
 
261
                getSeverity().toEditorSeverity(), 
 
262
                getDisplayName(), 
 
263
                Collections.<Fix>singletonList( bf ), 
 
264
                info.getFileObject(),
 
265
                (int)info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), elseSt ),
 
266
                (int)info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), elseSt ) ) ); 
 
267
 
 
268
        }
 
269
                
 
270
        return result;
 
271
    }
 
272
    
 
273
    private boolean isErroneousExpression(StatementTree statement) {
 
274
        if ( statement instanceof ExpressionStatementTree ) {
 
275
            if ( ((ExpressionStatementTree)statement).getExpression().getKind() == Kind.ERRONEOUS ) {
 
276
                return true;
 
277
            }
 
278
        }
 
279
        return false;
 
280
    }
 
281
    
 
282
    private static class BracesFix implements Fix, Task<WorkingCopy> {
 
283
 
 
284
        
 
285
        FileObject file;
 
286
        TreePathHandle tph;
 
287
        int kind;
 
288
        
 
289
        boolean fixThen;
 
290
        boolean fixElse;
 
291
        
 
292
        public BracesFix(FileObject file, TreePathHandle tph) {
 
293
            this.file = file;
 
294
            this.tph = tph;
 
295
        }
 
296
        
 
297
        public String getText() {
 
298
            return NbBundle.getMessage(Braces.class, "LBL_Braces_Fix"); // NOI18N
 
299
        }
 
300
 
 
301
        public ChangeInfo implement() throws IOException {
 
302
            JavaSource js = JavaSource.forFileObject(file);
 
303
            js.runModificationTask(this).commit();
 
304
            return null;
 
305
        }
 
306
 
 
307
        public void run(WorkingCopy copy) throws Exception {
 
308
            copy.toPhase(JavaSource.Phase.PARSED);
 
309
            TreePath path = tph.resolve(copy);
 
310
            
 
311
            if ( path != null ) {
 
312
                
 
313
                TreeMaker make = copy.getTreeMaker();
 
314
                Tree oldTree = path.getLeaf();                 
 
315
                
 
316
                switch( oldTree.getKind() ) {
 
317
                case FOR_LOOP:
 
318
                    ForLoopTree oldFor = (ForLoopTree)oldTree;
 
319
                    StatementTree oldBlock = oldFor.getStatement();
 
320
                    BlockTree newBlock = make.Block(Collections.<StatementTree>singletonList(oldBlock), false);
 
321
                    copy.rewrite(oldBlock, newBlock);
 
322
                    break;
 
323
                case ENHANCED_FOR_LOOP:
 
324
                    EnhancedForLoopTree oldEnhancedFor = (EnhancedForLoopTree)oldTree;
 
325
                    oldBlock = oldEnhancedFor.getStatement();
 
326
                    newBlock = make.Block(Collections.<StatementTree>singletonList(oldBlock), false);                    
 
327
                    copy.rewrite(oldBlock, newBlock);
 
328
                    break;
 
329
                case WHILE_LOOP:
 
330
                    WhileLoopTree oldWhile = (WhileLoopTree)oldTree;
 
331
                    oldBlock = oldWhile.getStatement();
 
332
                    newBlock = make.Block(Collections.<StatementTree>singletonList(oldBlock), false);                    
 
333
                    copy.rewrite(oldBlock, newBlock);
 
334
                    break;
 
335
                case DO_WHILE_LOOP:
 
336
                    DoWhileLoopTree oldDoWhile = (DoWhileLoopTree)oldTree;
 
337
                    oldBlock = oldDoWhile.getStatement();
 
338
                    newBlock = make.Block(Collections.<StatementTree>singletonList(oldBlock), false);                    
 
339
                    copy.rewrite(oldBlock, newBlock);
 
340
                    break;
 
341
                case IF:
 
342
                    IfTree oldIf = (IfTree)oldTree;
 
343
                    if ( fixThen ) {
 
344
                        oldBlock = oldIf.getThenStatement();
 
345
                        newBlock = make.Block(Collections.<StatementTree>singletonList(oldBlock), false);
 
346
                        copy.rewrite(oldBlock, newBlock);
 
347
                    }
 
348
                    if ( fixElse ) {
 
349
                        oldBlock = oldIf.getElseStatement();
 
350
                        newBlock = make.Block(Collections.<StatementTree>singletonList(oldBlock), false);
 
351
                        copy.rewrite(oldBlock, newBlock);
 
352
                    } 
 
353
                    
 
354
                }
 
355
            }
 
356
        }
 
357
                
 
358
    }
 
359
 
 
360
    
 
361
    
 
362
}