1 19 20 package org.netbeans.modules.java.codegen; 21 22 import java.io.*; 23 import javax.swing.text.*; 24 25 import org.openide.src.*; 26 import org.openide.text.*; 27 28 import org.netbeans.modules.java.bridge.Binding; 29 30 35 class FieldB extends Member implements Binding.Field { 36 private static final boolean DEBUG = false; 37 38 42 FieldB previous, next; 43 44 46 public PositionBounds typeBounds; 47 48 boolean single; 49 50 public FieldB(FieldElement el, SourceText s) { 51 super(el, s); 52 single = true; 53 } 54 55 56 59 public void linkAfter(TextBinding t) { 60 FieldB f = (FieldB)t; 61 if (next == f) 62 return; 63 64 if (next != null) { 65 next.previous = f; 66 next.single = f == null && next.next == null; 67 next.adjustBounds(); 68 } 69 if (f != null) { 70 f.previous = this; 71 f.next = next; 72 f.single = false; 73 single = false; 74 if (typeBounds != null) 75 f.typeBounds = typeBounds; 76 } else { 77 single = previous == null; 78 adjustBounds(); 79 } 80 next = f; 81 } 82 83 84 public void linkBefore(TextBinding t) { 85 FieldB f = (FieldB)t; 86 if (previous == f) 87 return; 88 89 if (previous != null) { 90 previous.next = f; 91 previous.single = f == null && previous.previous == null; 92 previous.adjustBounds(); 93 } 94 if (f != null) { 95 f.previous = previous; 96 f.next = this; 97 f.single = false; 98 single = false; 99 } else { 100 single = next == null; 101 adjustBounds(); 102 } 103 previous = f; 104 } 105 106 private boolean isSingle() { 107 return single; 108 } 109 110 private void adjustBounds() { 111 if (!isSingle() || typeBounds == null) 112 return; 113 if (DEBUG) 114 System.err.println("Adjusting bounds for single field..."); headerBounds = new PositionBounds(typeBounds.getBegin(), headerBounds.getEnd()); 116 if (docBounds == null) 117 wholeBounds = new PositionBounds(typeBounds.getBegin(), wholeBounds.getEnd()); 118 else 119 wholeBounds = new PositionBounds(docBounds.getBegin(), wholeBounds.getEnd()); 120 121 typeBounds = null; 122 } 123 124 private FieldElement cloneField() { 125 return (FieldElement)cloneElement(); 126 } 127 128 protected int classifyProperty(String name) { 129 if (name == PROP_INIT_VALUE) 130 return CLASS_BODY; 131 else 132 return CLASS_HEADER; 133 } 134 135 public void updateBounds(int kind, PositionBounds b) { 136 if (kind == BOUNDS_FIELD_TYPE) { 137 if (typeBounds == null || b != null) 138 this.typeBounds = b; 139 } else { 140 super.updateBounds(kind, b); 141 } 142 } 143 144 protected void regenerateBody(org.openide.src.Element el) throws SourceException { 145 regenerateInitializer((FieldElement) el); 146 } 147 148 protected void doChangeProperty(String property, Object old, final Object now) 149 throws Exception { 150 if (isSingle() || property == PROP_INIT_VALUE) { 151 super.doChangeProperty(property, old, now); 152 return; 153 } 154 155 if (property == PROP_NAME) { 156 source.runAtomic(getElement(), new ExceptionRunnable() { 157 public void run() throws Exception { 158 CodeGenerator.fillTextBounds(headerBounds, 159 ((Identifier)now).getSourceName()); 160 } 161 }); 162 } else { 163 FieldElement f = cloneField(); 164 applyPropertyChange(f, property, now); 165 new SingleMaker(f).run(); 166 } 167 } 168 169 171 public void changeType(Type newType) throws SourceException { 172 if (!source.isGeneratorEnabled()) 173 return; 174 175 if (isSingle()) { 176 FieldElement f = cloneField(); 177 f.setType(newType); 178 regenerateHeader(f); 179 return; 180 } 181 FieldElement f = cloneField(); 182 f.setType(newType); 183 source.runAtomic(getElement(), new SingleMaker(f)); 184 } 185 186 private void regenerateJavaDoc() throws SourceException { 187 super.regenerateJavaDoc(getElement(), ((FieldElement)getElement()).getJavaDoc()); 188 } 189 190 195 public PositionRef prepareInsert(ElementBinding tbi, boolean after) 196 throws SourceException { 197 if (after && next != null) { 198 breakFieldGroup(); 199 if (DEBUG) 200 source.dumpDocument(); 201 } else if (!after && previous != null) { 202 previous.breakFieldGroup(); 203 if (DEBUG) 204 source.dumpDocument(); 205 } 206 if (DEBUG) { 207 System.err.println("prepareInsert: after = " + after + "wholeBounds = " + wholeBounds); } 209 return super.prepareInsert(tbi, after); 210 } 211 212 214 void breakFieldGroup() throws SourceException { 215 try { 216 final String headerText = typeBounds.getText(); 217 final FieldB prev = this.previous; 218 final FieldB next = this.next; 219 final StyledDocument doc = findDocument(); 220 221 if (DEBUG) { 222 System.err.println("breakFieldGroup invoked on " + getField()); System.err.println("[breakFieldGroup] headerText = " + headerText); System.err.println("[breakFieldGroup] myBounds = " + wholeBounds); dumpBoundsForChain(); 226 } 227 if (next == null) { 228 throw new IllegalStateException ("breakFieldGroup invoked on field " + ((FieldElement)getElement()).getName() + " that is at the end of the group"); } 231 PositionBounds insertion; 232 233 234 PositionBounds replacement = new PositionBounds( 239 source.createPos( 240 wholeBounds.getEnd().getOffset() - 1, 241 Position.Bias.Backward 242 ), 243 source.createPos( 244 wholeBounds.getEnd().getOffset(), 245 Position.Bias.Forward 246 ) 247 ); 248 CodeGenerator.fillTextBounds(replacement, 249 CodeGenerator.formatText(doc, replacement.getBegin(), ";")); 251 String separator = CodeGenerator.formatText(doc, replacement.getEnd(), 252 "\n" + headerText) + " "; int hdrOffset = separator.indexOf(headerText); 254 255 PositionBounds insertion2 = new PositionBounds( 256 source.createPos( 257 replacement.getEnd().getOffset(), 258 Position.Bias.Forward 259 ), 260 source.createPos( 261 next.headerBounds.getBegin().getOffset(), 262 Position.Bias.Backward 263 ) 264 ); 265 insertion2.setText(separator); 266 267 PositionBounds tBounds = new PositionBounds( 268 source.createPos(insertion2.getBegin().getOffset() + hdrOffset, Position.Bias.Backward), 269 source.createPos(insertion2.getEnd().getOffset() - 1, Position.Bias.Forward) 270 ); 271 272 288 289 if (DEBUG) { 290 System.err.println("[breakFieldGroup] Insertion for type is " + insertion2 + " hdr offset = " + hdrOffset); } 293 306 307 if (DEBUG) { 308 System.err.println("[breakFieldGroup] next's type bounds = " + tBounds); } 310 311 next.typeBounds = tBounds; 314 next.wholeBounds = new PositionBounds( 315 tBounds.getBegin(), 316 next.wholeBounds.getEnd() 317 ); 318 next.linkBefore(null); 321 next.docBounds = null; 323 324 for (FieldB fimpl = next.next; fimpl != null; fimpl = fimpl.next) { 327 fimpl.typeBounds = tBounds; 328 fimpl.docBounds = next.docBounds; 329 } 330 331 if (DEBUG) { 332 if (prev != null) { 333 System.err.println("Dumping prev chain:"); prev.dumpBoundsForChain(); 335 } 336 System.err.println("Dumping next chain:"); next.dumpBoundsForChain(); 338 } 339 340 if (docBounds != null) { 341 next.regenerateJavaDoc(); 345 } 346 adjustBounds(); 347 if (DEBUG) { 348 System.err.println("breakFieldGroup report:"); System.err.println("-- first part tail details:"); System.err.println("whole = " + wholeBounds + " header = " + headerBounds + " body = " + bodyBounds + " type = " + typeBounds + " single = " + isSingle()); System.err.println("-- second part head details:"); System.err.println("whole = " + next.wholeBounds + " header = " + next.headerBounds + " body = " + next.bodyBounds + " type = " + next.typeBounds + " single = " + next.isSingle()); System.err.println("link deatils:"); System.err.println("tail = " + this + " head = " + next + " tail's next = " + this.next + " head's prev = " + next.previous); source.dumpDocument(); 359 } 360 } catch (Exception ex) { 361 SourceText.rethrowException(getElement(), ex); 362 } 363 } 364 365 367 public void changeInitializer(String newInitializer) throws SourceException { 368 if (!source.isGeneratorEnabled()) 369 return; 370 371 FieldElement f = cloneField(); 372 f.setInitValue(newInitializer); 373 regenerateInitializer(f); 374 } 375 376 protected void regenerateWhole(org.openide.src.Element model, boolean updatePositions) 377 throws SourceException { 378 super.regenerateWhole(model, updatePositions); 379 int headerEndOffset = headerBounds.getEnd().getOffset(); 380 381 if (updatePositions && (((FieldElement)model).getInitValue().length() > 0)) { 382 bodyBounds = new PositionBounds( 385 source.createPos(headerEndOffset, Position.Bias.Backward), 386 bodyBounds.getEnd()); 387 } else { 388 bodyBounds = null; 390 } 391 } 392 393 396 public void changeModifiers(int newMods) throws SourceException { 397 if (!source.isGeneratorEnabled()) 398 return; 399 400 if (isSingle()) { 401 super.changeModifiers(newMods); 402 return; 403 } 404 405 FieldElement f = cloneField(); 406 f.setModifiers(newMods); 407 source.runAtomic(getElement(), new SingleMaker(f)); 408 } 409 410 413 public void changeName(final Identifier name) throws SourceException { 414 if (!source.isGeneratorEnabled()) 415 return; 416 417 if (isSingle()) { 418 super.changeName(name); 419 return; 420 } 421 source.runAtomic(getElement(), new ExceptionRunnable() { 422 public void run() throws Exception { 423 CodeGenerator.fillTextBounds(headerBounds, name.getSourceName()); 424 } 425 }); 426 } 427 428 433 public void remove(boolean collapseBefore, boolean collapseAfter) throws SourceException, IllegalStateException { 434 if (isSingle()) { 435 super.remove(collapseBefore, collapseAfter); 436 return; 437 } 438 removeFromGroup(); 439 } 440 441 444 public void updateFrom(Binding other) { 445 } 446 447 public void changeJavaDoc(JavaDoc content) throws SourceException { 448 if (!source.isGeneratorEnabled()) 449 return; 450 if (!isSingle()) { 451 FieldElement f=(FieldElement)getElement(); 452 source.runAtomic(f, new SingleMaker(f)); 453 } 454 super.changeJavaDoc(content); 455 } 456 457 private void regenerateInitializer(final FieldElement fld) throws SourceException { 458 final StyledDocument doc; 459 460 doc = source.getDocument(); 461 462 ExceptionRunnable run = new ExceptionRunnable() { 463 public void run() throws Exception { 464 String txt; 465 String init = fld.getInitValue(); 466 int start; 467 468 if (bodyBounds == null) { 469 start = wholeBounds.getEnd().getOffset() - 1; 470 } else { 471 start = bodyBounds.getBegin().getOffset(); 472 } 473 474 if (init != null && 475 !init.equals("")) { 476 StringWriter writer = new StringWriter(); 477 Writer iWriter = CodeGenerator.findIndentWriter(doc, start, writer); 478 iWriter.write(" = "); ElementPrinter prn = new ElementPrinterImpl(iWriter, fld, ElementPrinter.BODY_BEGIN, 480 ElementPrinter.BODY_END); 481 try { 482 fld.print(prn); 483 } catch (ElementPrinterInterruptException e) { 484 } 485 txt = writer.toString(); 486 } else { 487 txt = ""; 488 } 489 if (bodyBounds == null) { 490 bodyBounds = new PositionBounds( 491 headerBounds.getEnd(), 492 source.createPos(wholeBounds.getEnd().getOffset() - 1, Position.Bias.Backward)); 493 } else if (bodyBounds.getBegin().getOffset() == bodyBounds.getEnd().getOffset()) { 494 bodyBounds = new PositionBounds( 495 headerBounds.getEnd(), bodyBounds.getEnd() 496 ); 497 } 498 bodyBounds.setText(txt); 499 } 500 }; 501 502 source.runAtomic(getElement(), run); 503 } 504 505 private void unlinkField() { 506 FieldB p = previous; 507 508 if (previous != null) { 509 previous.next = next; 510 previous.single = previous.previous == null && next == null; 511 previous.adjustBounds(); 512 } 513 if (next != null) { 514 next.previous = p; 515 next.single = next.next == null && p == null; 516 next.adjustBounds(); 517 } 518 previous = next = null; 519 single = true; 520 adjustBounds(); 521 } 522 523 private FieldElement getField() { 524 return (FieldElement)getElement(); 525 } 526 527 void removeFromGroup() throws SourceException { 528 PositionRef endRef; 529 PositionBounds removal; 530 531 if (DEBUG) { 532 System.err.println("Field " + getField().getName().toString() + ": removing from SourceText file."); System.err.println("previous = " + (previous == null ? (Object )previous : (Object )previous.getField())); System.err.println("next = " + (next == null ? (Object )next : (Object )next.getField())); dumpBoundsForChain(); 536 } 537 endRef = source.createPos(wholeBounds.getEnd().getOffset(), Position.Bias.Forward); 538 if (previous != null) { 539 if (DEBUG) { 540 System.err.println("previous = " + previous + " f = " + previous.getField().getName().toString()); System.err.println("it's wholebounds = " + previous.wholeBounds); } 543 removal = new PositionBounds( 544 source.createPos(previous.wholeBounds.getEnd().getOffset() - 1, Position.Bias.Forward), 545 source.createPos(wholeBounds.getEnd().getOffset() - 1, Position.Bias.Backward)); 546 } else { 547 removal = new PositionBounds(headerBounds.getBegin(), endRef); 550 } 551 if (previous != null) { 553 previous.wholeBounds = new PositionBounds( 558 previous.wholeBounds.getBegin(), 559 source.createPos( 560 endRef.getOffset(), 561 Position.Bias.Forward) 562 ); 563 if (DEBUG) { 564 System.err.println("[removeFromGroup] previous' bounds: " + previous.wholeBounds); 566 } 567 } 568 if (DEBUG) { 569 System.err.println("removal bounds: " + removal); } 571 try { 572 CodeGenerator.clearBounds(removal, false); 573 if (DEBUG) 574 source.dumpDocument(); 575 } catch (BadLocationException ex) { 576 SourceText.rethrowException(getElement(),ex); 577 } 578 579 if (DEBUG) { 580 System.err.println("breakFieldGroup report:"); System.err.println("-- first part tail details:"); if (previous != null) { 583 System.err.println("whole = " + previous.wholeBounds + " header = " + previous.headerBounds + " body = " + previous.bodyBounds + " type = " + previous.typeBounds + " single = " + previous.isSingle()); System.err.println("-- second part head details:"); } 587 if (next != null) { 588 System.err.println("whole = " + next.wholeBounds + " header = " + next.headerBounds + " body = " + next.bodyBounds + " type = " + next.typeBounds + " single = " + next.isSingle()); } 591 System.err.println("link deatils:"); System.err.println("tail = " + previous + " head = " + next); if (previous != null) { 594 System.err.println(" tail's next = " + previous.next); } 596 if (next != null) { 597 System.err.println("head's prev = " + next.previous); } 599 System.err.println("myPrevious = " + previous + "myNext = " + next); } 601 FieldB p = previous, n = next; 602 unlinkField(); 603 if (DEBUG) { 604 System.err.println("link deatils after unlink:"); System.err.println("tail = " + p + " head = " + n); if (p != null) { 607 System.err.println(" tail's next = " + p.next); } 609 if (n != null) { 610 System.err.println("head's prev = " + n.previous); } 612 System.err.println("myPrevious = " + previous + "myNext = " + next); 614 if (DEBUG) { 615 if (p != null) { 616 System.err.println("Dumping previous chain:"); p.dumpBoundsForChain(); 618 } 619 if (n != null) { 620 System.err.println("Dumping next chain:"); n.dumpBoundsForChain(); 622 } 623 } 624 } 625 previous = next = null; 626 } 627 628 private void dumpBoundsForChain() { 629 if (!DEBUG) 630 return; 631 FieldB begin = this; 632 while (begin.previous != null) 633 begin = begin.previous; 634 635 while (begin != null) { 636 begin.dumpFieldBounds(); 637 begin = begin.next; 638 } 639 } 640 641 private void dumpFieldBounds() { 642 if (!DEBUG) 643 return; 644 System.err.println("Dumping bounds for: " + getField() + "(" + this + ")"); System.err.println("header = " + headerBounds); System.err.println("body = " + bodyBounds); System.err.println("whole = " + wholeBounds); System.err.println("type = " + typeBounds); System.err.println("------------------------------------"); 650 } 651 652 private class SingleMaker extends PartialGenerator { 653 SingleMaker(FieldElement model) throws SourceException { 654 super(FieldB.this.findDocument(), model, true); 655 } 656 657 private void makeSingle() throws Exception { 658 ElementBinding p = previous; 659 ElementBinding n = next; 660 PositionBounds newBounds; 661 662 if (p == null && n == null) { 663 throw new IllegalStateException ("Field does not refer to its siblings"); } 665 if (p == null) { 666 p = containerRef.findPrevious(FieldB.this); 667 } 668 if (n == null) { 669 n = containerRef.findNext(FieldB.this); 670 } 671 if (DEBUG) { 673 System.err.println("[makeSingle] prevField = " + p + ", nextField = " + n); } 676 removeFromGroup(); 677 if (DEBUG) 678 source.dumpDocument(); 679 containerRef.insertChild(FieldB.this, p, n); 680 } 681 682 public void run() throws Exception { 683 makeSingle(); 684 this.posBounds = wholeBounds; 685 if (DEBUG) { 686 System.err.println("Field made single:"); dumpBoundsForChain(); 688 source.dumpDocument(); 689 } 690 super.run(); 691 } 692 } 693 } 694 | Popular Tags |