1 11 package org.eclipse.jdt.internal.core; 12 13 import java.util.Comparator ; 14 import java.util.Stack ; 15 16 import org.eclipse.jdt.core.compiler.InvalidInputException; 17 import org.eclipse.jdt.core.dom.AST; 18 import org.eclipse.jdt.core.dom.ASTNode; 19 import org.eclipse.jdt.core.dom.FieldDeclaration; 20 import org.eclipse.jdt.core.dom.Initializer; 21 import org.eclipse.jdt.core.dom.MethodDeclaration; 22 import org.eclipse.jdt.core.dom.Name; 23 import org.eclipse.jdt.core.dom.PrimitiveType; 24 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 25 import org.eclipse.jdt.core.dom.Type; 26 import org.eclipse.jdt.core.dom.TypeDeclaration; 27 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 28 import org.eclipse.jdt.core.util.CompilationUnitSorter; 29 import org.eclipse.jdt.internal.compiler.SourceElementRequestorAdapter; 30 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 31 import org.eclipse.jdt.internal.compiler.env.IConstants; 32 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers; 33 import org.eclipse.jdt.internal.compiler.parser.Scanner; 34 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; 35 36 40 public class SortElementBuilder extends SourceElementRequestorAdapter { 41 42 abstract class SortElement extends SortJavaElement { 43 SortElement(int sourceStart, int modifiers) { 44 super(SortElementBuilder.this); 45 this.sourceStart = normalizeSourceStart(sourceStart); 46 modifiers &= ~IConstants.AccInterface; modifiers &= CompilerModifiers.AccJustFlag; 48 this.modifiers = modifiers; 49 this.children_count = 0; 50 } 51 52 protected void setParameters(MethodDeclaration methodDeclaration, String [] parameterNames, String [] parameterTypes) { 53 for (int i = 0, max = parameterNames.length; i < max; i++) { 54 String paramType = parameterTypes[i]; 55 SingleVariableDeclaration singleVariableDeclaration = ast.newSingleVariableDeclaration(); 56 singleVariableDeclaration.setName(ast.newSimpleName(parameterNames[i])); 57 int indexOfArrayBrace; 58 if (paramType.indexOf('.') != -1) { 59 String [] typeParts = splitOn('.', paramType); 60 int length = typeParts.length; 61 indexOfArrayBrace = typeParts[length - 1].indexOf('['); 62 if (indexOfArrayBrace != -1) { 63 int dimensions = occurencesOf('[', typeParts[length - 1]); 64 typeParts[length - 1] = typeParts[length - 1].substring(0, indexOfArrayBrace); 65 String [] typeSubstrings = new String [length]; 66 for (int j = 0; j < length; j++) { 67 typeSubstrings[j] = typeParts[j]; 68 } 69 singleVariableDeclaration.setType(ast.newArrayType(ast.newSimpleType(ast.newName(typeSubstrings)), dimensions)); 70 } else { 71 String [] typeSubstrings = new String [length]; 72 for (int j = 0; j < length; j++) { 73 typeSubstrings[j] = new String (typeParts[j]); 74 } 75 singleVariableDeclaration.setType(ast.newSimpleType(ast.newName(typeSubstrings))); 76 } 77 } else if ((indexOfArrayBrace = paramType.indexOf('[')) != -1) { 78 int dimensions = occurencesOf('[', paramType); 79 paramType = paramType.substring(0, indexOfArrayBrace); 80 singleVariableDeclaration.setType(ast.newArrayType(newType(paramType), dimensions)); 81 } else { 82 singleVariableDeclaration.setType(newType(paramType)); 83 } 84 methodDeclaration.parameters().add(singleVariableDeclaration); 85 } 86 } 87 88 protected String [] splitOn(char divider, String stringToSplit) { 89 int length = stringToSplit == null ? 0 : stringToSplit.length(); 90 if (length == 0) 91 return new String [] { stringToSplit }; 92 93 int wordCount = 1; 94 for (int i = 0; i < length; i++) 95 if (stringToSplit.charAt(i) == divider) 96 wordCount++; 97 String [] split = new String [wordCount]; 98 int last = 0, currentWord = 0; 99 for (int i = 0; i < length; i++) { 100 if (stringToSplit.charAt(i) == divider) { 101 split[currentWord++] = stringToSplit.substring(last, i); 102 last = i + 1; 103 } 104 } 105 split[currentWord] = stringToSplit.substring(last, length); 106 return split; 107 } 108 109 protected int occurencesOf(char toBeFound, String s) { 110 if (s == null) return 0; 111 int count = 0; 112 for (int i = 0, max = s.length(); i < max; i++) 113 if (toBeFound == s.charAt(i)) 114 count++; 115 return count; 116 } 117 118 protected Type newType(String typeSource) { 119 scanner.setSource(typeSource.toCharArray()); 121 scanner.resetTo(0, typeSource.length()); 122 int token = 0; 123 try { 124 token = scanner.getNextToken(); 125 } catch(InvalidInputException e) { 126 return null; 127 } 128 if (token == TerminalTokens.TokenNameIdentifier) { 129 return ast.newSimpleType(ast.newSimpleName(typeSource)); 130 } else { 131 switch(token) { 132 case TerminalTokens.TokenNameint : 133 return ast.newPrimitiveType(PrimitiveType.INT); 134 case TerminalTokens.TokenNamebyte : 135 return ast.newPrimitiveType(PrimitiveType.BYTE); 136 case TerminalTokens.TokenNameboolean : 137 return ast.newPrimitiveType(PrimitiveType.BOOLEAN); 138 case TerminalTokens.TokenNamechar : 139 return ast.newPrimitiveType(PrimitiveType.CHAR); 140 case TerminalTokens.TokenNamedouble : 141 return ast.newPrimitiveType(PrimitiveType.DOUBLE); 142 case TerminalTokens.TokenNamefloat : 143 return ast.newPrimitiveType(PrimitiveType.FLOAT); 144 case TerminalTokens.TokenNamelong : 145 return ast.newPrimitiveType(PrimitiveType.LONG); 146 case TerminalTokens.TokenNameshort : 147 return ast.newPrimitiveType(PrimitiveType.SHORT); 148 case TerminalTokens.TokenNamevoid : 149 return ast.newPrimitiveType(PrimitiveType.VOID); 150 } 151 } 152 return null; 153 } 154 155 abstract ASTNode convert(); 156 } 157 158 abstract class SortAbstractMethodDeclaration extends SortElement { 159 160 SortAbstractMethodDeclaration(int sourceStart, int modifiers, char[] name, char[][] parametersNames, char[][] parametersTypes, char[][] thrownExceptions) { 161 super(sourceStart, modifiers); 162 this.name = new String (name); 163 if (parametersNames != null) { 164 int length = parametersNames.length; 165 this.parametersNames = new String [length]; 166 this.parametersTypes = new String [length]; 167 for (int i = 0; i < length; i++) { 168 this.parametersNames[i] = new String (parametersNames[i]); 169 this.parametersTypes[i] = new String (parametersTypes[i]); 170 } 171 } 172 if (thrownExceptions != null) { 173 int length = thrownExceptions.length; 174 this.thrownExceptions = new String [length]; 175 for (int i = 0; i < length; i++) { 176 this.thrownExceptions[i] = new String (thrownExceptions[i]); 177 } 178 } 179 180 } 181 public String decodeSignature() { 182 StringBuffer buffer = new StringBuffer (); 183 buffer.append("("); if (this.parametersNames != null) { 185 int length = parametersNames.length; 186 for (int i = 0; i < length - 1; i++) { 187 buffer.append(parametersTypes[i] + " " + parametersNames[i] + ", "); } 189 buffer.append(parametersTypes[length - 1] + " " + parametersNames[length - 1]); } 191 buffer.append(")"); return buffer.toString(); 193 } 194 195 198 protected void generateSource(StringBuffer buffer) { 199 super.generateSource(buffer); 200 int length = this.children_count; 201 if (length != 0) { 202 int start = this.sourceStart; 203 int end = this.firstChildBeforeSorting.sourceStart - 1; 204 205 for (int i = 0; i < length; i++) { 206 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 207 this.children[i].generateSource(buffer); 208 if (i < length - 1) { 209 start = this.children[i].sourceEnd + 1; 210 } else { 211 start = this.lastChildBeforeSorting.sourceEnd + 1; 212 } 213 if (i < length - 1) { 214 end = this.children[i + 1].sourceStart - 1; 215 } else { 216 end = this.sourceEnd; 217 } 218 } 219 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 220 } else { 221 buffer.append(SortElementBuilder.this.source, this.sourceStart, this.sourceEnd - this.sourceStart + 1); 222 } 223 } 224 225 protected void mapPositions() { 226 int length = this.children_count; 227 if (length != 0) { 228 int start = this.sourceStart; 229 int end = this.firstChildBeforeSorting.sourceStart - 1; 230 231 for (int i = 0; i < length; i++) { 232 mapNextPosition(this, start, end); 233 this.children[i].mapPositions(); 234 if (i < length - 1) { 235 start = this.children[i].sourceEnd + 1; 236 } else { 237 start = this.lastChildBeforeSorting.sourceEnd + 1; 238 } 239 if (i < length - 1) { 240 end = this.children[i + 1].sourceStart - 1; 241 } else { 242 end = this.sourceEnd; 243 } 244 } 245 mapNextPosition(this, start, end); 246 } else { 247 mapNextPosition(this, this.sourceStart, this.sourceEnd); 248 } 249 } 250 } 251 252 class SortMethodDeclaration extends SortAbstractMethodDeclaration { 253 SortMethodDeclaration(int sourceStart, int modifiers, char[] name, char[][] parametersNames, char[][] parametersTypes, char[][] thrownExceptions, char[] returnType) { 254 super(sourceStart, modifiers, name, parametersNames, parametersTypes, thrownExceptions); 255 this.id = METHOD; 256 if (returnType != null) { 257 this.returnType = new String (returnType); 258 } 259 } 260 261 void display(StringBuffer buffer, int tab) { 262 buffer 263 .append(tab(tab)) 264 .append("method ") .append(name) 266 .append(decodeSignature()); 267 if (returnType != null) { 268 buffer.append(" " + returnType + LINE_SEPARATOR); } else { 270 buffer.append(LINE_SEPARATOR); } 272 } 273 274 ASTNode convert() { 275 MethodDeclaration methodDeclaration = ast.newMethodDeclaration(); 276 methodDeclaration.setConstructor(false); 277 methodDeclaration.setModifiers(this.modifiers); 278 methodDeclaration.setName(ast.newSimpleName(this.name)); 279 methodDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer (this.sourceStart)); 280 if (this.parametersNames != null) { 282 setParameters(methodDeclaration, this.parametersNames, this.parametersTypes); 283 } 284 if (this.thrownExceptions != null) { 286 for (int j = 0, max2 = this.thrownExceptions.length; j < max2; j++) { 287 String currentException = this.thrownExceptions[j]; 288 Name exceptionName; 289 if (currentException.indexOf('.') == -1) { 290 exceptionName = ast.newSimpleName(currentException); 291 } else { 292 exceptionName = ast.newName(splitOn('.', currentException)); 293 } 294 methodDeclaration.thrownExceptions().add(exceptionName); 295 } 296 } 297 int indexOfArrayBrace; 299 String currentReturnType = this.returnType; 300 if (currentReturnType != null) { 301 if (currentReturnType.indexOf('.') != -1) { 302 String [] returnTypeSubstrings = splitOn('.', currentReturnType); 303 int length = returnTypeSubstrings.length; 304 indexOfArrayBrace = returnTypeSubstrings[length - 1].indexOf('['); 305 if (indexOfArrayBrace != -1) { 306 int dimensions = occurencesOf('[', returnTypeSubstrings[length - 1]); 307 returnTypeSubstrings[length - 1] = returnTypeSubstrings[length - 1].substring(0, indexOfArrayBrace); 308 methodDeclaration.setReturnType(ast.newArrayType(ast.newSimpleType(ast.newName(returnTypeSubstrings)), dimensions)); 309 } else { 310 methodDeclaration.setReturnType(ast.newSimpleType(ast.newName(returnTypeSubstrings))); 311 } 312 } else if ((indexOfArrayBrace = currentReturnType.indexOf('[')) != -1) { 313 int dimensions = occurencesOf('[', currentReturnType); 314 currentReturnType = currentReturnType.substring(0, indexOfArrayBrace); 315 methodDeclaration.setReturnType(ast.newArrayType(newType(currentReturnType), dimensions)); 316 } else { 317 methodDeclaration.setReturnType(newType(currentReturnType)); 318 } 319 } 320 return methodDeclaration; 321 } 322 } 323 324 class SortConstructorDeclaration extends SortAbstractMethodDeclaration { 325 SortConstructorDeclaration(int sourceStart, int modifiers, char[] name, char[][] parametersNames, char[][] parametersTypes, char[][] thrownExceptions) { 326 super(sourceStart, modifiers, name, parametersNames, parametersTypes, thrownExceptions); 327 this.id = CONSTRUCTOR; 328 } 329 330 void display(StringBuffer buffer, int tab) { 331 buffer 332 .append(tab(tab)) 333 .append("constructor ") .append(decodeSignature() + LINE_SEPARATOR); 335 } 336 337 ASTNode convert() { 338 MethodDeclaration methodDeclaration = ast.newMethodDeclaration(); 339 methodDeclaration.setConstructor(true); 340 methodDeclaration.setModifiers(this.modifiers); 341 methodDeclaration.setName(ast.newSimpleName(this.name)); 342 methodDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer (this.sourceStart)); 343 if (this.parametersNames != null) { 345 setParameters(methodDeclaration, this.parametersNames, this.parametersTypes); 346 } 347 if (this.thrownExceptions != null) { 349 for (int j = 0, max2 = this.thrownExceptions.length; j < max2; j++) { 350 String currentException = this.thrownExceptions[j]; 351 Name exceptionName; 352 if (currentException.indexOf('.') == -1) { 353 exceptionName = ast.newSimpleName(currentException); 354 } else { 355 exceptionName = ast.newName(splitOn('.', currentException)); 356 } 357 methodDeclaration.thrownExceptions().add(exceptionName); 358 } 359 } 360 return methodDeclaration; 361 } 362 } 363 364 public class SortFieldDeclaration extends SortElement { 365 int previousSourceEnd; 366 367 SortFieldDeclaration(int sourceStart, int modifiers, char[] type, char[] name, int nameSourceStart) { 368 super(sourceStart, modifiers); 369 this.declarationStart = sourceStart; 370 this.id = FIELD; 371 this.type = new String (type); 372 this.name = new String (name); 373 this.nameSourceStart = nameSourceStart; 374 } 375 376 void display(StringBuffer buffer, int tab) { 377 buffer 378 .append(tab(tab)) 379 .append("field ") .append(type + " " + name + LINE_SEPARATOR); } 382 383 ASTNode convert() { 384 VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment(); 385 variableDeclarationFragment.setName(ast.newSimpleName(this.name)); 386 FieldDeclaration fieldDeclaration = ast.newFieldDeclaration(variableDeclarationFragment); 387 388 String currentFieldType = this.type; 389 390 int indexOfArrayBrace; 391 if (currentFieldType.indexOf('.') != -1) { 392 String [] typeParts = splitOn('.', currentFieldType); 393 int length = typeParts.length; 394 indexOfArrayBrace = typeParts[length - 1].indexOf('['); 395 if (indexOfArrayBrace != -1) { 396 int dimensions = occurencesOf('[', typeParts[length - 1]); 397 typeParts[length - 1] = typeParts[length - 1].substring(0, indexOfArrayBrace); 398 fieldDeclaration.setType(ast.newArrayType(ast.newSimpleType(ast.newName(typeParts)), dimensions)); 399 } else { 400 fieldDeclaration.setType(ast.newSimpleType(ast.newName(typeParts))); 401 } 402 } else if ((indexOfArrayBrace = currentFieldType.indexOf('[')) != -1) { 403 int dimensions = occurencesOf('[', currentFieldType); 404 currentFieldType = currentFieldType.substring(0, indexOfArrayBrace); 405 fieldDeclaration.setType(ast.newArrayType(newType(currentFieldType), dimensions)); 406 } else { 407 fieldDeclaration.setType(newType(currentFieldType)); 408 } 409 fieldDeclaration.setModifiers(this.modifiers); 410 fieldDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer (this.sourceStart)); 411 return fieldDeclaration; 412 } 413 416 protected void generateSource(StringBuffer buffer) { 417 super.generateSource(buffer); 418 int length = this.children_count; 419 if (length != 0) { 420 int start = this.sourceStart; 421 int end = this.firstChildBeforeSorting.sourceStart - 1; 422 423 for (int i = 0; i < length; i++) { 424 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 425 this.children[i].generateSource(buffer); 426 if (i < length - 1) { 427 start = this.children[i].sourceEnd + 1; 428 } else { 429 start = this.lastChildBeforeSorting.sourceEnd + 1; 430 } 431 if (i < length - 1) { 432 end = this.children[i + 1].sourceStart - 1; 433 } else { 434 end = this.declarationSourceEnd; 435 } 436 } 437 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 438 } else { 439 buffer.append(SortElementBuilder.this.source, this.sourceStart, this.declarationSourceEnd - this.sourceStart + 1); 440 } 441 } 442 protected void generateReduceSource(StringBuffer buffer) { 443 int length = this.children_count; 444 if (length != 0) { 445 int start = this.nameSourceStart; 446 int end = this.firstChildBeforeSorting.sourceStart - 1; 447 448 for (int i = 0; i < length; i++) { 449 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 450 this.children[i].generateSource(buffer); 451 if (i < length - 1) { 452 start = this.children[i].sourceEnd + 1; 453 } else { 454 start = this.lastChildBeforeSorting.sourceEnd + 1; 455 } 456 if (i < length - 1) { 457 end = this.children[i + 1].sourceStart - 1; 458 } else { 459 end = this.sourceEnd; 460 } 461 } 462 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 463 } else { 464 buffer.append(SortElementBuilder.this.source, this.nameSourceStart, this.sourceEnd - this.nameSourceStart + 1); 465 } 466 } 467 protected void mapReducedPositions() { 468 int length = this.children_count; 469 if (length != 0) { 470 int start = this.nameSourceStart; 471 int end = this.firstChildBeforeSorting.sourceStart - 1; 472 mapNextPosition(this, start, end); 473 for (int i = 0; i < length; i++) { 474 this.children[i].mapPositions(); 475 if (i < length - 1) { 476 start = this.children[i].sourceEnd + 1; 477 } else { 478 start = this.lastChildBeforeSorting.sourceEnd + 1; 479 } 480 if (i < length - 1) { 481 end = this.children[i + 1].sourceStart - 1; 482 } else { 483 end = this.sourceEnd; 484 } 485 } 486 mapNextPosition(this, start, end); 487 } else { 488 mapNextPosition(this, this.nameSourceStart, this.sourceEnd); 489 } 490 } 491 492 protected void mapPositions() { 493 int length = this.children_count; 494 if (length != 0) { 495 int start = this.sourceStart; 496 int end = this.firstChildBeforeSorting.sourceStart - 1; 497 498 for (int i = 0; i < length; i++) { 499 mapNextPosition(this, start, end); 500 this.children[i].mapPositions(); 501 if (i < length - 1) { 502 start = this.children[i].sourceEnd + 1; 503 } else { 504 start = this.lastChildBeforeSorting.sourceEnd + 1; 505 } 506 if (i < length - 1) { 507 end = this.children[i + 1].sourceStart - 1; 508 } else { 509 end = this.declarationSourceEnd; 510 } 511 } 512 mapNextPosition(this, start, end); 513 } else { 514 mapNextPosition(this, this.sourceStart, this.declarationSourceEnd); 515 } 516 } 517 } 518 519 class SortMultipleFieldDeclaration extends SortElement { 520 SortMultipleFieldDeclaration(SortFieldDeclaration fieldDeclaration) { 521 super(fieldDeclaration.declarationStart, fieldDeclaration.modifiers); 522 this.declarationStart = fieldDeclaration.declarationStart; 523 this.id = MULTIPLE_FIELD; 524 this.innerFields = new SortFieldDeclaration[1]; 525 this.fieldCounter = 0; 526 this.innerFields[this.fieldCounter++] = fieldDeclaration; 527 this.type = fieldDeclaration.type; 528 this.sourceStart = fieldDeclaration.sourceStart; 529 fieldDeclaration.sourceEnd = fieldDeclaration.previousSourceEnd; 530 } 531 532 void addField(SortFieldDeclaration fieldDeclaration) { 533 System.arraycopy(this.innerFields, 0, this.innerFields = new SortFieldDeclaration[this.fieldCounter + 1], 0, this.fieldCounter); 534 this.innerFields[this.fieldCounter++] = fieldDeclaration; 535 fieldDeclaration.sourceEnd = fieldDeclaration.previousSourceEnd; 536 } 537 538 void display(StringBuffer buffer, int tab) { 539 buffer 540 .append(tab(tab)) 541 .append("multiple fields ") .append(LINE_SEPARATOR); 543 if (this.innerFields != null) { 544 buffer 545 .append(tab(tab + 1)) 546 .append("INNER FIELDS ------------------------------" + LINE_SEPARATOR); for (int i = 0; i < this.fieldCounter; i++) { 548 buffer.append(this.innerFields[i].toString(tab + 2)); 549 buffer.append(LINE_SEPARATOR); 550 } 551 } 552 } 553 554 ASTNode convert() { 555 VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment(); 556 variableDeclarationFragment.setName(ast.newSimpleName(this.innerFields[0].name)); 557 FieldDeclaration fieldDeclaration = ast.newFieldDeclaration(variableDeclarationFragment); 558 559 for (int j = 1, max2 = this.innerFields.length; j < max2; j++) { 560 VariableDeclarationFragment fragment = ast.newVariableDeclarationFragment(); 561 fragment.setName(ast.newSimpleName(new String (this.innerFields[j].name))); 562 } 563 String currentFieldType = this.type; 564 565 int indexOfArrayBrace; 566 if (currentFieldType.indexOf('.') != -1) { 567 String [] typeParts = splitOn('.', currentFieldType); 568 int length = typeParts.length; 569 indexOfArrayBrace = typeParts[length - 1].indexOf('['); 570 if (indexOfArrayBrace != -1) { 571 int dimensions = occurencesOf('[', typeParts[length - 1]); 572 typeParts[length - 1] = typeParts[length - 1].substring(0, indexOfArrayBrace); 573 fieldDeclaration.setType(ast.newArrayType(ast.newSimpleType(ast.newName(typeParts)), dimensions)); 574 } else { 575 fieldDeclaration.setType(ast.newSimpleType(ast.newName(typeParts))); 576 } 577 } else if ((indexOfArrayBrace = currentFieldType.indexOf('[')) != -1) { 578 int dimensions = occurencesOf('[', currentFieldType); 579 currentFieldType = currentFieldType.substring(0, indexOfArrayBrace); 580 fieldDeclaration.setType(ast.newArrayType(newType(currentFieldType), dimensions)); 581 } else { 582 fieldDeclaration.setType(newType(currentFieldType)); 583 } 584 fieldDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer (this.sourceStart)); 585 fieldDeclaration.setModifiers(this.modifiers); 586 return fieldDeclaration; 587 } 588 591 protected void generateSource(StringBuffer buffer) { 592 super.generateSource(buffer); 593 int length = this.fieldCounter; 594 int start = this.innerFields[0].sourceStart; 595 int end = this.innerFields[0].nameSourceStart - 1; 596 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 597 for (int i = 0; i < length; i++) { 598 this.innerFields[i].newSourceStart = this.newSourceStart; 599 this.innerFields[i].generateReduceSource(buffer); 600 if (i < length - 1) { 601 start = this.innerFields[i].sourceEnd + 1; 602 end = this.innerFields[i + 1].nameSourceStart - 1; 603 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 604 } 605 } 606 start = this.innerFields[length - 1].sourceEnd + 1; 607 end = this.innerFields[length - 1].declarationSourceEnd; 608 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 609 } 610 611 protected void mapPositions() { 612 int length = this.fieldCounter; 613 int start = this.innerFields[0].sourceStart; 614 int end = this.innerFields[0].nameSourceStart - 1; 615 mapNextPosition(this, start, end); 616 for (int i = 0; i < length; i++) { 617 this.innerFields[i].newSourceStart = this.newSourceStart; 618 this.innerFields[i].mapReducedPositions(); 619 if (i < length - 1) { 620 start = this.innerFields[i].sourceEnd + 1; 621 end = this.innerFields[i + 1].nameSourceStart - 1; 622 mapNextPosition(this, start, end); 623 } 624 } 625 start = this.innerFields[length - 1].sourceEnd + 1; 626 end = this.innerFields[length - 1].declarationSourceEnd; 627 mapNextPosition(this, start, end); 628 } 629 630 protected void sort() { 631 for (int i = 0, max = this.fieldCounter; i < max; i++) { 632 this.innerFields[i].sort(); 633 } 634 } 635 } 636 637 class SortInitializer extends SortElement { 638 SortInitializer(int sourceStart, int modifiers) { 639 super(sourceStart, modifiers); 640 this.id = INITIALIZER; 641 } 642 643 void display(StringBuffer buffer, int tab) { 644 buffer 645 .append(tab(tab)) 646 .append("initializer " + LINE_SEPARATOR); } 648 649 ASTNode convert() { 650 Initializer initializer = ast.newInitializer(); 651 initializer.setModifiers(this.modifiers); 652 initializer.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer (this.sourceStart)); 653 return initializer; 654 } 655 658 protected void generateSource(StringBuffer buffer) { 659 super.generateSource(buffer); 660 int length = this.children_count; 661 if (length != 0) { 662 int start = this.sourceStart; 663 int end = this.firstChildBeforeSorting.sourceStart - 1; 664 665 for (int i = 0; i < length; i++) { 666 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 667 this.children[i].generateSource(buffer); 668 if (i < length - 1) { 669 start = this.children[i].sourceEnd + 1; 670 } else { 671 start = this.lastChildBeforeSorting.sourceEnd + 1; 672 } 673 if (i < length - 1) { 674 end = this.children[i + 1].sourceStart - 1; 675 } else { 676 end = this.sourceEnd; 677 } 678 } 679 buffer.append(SortElementBuilder.this.source, start, end - start + 1); 680 } else { 681 buffer.append(SortElementBuilder.this.source, this.sourceStart, this.sourceEnd - this.sourceStart + 1); 682 } 683 } 684 685 protected void mapPositions() { 686 int length = this.children_count; 687 if (length != 0) { 688 int start = this.sourceStart; 689 int end = this.firstChildBeforeSorting.sourceStart - 1; 690 691 for (int i = 0; i < length; i++) { 692 mapNextPosition(this, start, end); 693 this.children[i].mapPositions(); 694 if (i < length - 1) { 695 start = this.children[i].sourceEnd + 1; 696 } else { 697 start = this.lastChildBeforeSorting.sourceEnd + 1; 698 } 699 if (i < length - 1) { 700 end = this.children[i + 1].sourceStart - 1; 701 } else { 702 end = this.sourceEnd; 703 } 704 } 705 mapNextPosition(this, start, end); 706 } else { 707 mapNextPosition(this, this.sourceStart, this.sourceEnd); 708 } 709 } 710 } 711 712 class SortClassDeclaration extends SortType { 713 SortClassDeclaration(int sourceStart, int modifiers, char[] name, char[] superclass, char[][] superinterfaces) { 714 super(sourceStart, modifiers, name, superinterfaces); 715 this.id = CLASS | TYPE; 716 if (superclass != null) { 717 this.superclass = new String (superclass); 718 } 719 } 720 721 void display(StringBuffer buffer, int tab) { 722 buffer 723 .append(tab(tab)) 724 .append("class ") .append(this.name); 726 if (this.superclass != null) { 727 buffer.append(" extends " + this.superclass); } 729 if (this.superInterfaces != null) { 730 int length = this.superInterfaces.length; 731 buffer.append(" implements "); for (int i = 0; i < length - 1; i++) { 733 buffer.append(this.superInterfaces[i] + ", "); } 735 buffer.append(this.superInterfaces[length - 1]); 736 } 737 buffer.append(LINE_SEPARATOR); 738 } 739 740 ASTNode convert() { 741 TypeDeclaration typeDeclaration = ast.newTypeDeclaration(); 742 typeDeclaration.setInterface(false); 743 typeDeclaration.setModifiers(this.modifiers); 744 typeDeclaration.setName(ast.newSimpleName(this.name)); 745 if (this.superclass != null) { 747 if (this.superclass.indexOf('.') == -1) { 748 typeDeclaration.setSuperclass(ast.newSimpleName(this.superclass)); 750 } else { 751 String [] superclassNames = splitOn('.', this.superclass); 753 typeDeclaration.setSuperclass(ast.newName(superclassNames)); 754 } 755 } 756 if (this.superInterfaces != null) { 758 for (int j = 0, max2 = this.superInterfaces.length; j < max2; j++) { 759 String currentInterfaceName = this.superInterfaces[j]; 760 Name interfaceName; 761 if (currentInterfaceName.indexOf('.') == -1) { 762 interfaceName = ast.newSimpleName(currentInterfaceName); 764 } else { 765 String [] interfaceNames = splitOn('.', currentInterfaceName); 767 interfaceName = ast.newName(interfaceNames); 768 } 769 typeDeclaration.superInterfaces().add(interfaceName); 770 } 771 } 772 typeDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer (this.sourceStart)); 773 return typeDeclaration; 774 } 775 } 776 777 abstract class SortType extends SortElement { 778 SortType(int sourceStart, int modifier, char[] name, char[][] superinterfaces) { 779 super(sourceStart, modifier); 780 this.name = new String (name); 781 if (superinterfaces != null) { 782 int length = superinterfaces.length; 783 this.superInterfaces = new String [length]; 784 for (int i = 0; i < length; i++) { 785 this.superInterfaces[i] = new String (superinterfaces[i]); 786 } 787 } 788 } 789 792 protected void generateSource(StringBuffer buffer) { 793 super.generateSource(buffer); 794 int length = this.children_count; 795 int start = this.sourceStart; 796 if (length != 0) { 797 int end = this.firstChildBeforeSorting.sourceStart; 798 799 buffer.append(SortElementBuilder.this.source, start, end - start); 800 for (int i = 0; i < length; i++) { 801 ((SortElementBuilder.SortElement)this.astNodes[i].getProperty(CORRESPONDING_ELEMENT)).generateSource(buffer); 802 } 803 start = this.lastChildBeforeSorting.sourceEnd + 1; 804 buffer.append(SortElementBuilder.this.source, start, this.sourceEnd - start + 1); 805 } else { 806 buffer.append(SortElementBuilder.this.source, start, this.sourceEnd - start + 1); 807 } 808 } 809 810 protected void mapPositions() { 811 int length = this.children_count; 812 int start = this.sourceStart; 813 if (length != 0) { 814 int end = this.firstChildBeforeSorting.sourceStart - 1; 815 mapNextPosition(this, start, end); 816 for (int i = 0; i < length; i++) { 817 children[i].mapPositions(); 818 } 819 start = this.lastChildBeforeSorting.sourceEnd + 1; 820 mapNextPosition(this, start, this.sourceEnd); 821 } else { 822 mapNextPosition(this, start, this.sourceEnd); 823 } 824 } 825 } 826 827 class SortInterfaceDeclaration extends SortType { 828 SortInterfaceDeclaration(int sourceStart, int modifiers, char[] name, char[][] superinterfaces) { 829 super(sourceStart, modifiers, name, superinterfaces); 830 this.id = TYPE | INTERFACE; 831 } 832 void display(StringBuffer buffer, int tab) { 833 buffer 834 .append(tab(tab)) 835 .append("interface ") .append(this.name); 837 if (this.superInterfaces != null) { 838 int length = this.superInterfaces.length; 839 buffer.append(" implements "); for (int i = 0; i < length - 1; i++) { 841 buffer.append(this.superInterfaces[i] + ", "); } 843 buffer.append(this.superInterfaces[length - 1]); 844 } 845 buffer.append(LINE_SEPARATOR); 846 } 847 ASTNode convert() { 848 TypeDeclaration typeDeclaration = ast.newTypeDeclaration(); 849 typeDeclaration.setInterface(true); 850 typeDeclaration.setModifiers(this.modifiers); 851 typeDeclaration.setName(ast.newSimpleName(this.name)); 852 if (this.superInterfaces != null) { 854 for (int j = 0, max2 = this.superInterfaces.length; j < max2; j++) { 855 String currentInterfaceName = this.superInterfaces[j]; 856 Name interfaceName; 857 if (currentInterfaceName.indexOf('.') == -1) { 858 interfaceName = ast.newSimpleName(currentInterfaceName); 860 } else { 861 String [] interfaceNames = splitOn('.', currentInterfaceName); 863 interfaceName = ast.newName(interfaceNames); 864 } 865 typeDeclaration.superInterfaces().add(interfaceName); 866 } 867 } 868 typeDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer (this.sourceStart)); 869 return typeDeclaration; 870 } 871 } 872 873 class SortCompilationUnit extends SortElement { 874 SortCompilationUnit(int sourceStart) { 875 super(sourceStart, 0); 876 this.id = COMPILATION_UNIT; 877 } 878 void display(StringBuffer buffer, int tab) { 879 } 881 882 ASTNode convert() { 883 return ast.newCompilationUnit(); 884 } 885 888 protected void generateSource(StringBuffer buffer) { 889 super.generateSource(buffer); 890 int length = this.children_count; 891 if (length != 0) { 892 int end = this.firstChildBeforeSorting.sourceStart; 893 int start = this.lastChildBeforeSorting.sourceEnd + 1; 894 buffer.append(SortElementBuilder.this.source, 0, end); 895 for (int i = 0; i < length; i++) { 896 ((SortElementBuilder.SortElement)this.astNodes[i].getProperty(CORRESPONDING_ELEMENT)).generateSource(buffer); 897 } 898 buffer.append(SortElementBuilder.this.source, start, this.sourceEnd - start + 1); 899 } 900 } 901 902 protected void mapPositions() { 903 int length = this.children_count; 904 if (length != 0) { 905 int end = this.firstChildBeforeSorting.sourceStart; 906 int start = this.lastChildBeforeSorting.sourceEnd + 1; 907 mapNextPosition(this, 0, end); 908 for (int i = 0; i < length; i++) { 909 children[i].mapPositions(); 910 } 911 mapNextPosition(this, start, this.sourceEnd); 912 } else { 913 mapNextPosition(this, this.sourceStart, this.sourceEnd); 914 } 915 } 916 } 917 918 SortElement currentElement; 919 Stack stack; 920 SortCompilationUnit compilationUnit; 921 Scanner scanner; 922 AST ast; 923 924 char[] source; 925 int[] lineEnds; 926 Comparator comparator; 927 int[] positionsToMap; 928 int positionsToMapIndex; 929 930 public SortElementBuilder(char[] source, int[] positionsToMap, Comparator comparator) { 931 this.source = source; 932 this.comparator = comparator; 933 this.positionsToMap = positionsToMap; 934 this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3, null, null, true); 935 this.ast = AST.newAST(AST.JLS2); 936 } 937 938 941 public void acceptLineSeparatorPositions(int[] positions) { 942 this.lineEnds = positions; 943 } 944 945 public String getSource() { 946 StringBuffer buffer = new StringBuffer (); 947 this.positionsToMapIndex = 0; 948 this.compilationUnit.generateSource(buffer); 949 if (this.positionsToMap != null) { 950 this.compilationUnit.mapPositions(); 951 } 952 return buffer.toString(); 953 } 954 955 private static int searchLineNumber( 956 int[] startLineIndexes, 957 int position) { 958 int length = startLineIndexes.length; 963 if (length == 0) 964 return 1; 965 int g = 0, d = length - 1; 966 int m = 0; 967 while (g <= d) { 968 m = (g + d) / 2; 969 if (position < startLineIndexes[m]) { 970 d = m - 1; 971 } else 972 if (position > startLineIndexes[m]) { 973 g = m + 1; 974 } else { 975 return m + 1; 976 } 977 } 978 if (position < startLineIndexes[m]) { 979 return m + 1; 980 } 981 return m + 2; 982 } 983 984 void sort() { 985 this.compilationUnit.sort(); 986 } 987 988 void mapNextPosition(SortJavaElement node, int start, int end) { 989 int i = this.positionsToMapIndex; 990 for (; i < this.positionsToMap.length; i++) { 991 int nextPosition = this.positionsToMap[i]; 992 if (nextPosition >= start 993 && nextPosition <= end) { 994 this.positionsToMap[i] += (node.newSourceStart - node.sourceStart); 995 } else { 996 break; 997 } 998 } 999 this.positionsToMapIndex = i; 1000 } 1001 1004 public void enterClass( 1005 int declarationStart, 1006 int modifiers, 1007 char[] name, 1008 int nameSourceStart, 1009 int nameSourceEnd, 1010 char[] superclass, 1011 char[][] superinterfaces) { 1012 SortType type = new SortClassDeclaration(declarationStart, modifiers, name, superclass, superinterfaces); 1013 this.currentElement.addChild(type); 1014 push(type); 1015 } 1016 1017 1020 public void enterCompilationUnit() { 1021 this.stack = new Stack (); 1022 push(this.compilationUnit = new SortCompilationUnit(0)); 1023 } 1024 1025 1028 public void enterConstructor( 1029 int declarationStart, 1030 int modifiers, 1031 char[] name, 1032 int nameSourceStart, 1033 int nameSourceEnd, 1034 char[][] parameterTypes, 1035 char[][] parameterNames, 1036 char[][] exceptionTypes) { 1037 if ((this.currentElement.id & SortJavaElement.TYPE) != 0) { 1038 SortConstructorDeclaration constructorDeclaration = new SortConstructorDeclaration(declarationStart, modifiers, name, parameterNames, parameterTypes, exceptionTypes); 1039 this.currentElement.addChild(constructorDeclaration); 1040 push(constructorDeclaration); 1041 } 1042 } 1043 1044 1047 public void enterField( 1048 int declarationStart, 1049 int modifiers, 1050 char[] type, 1051 char[] name, 1052 int nameSourceStart, 1053 int nameSourceEnd) { 1054 if ((this.currentElement.id & SortJavaElement.TYPE) != 0) { 1055 SortFieldDeclaration fieldDeclaration = new SortFieldDeclaration(declarationStart, modifiers, type, name, nameSourceStart); 1056 SortElement[] currentElementChildren = this.currentElement.children; 1057 if (currentElementChildren != null) { 1058 SortElement previousElement = this.currentElement.children[this.currentElement.children_count - 1]; 1059 if (previousElement.id == SortJavaElement.FIELD && ((SortFieldDeclaration) previousElement).declarationStart == declarationStart) { 1060 SortMultipleFieldDeclaration multipleFielDeclaration = new SortMultipleFieldDeclaration((SortFieldDeclaration) previousElement); 1061 multipleFielDeclaration.addField(fieldDeclaration); 1062 this.currentElement.children[this.currentElement.children_count - 1] = multipleFielDeclaration; 1063 } else if (previousElement.id == SortJavaElement.MULTIPLE_FIELD && ((SortMultipleFieldDeclaration) previousElement).declarationStart == declarationStart) { 1064 ((SortMultipleFieldDeclaration) previousElement).addField(fieldDeclaration); 1065 } else { 1066 this.currentElement.addChild(fieldDeclaration); 1067 } 1068 } else { 1069 this.currentElement.addChild(fieldDeclaration); 1070 } 1071 push(fieldDeclaration); 1072 } 1073 } 1074 1075 1078 public void enterInitializer(int declarationStart, int modifiers) { 1079 if ((this.currentElement.id & SortJavaElement.TYPE) != 0) { 1080 SortInitializer initializer = new SortInitializer(declarationStart, modifiers); 1081 this.currentElement.addChild(initializer); 1082 push(initializer); 1083 } 1084 } 1085 1086 1089 public void enterInterface( 1090 int declarationStart, 1091 int modifiers, 1092 char[] name, 1093 int nameSourceStart, 1094 int nameSourceEnd, 1095 char[][] superinterfaces) { 1096 SortType type = new SortInterfaceDeclaration(declarationStart, modifiers, name, superinterfaces); 1097 this.currentElement.addChild(type); 1098 push(type); 1099 } 1100 1101 1104 public void enterMethod( 1105 int declarationStart, 1106 int modifiers, 1107 char[] returnType, 1108 char[] name, 1109 int nameSourceStart, 1110 int nameSourceEnd, 1111 char[][] parameterTypes, 1112 char[][] parameterNames, 1113 char[][] exceptionTypes) { 1114 if ((this.currentElement.id & SortJavaElement.TYPE) != 0) { 1115 SortMethodDeclaration methodDeclaration = new SortMethodDeclaration(declarationStart, modifiers, name, parameterNames, parameterTypes, exceptionTypes, returnType); 1116 this.currentElement.addChild(methodDeclaration); 1117 push(methodDeclaration); 1118 } 1119 } 1120 1121 1124 public void exitClass(int declarationEnd) { 1125 pop(declarationEnd); 1126 } 1127 1128 1131 public void exitCompilationUnit(int declarationEnd) { 1132 pop(declarationEnd); 1133 sort(); 1134 } 1135 1136 1139 public void exitConstructor(int declarationEnd) { 1140 pop(declarationEnd); 1141 } 1142 1143 1146 public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) { 1147 int normalizedDeclarationSourceEnd = this.normalizeSourceEnd(declarationSourceEnd); 1148 if (this.currentElement.id == SortJavaElement.FIELD) { 1149 SortFieldDeclaration fieldDeclaration = (SortFieldDeclaration) this.currentElement; 1150 fieldDeclaration.declarationSourceEnd = normalizedDeclarationSourceEnd; 1151 } 1152 pop(declarationEnd); 1153 if (this.currentElement.children != null) { 1154 SortElement element = this.currentElement.children[this.currentElement.children_count - 1]; 1155 switch(element.id) { 1156 case SortJavaElement.MULTIPLE_FIELD : 1157 SortMultipleFieldDeclaration multipleFielDeclaration = (SortMultipleFieldDeclaration) element; 1158 multipleFielDeclaration.innerFields[multipleFielDeclaration.fieldCounter - 1].declarationSourceEnd = normalizedDeclarationSourceEnd; 1159 multipleFielDeclaration.sourceEnd = normalizedDeclarationSourceEnd; 1160 break; 1161 case SortJavaElement.FIELD : 1162 SortFieldDeclaration fieldDeclaration = (SortFieldDeclaration) element; 1163 1167 fieldDeclaration.previousSourceEnd = fieldDeclaration.sourceEnd; 1168 fieldDeclaration.sourceEnd = normalizedDeclarationSourceEnd; 1169 } 1170 } 1171 } 1172 1173 1176 public void exitInitializer(int declarationEnd) { 1177 pop(declarationEnd); 1178 } 1179 1180 1183 public void exitInterface(int declarationEnd) { 1184 pop(declarationEnd); 1185 } 1186 1187 1190 public void exitMethod(int declarationEnd) { 1191 pop(declarationEnd); 1192 } 1193 1194 final int normalizeSourceStart(int position) { 1195 if (position == 0) { 1196 return 0; 1197 } 1198 int index = position - 1; 1199 while(index >= 0 && Character.isWhitespace(this.source[index])) { 1200 index--; 1201 } 1202 1203 int originalLineNumber = searchLineNumber(this.lineEnds, position); 1204 int newLineNumber = searchLineNumber(this.lineEnds, index); 1205 1206 if (originalLineNumber == newLineNumber) { 1207 return index + 1; 1208 } else { 1209 return this.lineEnds[newLineNumber - 1] + 1; 1210 } 1211 } 1212 1213 final int normalizeSourceEnd(int position) { 1214 int lineNumber = searchLineNumber(this.lineEnds, position); 1215 if (lineNumber == 1) { 1216 return position; 1217 } 1218 int normalizeSourceEnd = 0; 1219 if (lineNumber - 1 >= this.lineEnds.length) { 1220 normalizeSourceEnd = this.source.length - 1; 1221 } else { 1222 normalizeSourceEnd = this.lineEnds[lineNumber - 1]; 1223 } 1224 int index = position + 1; 1225 while (index < normalizeSourceEnd && Character.isWhitespace(this.source[index])) { 1226 index++; 1227 } 1228 if (index == normalizeSourceEnd) { 1229 return normalizeSourceEnd; 1230 } else { 1231 return position; 1232 } 1233 } 1234 1235 private void pop(int declarationEnd) { 1236 this.currentElement.sourceEnd = normalizeSourceEnd(declarationEnd); 1237 this.currentElement.closeCollections(); 1238 this.stack.pop(); 1239 if (!this.stack.isEmpty()) { 1240 this.currentElement = (SortElement) this.stack.peek(); 1241 } 1242 } 1243 1244 private void push(SortElement sortElement) { 1245 this.currentElement = sortElement; 1246 this.stack.push(sortElement); 1247 } 1248} 1249 | Popular Tags |