1 19 package org.netbeans.modules.javacore.parser; 20 21 import java.util.Arrays ; 22 import java.util.HashSet ; 23 import java.util.Set ; 24 import org.netbeans.lib.java.parser.*; 25 26 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 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 ("Unexpected ASTree type: " + type); } 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 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 |