KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > javacore > parser > ASTRepairer


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.javacore.parser;
20
21 import java.util.Arrays JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Set JavaDoc;
24 import org.netbeans.lib.java.parser.*;
25
26 /**
27  *
28  * @author Martin Matula, Tomas Hurka
29  */

30 public class ASTRepairer implements ASTreeTypes, ParserTokens {
31     private final ASTProvider provider;
32     private final JParser parser;
33
34     ASTRepairer(ASTProvider provider, JParser parser) {
35         this.parser = parser;
36         this.provider = provider;
37     }
38
39     ASTree fixTree() {
40         ASTree compUnit = parser.getASTree();
41              
42         if (compUnit != null && compUnit.getType() == COMPILATION_UNIT && compUnit.getSubTrees() != null) {
43             fixTree(compUnit);
44         } else {
45             // let's create a fake AST
46
compUnit = new ASTreeNode(COMPILATION_UNIT, 0, provider.getTokens().length - 1, new ASTree[] {null, null, null});
47         }
48         consistencyCheck(compUnit);
49         return compUnit;
50     }
51     
52     private void consistencyCheck(ASTree topLevel) {
53         final int S_NORMAL = 0;
54         final int S_TOP_TYPE = 1;
55         final int S_PACKAGE = 2;
56         
57         ASTree typeDecls = topLevel.getSubTrees()[2];
58         int index = 0;
59         int blockDepth = 0;
60         int state = S_NORMAL;
61         int lastTokenType = 0;
62         boolean inTopType = false;
63         
64         Token[] tokens = provider.getTokens();
65         for (int i = 0; i < tokens.length; i++) {
66             int tokenType = tokens[i].getType();
67             switch (state) {
68                 case S_NORMAL:
69                     switch (tokenType) {
70                         case CLASS:
71                         case INTERFACE:
72                         case ENUM:
73                             if (lastTokenType != ParserTokens.DOT && blockDepth == 0 && !inTopType) {
74                                 state = S_TOP_TYPE;
75                             }
76                             break;
77                         case L_CURLY:
78                             blockDepth++;
79                             break;
80                         case R_CURLY:
81                             if (blockDepth > 0) {
82                                 blockDepth--;
83                                 if (blockDepth == 0) inTopType = false;
84                             }
85                             break;
86                         case PACKAGE:
87                             state = S_PACKAGE;
88                             break;
89                     }
90                     break;
91                 case S_PACKAGE:
92                     if (tokenType == SEMICOLON) state = S_NORMAL;
93                     break;
94                 case S_TOP_TYPE:
95                     if (tokenType == IDENTIFIER) {
96                         int type;
97                         if (lastTokenType == INTERFACE) {
98                             if (i - 2 > 0 && tokens[i - 2].getType() == MONKEYS_AT) {
99                                 type = ANNOTATION_TYPE_DECLARATION;
100                             } else {
101                                 type = INTERFACE_DECLARATION;
102                             }
103                         } else if (lastTokenType == ENUM) {
104                             type = ENUM_DECLARATION;
105                         } else {
106                             type = CLASS_DECLARATION;
107                         }
108                         index = getNextChildIndex(typeDecls, index);
109                         ASTree typeAST = getChild(typeDecls, index);
110                         if (typeAST == null || typeAST.getType() != type || typeAST.getSubTrees()[1].getFirstToken() != i) {
111                             typeDecls = addToTypeDecls(typeDecls, index, type, tokens[i], i);
112                         }
113                         index++;
114                     }
115                     state = S_NORMAL;
116                     inTopType = true;
117                     break;
118             }
119             lastTokenType = tokenType;
120         }
121         topLevel.getSubTrees()[2] = trimTypeDecls(typeDecls, index);
122     }
123     
124     private ASTree trimTypeDecls(ASTree typeDecls, int index) {
125         if (index > 0) {
126             ASTree[] children = typeDecls.getSubTrees();
127             if (children.length > index) {
128                 ASTree[] newChildren = new ASTree[index];
129                 System.arraycopy(children, 0, newChildren, 0, index);
130                 typeDecls = new ASTreeNode(TYPE_DECLARATIONS, newChildren[0].getFirstToken(), newChildren[index - 1].getLastToken(), newChildren);
131             }
132             return typeDecls;
133         } else {
134             return null;
135         }
136     }
137     
138     private ASTree addToTypeDecls(ASTree typeDecls, int index, int type, Token token, int lastTokenIndex) {
139         ASTree[] children = typeDecls == null ? new ASTree[1] : typeDecls.getSubTrees();
140         
141         assert children.length >= index;
142         
143         if (children.length == index) {
144             ASTree[] newChildren = new ASTree[index + 1];
145             System.arraycopy(children, 0, newChildren, 0, children.length);
146             children = newChildren;
147         }
148         
149         int size;
150         switch (type) {
151             case CLASS_DECLARATION:
152             case INTERFACE_DECLARATION:
153                 size = 6;
154                 break;
155             case ENUM_DECLARATION:
156                 size = 4;
157                 break;
158             case ANNOTATION_TYPE_DECLARATION:
159                 size = 3;
160                 break;
161             default:
162                 throw new IllegalArgumentException JavaDoc("Unexpected ASTree type: " + type); // NOI18N
163
}
164         ASTree[] subtrees = new ASTree[size];
165         subtrees[1] = token;
166         children[index] = new ASTreeNode(type, lastTokenIndex - 1, lastTokenIndex, subtrees);
167         
168         if (typeDecls == null || typeDecls.getSubTrees() != children) {
169             typeDecls = new ASTreeNode(TYPE_DECLARATIONS, children[0].getFirstToken(), children[children.length - 1].getLastToken(), children);
170         }
171         
172         return typeDecls;
173     }
174     
175     private ASTree getChild(ASTree tree, int index) {
176         if (tree == null || tree.getSubTrees().length <= index) {
177             return null;
178         }
179         return tree.getSubTrees()[index];
180     }
181     
182     private int getNextChildIndex(ASTree tree, int index) {
183         if (tree == null) {
184             return index;
185         }
186         ASTree[] subTrees = tree.getSubTrees();
187         while (subTrees.length > index && subTrees[index].getType() == SEMICOLON) {
188             ++index;
189         }
190         return index;
191     }
192     
193     private ASTree fixTree(ASTree tree) {
194         if (tree == null) return null;
195         int type = tree.getType();
196         ASTree parts[] = tree.getSubTrees();
197         
198         switch (type) {
199             case ENUM_BODY:
200             case COMPILATION_UNIT: {
201                 fixChildren(parts);
202                 break;
203             } case ENUM_CONSTANT: {
204                 if (parts == null) return null;
205                 parts[1] = parts[2] = null;
206             } case TYPE_PARAMETER:
207             case SUPER_:
208             case CONSTRUCTOR_DECLARATOR: {
209                 fixChildren(parts);
210                 if (parts == null || parts[0] == null || (parts[0].getType() != IDENTIFIER && parts[0].getType() != MULTI_PART_ID)) {
211                     return null;
212                 }
213                 break;
214             } case PACKAGE_DECLARATION: {
215                 fixChildren(parts);
216                 if (parts == null || parts[1] == null || (parts[1].getType() != IDENTIFIER && parts[1].getType() != MULTI_PART_ID)) {
217                     return null;
218                 }
219                 break;
220             } case PRIMITIVE_TYPE: {
221                 fixChildren(parts);
222                 if (parts == null || parts[0] == null) {
223                     return null;
224                 }
225                 switch (parts[0].getType()) {
226                     case BOOLEAN:
227                     case BYTE:
228                     case CHAR:
229                     case DOUBLE:
230                     case FLOAT:
231                     case INT:
232                     case LONG:
233                     case SHORT:
234                     case VOID:
235                         break;
236                     default:
237                         return null;
238                 }
239                 break;
240             } case METHOD_DECLARATOR: {
241                 fixChildren(parts);
242                 if (parts == null || parts[0] == null || parts[0].getType() != IDENTIFIER) {
243                     return null;
244                 }
245                 break;
246             } case MULTI_PART_ID: {
247                 if (parts == null) return null;
248                 fixChildren(parts);
249                 if ((parts[0] != null) && (parts[0].getType() != IDENTIFIER) && (parts[0].getType() != MULTI_PART_ID)) {
250                     return null;
251                 }
252                 if (parts[1] == null || parts[1].getType() != IDENTIFIER) {
253                     return null;
254                 }
255                 break;
256             } case SINGLE_TYPE_IMPORT:
257             case TYPE_IMPORT_ON_DEMAND: {
258                 if (parts == null) return null;
259                 fixChildren(parts);
260                 if (parts[1] == null) {
261                     return null;
262                 }
263                 break;
264             } case REFERENCE_TYPE: {
265                 if (parts == null) return null;
266                 fixChildren(parts);
267                 if (parts[0] == null || parts[1] == null) {
268                     return null;
269                 }
270                 break;
271             } case FIELD_DECLARATION:
272             case ANNOTATION_ATTRIBUTE_DECLARATION: {
273                 if (parts == null) return null;
274                 fixChildren(parts);
275                 if (parts[1] == null || parts[2] == null) {
276                     return null;
277                 }
278                 break;
279             } case FORMAL_PARAMETER: {
280                 if (parts == null) return null;
281                 fixChildren(parts);
282                 if (parts[1] == null || parts[3] == null) {
283                     return null;
284                 }
285                 break;
286             } case CLASS_DECLARATION:
287             case INTERFACE_DECLARATION: {
288                 if (parts == null) return null;
289                 fixChildren(parts);
290                 if (parts[1] == null || parts[1].getType() != IDENTIFIER || parts[5] == null) {
291                     return null;
292                 }
293                 break;
294             } case ENUM_DECLARATION: {
295                 if (parts == null) return null;
296                 fixChildren(parts);
297                 if (parts[1] == null || parts[1].getType() != IDENTIFIER || parts[3] == null) {
298                     return null;
299                 }
300                 break;
301             } case ANNOTATION_TYPE_DECLARATION: {
302                 if (parts == null) return null;
303                 fixChildren(parts);
304                 if (parts[1] == null || parts[1].getType() != IDENTIFIER || parts[2] == null) {
305                     return null;
306                 }
307                 break;
308             } case CONSTRUCTOR_DECLARATION: {
309                 if (parts == null) return null;
310                 fixChildren(parts);
311                 if (parts[3] == null || parts[5] == null || parts[5].getType() != BLOCK_STATEMENTS) {
312                     return null;
313                 }
314                 break;
315             } case METHOD_DECLARATION: {
316                 if (parts == null) return null;
317                 fixChildren(parts);
318                 if (parts[2] == null || parts[3] == null || parts[5] == null
319                     || (parts[5].getType() != BLOCK_STATEMENTS && parts[5].getType() != SEMICOLON)) {
320                     return null;
321                 }
322                 break;
323             } case VARIABLE_DECLARATORS: {
324                 ASTree result = fixChildren(tree, type, parts, false);
325                 if (result != null && result.getSubTrees().length == 1) {
326                     result = result.getSubTrees()[0];
327                 }
328                 return result;
329             } case VARIABLE_DECLARATOR: {
330                 if (parts == null) return null;
331                 if (parts.length > 2) parts[2] = null;
332                 fixChildren(parts);
333                 if (parts[0] == null || parts[0].getType() != IDENTIFIER) {
334                     return null;
335                 }
336                 break;
337             } case TYPE_ARGUMENTS:
338             case TYPE_DECLARATIONS:
339             case MODIFIERS:
340             case TYPE_PARAMETER_LIST:
341             case FORMAL_PARAMETER_LIST:
342             case ENUM_CONSTANTS:
343             case IMPORT_DECLARATIONS: {
344                 return fixChildren(tree, type, parts, false);
345             }
346             case BOUND_LIST:
347             case TYPE_LIST: {
348                 return fixChildren(tree, type, parts, new int[] {MULTI_PART_ID, IDENTIFIER}, false);
349             }
350         case ANNOTATION_TYPE_BODY_DECLARATIONS:
351             case ENUM_BODY_DECLARATIONS:
352             case INTERFACE_MEMBER_DECLARATIONS:
353             case CLASS_BODY_DECLARATIONS: {
354                 return fixChildren(tree, type, parts, true);
355             } case WILDCARD: {
356                 if (parts == null) return null;
357                 fixChildren(parts);
358                 if ((parts[0] == null) != (parts[1] == null)) {
359                     return null;
360                 }
361                 break;
362             } case BLOCK_STATEMENTS: {
363                 return new ASTreeNode(type, tree.getFirstToken(), tree.getLastToken(), ASTProvider.NULL_TREE);
364             } case ERRONEOUS:
365             case ANNOTATION:
366             case INSTANCE_INITIALIZER:
367             case STATIC_INITIALIZER:
368             case DEFAULT_VALUE: {
369                 return null;
370             }
371         }
372         return tree;
373     }
374
375     private ASTree fixChildren(ASTree tree, int type, ASTree[] parts, boolean canBeEmpty) {
376     return fixChildren(tree, type, parts, null, canBeEmpty);
377     }
378     
379     /** NOTE !!
380      * allowedTypes must be sorted
381      */

382     private ASTree fixChildren(ASTree tree, int type, ASTree[] parts,int[] allowedTypes, boolean canBeEmpty) {
383         if (parts == null) return null;
384         int i = 0, j = 0;
385         for (; i < parts.length; i++) {
386             parts[i] = fixTree(parts[i]);
387             if (parts[i] != null) {
388                 if (allowedTypes==null || Arrays.binarySearch(allowedTypes,parts[i].getType())>=0) {
389                     j++;
390                 } else {
391                     parts[i] = null;
392                 }
393             }
394         }
395         if (i == j) {
396             return tree;
397         } else if (j == 0) {
398             return canBeEmpty ? new ASTreeNode(type, tree.getFirstToken(), tree.getLastToken(), ASTProvider.NULL_TREE) : null;
399         } else {
400             ASTree[] newParts = new ASTree[j];
401             for (i = 0, j = 0; i < parts.length; i++) {
402                 if (parts[i] != null) {
403                     newParts[j++] = parts[i];
404                 }
405             }
406             return new ASTreeNode(type, tree.getFirstToken(), tree.getLastToken(), newParts);
407         }
408     }
409
410     private void fixChildren(ASTree[] parts) {
411         if (parts == null) return;
412         for (int i = 0; i < parts.length; i++) {
413             parts[i] = fixTree(parts[i]);
414         }
415     }
416
417     private class ASTreeNode implements ASTree {
418         private final int type, firstToken, lastToken;
419         private final ASTree[] subTrees;
420         
421         private ASTreeNode(int type, int firstToken, int lastToken, ASTree[] subTrees) {
422             this.type = type;
423             this.firstToken = firstToken;
424             this.lastToken = lastToken;
425             this.subTrees = subTrees;
426         }
427
428         public int getType() {
429             return type;
430         }
431
432         public int getFirstToken() {
433             return firstToken;
434         }
435
436         public int getLastToken() {
437             return lastToken;
438         }
439
440         public ASTree[] getSubTrees() {
441             return subTrees;
442         }
443
444         public SymbolInfo getSymbolInfo() {
445             return null;
446         }
447
448         public ASTContext getASTContext() {
449             return provider;
450         }
451     }
452 }
453
Popular Tags