EADS-3516 - Still getting: "Adding a fold that is identical with another previously added fold from the same FoldManager is not allowed."
- NewPlsqlFoldManager now includes way to remember old fold, should avoid issue at hand.
- added SimplePlsqlFoldManager for testing. It always removes all fold then add existing back. Will probably remove if NewPlsqlFoldManager fixes issue.
1.1 --- a/PLSQL/Folding/nbproject/project.xml Fri Mar 15 14:14:52 2013 +0100
1.2 +++ b/PLSQL/Folding/nbproject/project.xml Fri Mar 15 14:16:18 2013 +0100
1.3 @@ -91,6 +91,19 @@
1.4 </run-dependency>
1.5 </dependency>
1.6 </module-dependencies>
1.7 + <test-dependencies>
1.8 + <test-type>
1.9 + <name>unit</name>
1.10 + <test-dependency>
1.11 + <code-name-base>org.mockito.all</code-name-base>
1.12 + <compile-dependency/>
1.13 + </test-dependency>
1.14 + <test-dependency>
1.15 + <code-name-base>org.netbeans.libs.junit4</code-name-base>
1.16 + <compile-dependency/>
1.17 + </test-dependency>
1.18 + </test-type>
1.19 + </test-dependencies>
1.20 <public-packages/>
1.21 </data>
1.22 </configuration>
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/PLSQL/Folding/src/org/netbeans/modules/plsql/fold/FoldAdapter.java Fri Mar 15 14:16:18 2013 +0100
2.3 @@ -0,0 +1,28 @@
2.4 +/*
2.5 + * To change this template, choose Tools | Templates
2.6 + * and open the template in the editor.
2.7 + */
2.8 +package org.netbeans.modules.plsql.fold;
2.9 +
2.10 +import org.netbeans.api.editor.fold.Fold;
2.11 +
2.12 +/**
2.13 + *
2.14 + * @author ChrLSE
2.15 + */
2.16 +class FoldAdapter {
2.17 +
2.18 + private final Fold fold;
2.19 +
2.20 + FoldAdapter(Fold fold) {
2.21 + this.fold = fold;
2.22 + }
2.23 +
2.24 + int getStartOffset() {
2.25 + return fold.getStartOffset();
2.26 + }
2.27 +
2.28 + int getEndOffset() {
2.29 + return fold.getEndOffset();
2.30 + }
2.31 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/PLSQL/Folding/src/org/netbeans/modules/plsql/fold/FoldSearchObject.java Fri Mar 15 14:16:18 2013 +0100
3.3 @@ -0,0 +1,74 @@
3.4 +/*
3.5 + * To change this template, choose Tools | Templates
3.6 + * and open the template in the editor.
3.7 + */
3.8 +package org.netbeans.modules.plsql.fold;
3.9 +
3.10 +import java.io.Serializable;
3.11 +
3.12 +/**
3.13 + *
3.14 + * @author ChrLSE
3.15 + */
3.16 +class FoldSearchObject implements Serializable {
3.17 +
3.18 + private static final long serialVersionUID = 1L;
3.19 + private final int startOffset;
3.20 + private final int endOffset;
3.21 + private FoldAdapter fold;
3.22 +
3.23 + FoldSearchObject(int startOffset, int endOffset) {
3.24 + this.startOffset = startOffset;
3.25 + this.endOffset = endOffset;
3.26 + }
3.27 +
3.28 + FoldSearchObject(FoldAdapter fold) {
3.29 + this(-1, -1);
3.30 + this.fold = fold;
3.31 + }
3.32 +
3.33 + public int getStartOffset() {
3.34 + if (startOffset == -1) {
3.35 + return fold.getStartOffset();
3.36 + }
3.37 + return startOffset;
3.38 + }
3.39 +
3.40 + public int getEndOffset() {
3.41 + if (endOffset == -1) {
3.42 + return fold.getEndOffset();
3.43 + }
3.44 + return endOffset;
3.45 + }
3.46 +
3.47 + @Override
3.48 + public int hashCode() {
3.49 + int hash = 7;
3.50 + hash = 13 * hash + this.getStartOffset();
3.51 + hash = 13 * hash + this.getEndOffset();
3.52 + return hash;
3.53 + }
3.54 +
3.55 + @Override
3.56 + public boolean equals(Object obj) {
3.57 + if (obj == null) {
3.58 + return false;
3.59 + }
3.60 + if (getClass() != obj.getClass()) {
3.61 + return false;
3.62 + }
3.63 + final FoldSearchObject other = (FoldSearchObject) obj;
3.64 + if (this.getStartOffset() != other.getStartOffset()) {
3.65 + return false;
3.66 + }
3.67 + if (this.getEndOffset() != other.getEndOffset()) {
3.68 + return false;
3.69 + }
3.70 + return true;
3.71 + }
3.72 +
3.73 + @Override
3.74 + public String toString() {
3.75 + return "FoldSearchObject{" + "startOffset=" + getStartOffset() + ", endOffset=" + getEndOffset() + '}';
3.76 + }
3.77 +}
4.1 --- a/PLSQL/Folding/src/org/netbeans/modules/plsql/fold/NewPlsqlFoldManager.java Fri Mar 15 14:14:52 2013 +0100
4.2 +++ b/PLSQL/Folding/src/org/netbeans/modules/plsql/fold/NewPlsqlFoldManager.java Fri Mar 15 14:16:18 2013 +0100
4.3 @@ -42,9 +42,7 @@
4.4 package org.netbeans.modules.plsql.fold;
4.5
4.6 import java.util.ArrayList;
4.7 -import java.util.HashMap;
4.8 import java.util.List;
4.9 -import java.util.Map;
4.10 import java.util.Observable;
4.11 import java.util.Observer;
4.12 import java.util.logging.Level;
4.13 @@ -52,7 +50,6 @@
4.14 import javax.swing.event.DocumentEvent;
4.15 import javax.swing.text.BadLocationException;
4.16 import javax.swing.text.Document;
4.17 -import javax.swing.text.Position;
4.18 import org.netbeans.api.editor.fold.Fold;
4.19 import org.netbeans.api.editor.fold.FoldHierarchy;
4.20 import org.netbeans.api.editor.fold.FoldType;
4.21 @@ -74,17 +71,14 @@
4.22 public class NewPlsqlFoldManager implements FoldManager, Runnable, Observer {
4.23
4.24 private static final Logger LOG = Logger.getLogger(NewPlsqlFoldManager.class.getName());
4.25 + private static final RequestProcessor RP = new RequestProcessor(NewPlsqlFoldManager.class.getName(), 1, false, false);
4.26 + private static final int TASK_DELAY = 300;
4.27 + private final RequestProcessor.Task task = RP.create(this);
4.28 private FoldOperation operation;
4.29 private Document doc;
4.30 - // XXX replace with Map to be able to test if mark already exist before adding new fold.
4.31 -// private Map<Integer, FoldMarkInfo> markArray = new HashMap<Integer, FoldMarkInfo>();
4.32 - private org.netbeans.editor.GapObjectArray markArray = new org.netbeans.editor.GapObjectArray();
4.33 - private int minUpdateMarkOffset = Integer.MAX_VALUE;
4.34 - private int maxUpdateMarkOffset = -1;
4.35 - private List<Fold> removedFoldList;
4.36 - private Map<String, Boolean> customFoldId = new HashMap<String, Boolean>();
4.37 - private static final RequestProcessor RP = new RequestProcessor(NewPlsqlFoldManager.class.getName(), 1, false, false);
4.38 - private final RequestProcessor.Task task = RP.create(this);
4.39 + // Note: FoldSearchObject need to be in a List, otherwise contains doesn't work. Seems HashSet keeps internal list of hash.
4.40 + private final List<FoldSearchObject> foldSearchObjects = new ArrayList<FoldSearchObject>();
4.41 + private List<Fold> removedFoldList = new ArrayList<Fold>(3);
4.42 private boolean initial = true;
4.43 private PlsqlBlockFactory blockFactory;
4.44
4.45 @@ -107,18 +101,23 @@
4.46 if (blockFactory != null) {
4.47 blockFactory.addObserver(this);
4.48 }
4.49 - task.schedule(300);
4.50 + task.schedule(TASK_DELAY);
4.51 }
4.52
4.53 @Override
4.54 public void insertUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
4.55 + if (LOG.isLoggable(Level.FINER)) {
4.56 + LOG.log(Level.FINER, "insertUpdate: {0}", System.identityHashCode(this));
4.57 + }
4.58 processRemovedFolds(transaction);
4.59 }
4.60
4.61 @Override
4.62 public void removeUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
4.63 + if (LOG.isLoggable(Level.FINER)) {
4.64 + LOG.log(Level.FINER, "removeUpdate: {0}", System.identityHashCode(this));
4.65 + }
4.66 processRemovedFolds(transaction);
4.67 - removeAffectedMarks(evt, transaction);
4.68 }
4.69
4.70 @Override
4.71 @@ -127,11 +126,17 @@
4.72
4.73 @Override
4.74 public void removeEmptyNotify(Fold emptyFold) {
4.75 + if (LOG.isLoggable(Level.FINER)) {
4.76 + LOG.log(Level.FINER, "removeEmptyNotify: {0}", System.identityHashCode(this));
4.77 + }
4.78 removeFoldNotify(emptyFold);
4.79 }
4.80
4.81 @Override
4.82 public void removeDamagedNotify(Fold damagedFold) {
4.83 + if (LOG.isLoggable(Level.FINER)) {
4.84 + LOG.log(Level.FINER, "removeDamagedNotify: {0}", System.identityHashCode(this));
4.85 + }
4.86 removeFoldNotify(damagedFold);
4.87 }
4.88
4.89 @@ -142,13 +147,16 @@
4.90 @Override
4.91 public void release() {
4.92 if (LOG.isLoggable(Level.FINE)) {
4.93 - LOG.log(Level.FINE, "Released: {0}", System.identityHashCode(this));
4.94 + LOG.log(Level.FINE, "release: {0}", System.identityHashCode(this));
4.95 }
4.96 }
4.97
4.98 @Override
4.99 public void update(Observable o, Object arg) {
4.100 - task.schedule(300);
4.101 + if (LOG.isLoggable(Level.FINER)) {
4.102 + LOG.log(Level.FINER, "update: {0}", System.identityHashCode(this));
4.103 + }
4.104 + task.schedule(TASK_DELAY);
4.105 }
4.106
4.107 @Override
4.108 @@ -203,616 +211,114 @@
4.109 }
4.110
4.111 private void removeFoldNotify(Fold removedFold) {
4.112 - if (removedFoldList == null) {
4.113 - removedFoldList = new ArrayList<Fold>(3);
4.114 - }
4.115 removedFoldList.add(removedFold);
4.116 }
4.117
4.118 - private void removeAffectedMarks(DocumentEvent evt, FoldHierarchyTransaction transaction) {
4.119 - int removeOffset = evt.getOffset();
4.120 - int markIndex = findMarkIndex(removeOffset);
4.121 - if (markIndex < getMarkCount()) {
4.122 - FoldMarkInfo mark;
4.123 - while (markIndex >= 0 && (mark = getMark(markIndex)).getOffset() == removeOffset) {
4.124 - mark.release(false, transaction);
4.125 - removeMark(markIndex);
4.126 - markIndex--;
4.127 + private void processRemovedFolds(FoldHierarchyTransaction transaction) {
4.128 + for (Fold removedFold : removedFoldList) {
4.129 + boolean remove = foldSearchObjects.remove(new FoldSearchObject(new FoldAdapter(removedFold)));
4.130 + if (LOG.isLoggable(Level.FINE)) {
4.131 + LOG.log(Level.FINE, "Fold={0} removed={1}", new Object[]{removedFold, remove});
4.132 }
4.133 }
4.134 - }
4.135 -
4.136 - private void processRemovedFolds(FoldHierarchyTransaction transaction) {
4.137 - if (removedFoldList != null) {
4.138 - for (int i = removedFoldList.size() - 1; i >= 0; i--) {
4.139 - Fold removedFold = removedFoldList.get(i);
4.140 - FoldMarkInfo startMark = (FoldMarkInfo) getOperation().getExtraInfo(removedFold);
4.141 - if (startMark.getId() != null) {
4.142 - customFoldId.put(startMark.getId(), Boolean.valueOf(removedFold.isCollapsed())); // remember the last fold's state before remove
4.143 - }
4.144 - FoldMarkInfo endMark = startMark.getPairMark(); // get prior releasing
4.145 - if (getOperation().isStartDamaged(removedFold)) { // start mark area was damaged
4.146 - startMark.release(true, transaction); // forced remove
4.147 - }
4.148 - if (getOperation().isEndDamaged(removedFold)) {
4.149 - endMark.release(true, transaction);
4.150 - }
4.151 - }
4.152 - }
4.153 - removedFoldList = null;
4.154 - }
4.155 -
4.156 - private void markUpdate(FoldMarkInfo mark) {
4.157 - markUpdate(mark.getOffset());
4.158 - }
4.159 -
4.160 - private void markUpdate(int offset) {
4.161 - if (offset < minUpdateMarkOffset) {
4.162 - minUpdateMarkOffset = offset;
4.163 - }
4.164 - if (offset > maxUpdateMarkOffset) {
4.165 - maxUpdateMarkOffset = offset;
4.166 - }
4.167 - }
4.168 -
4.169 - private FoldMarkInfo getMark(int index) {
4.170 - return (FoldMarkInfo) markArray.getItem(index);
4.171 -// return markArray.get(index);
4.172 - }
4.173 -
4.174 - private int getMarkCount() {
4.175 - return markArray.getItemCount();
4.176 -// return markArray.size();
4.177 - }
4.178 -
4.179 - private void removeMark(int index) {
4.180 - if (LOG.isLoggable(Level.FINER)) {
4.181 - LOG.log(Level.FINER, "Removing mark from ind={0}: {1}", new Object[]{index, getMark(index)}); // NOI18N
4.182 - }
4.183 - markArray.remove(index, 1);
4.184 -// markArray.remove(index);
4.185 - }
4.186 -
4.187 - private void insertMark(int index, FoldMarkInfo mark) {
4.188 -// markArray.put(index, mark);
4.189 - markArray.insertItem(index, mark);
4.190 - if (LOG.isLoggable(Level.FINER)) {
4.191 - LOG.log(Level.FINER, "Inserted mark at ind={0}: {1}", new Object[]{index, mark}); // NOI18N
4.192 - }
4.193 - }
4.194 -
4.195 - private int findMarkIndex(int offset) {
4.196 - int markCount = getMarkCount();
4.197 - int low = 0;
4.198 - int high = markCount - 1;
4.199 -
4.200 - while (low <= high) {
4.201 - int mid = (low + high) / 2;
4.202 - int midMarkOffset = getMark(mid).getOffset();
4.203 -
4.204 - if (midMarkOffset < offset) {
4.205 - low = mid + 1;
4.206 - } else if (midMarkOffset > offset) {
4.207 - high = mid - 1;
4.208 - } else {
4.209 - // mark starting exactly at the given offset found
4.210 - // If multiple -> find the one with highest index
4.211 - mid++;
4.212 - while (mid < markCount && getMark(mid).getOffset() == offset) {
4.213 - mid++;
4.214 - }
4.215 - mid--;
4.216 - return mid;
4.217 - }
4.218 - }
4.219 - return low; // return higher index (e.g. for insert)
4.220 - }
4.221 -
4.222 - private List<FoldMarkInfo> getMarkList(List<PlsqlBlock> blocks) {
4.223 - List<FoldMarkInfo> markList = new ArrayList<FoldMarkInfo>();
4.224 - try {
4.225 - scanBlocks(markList, blocks);
4.226 - } catch (BadLocationException e) {
4.227 - LOG.log(Level.WARNING, null, e);
4.228 - }
4.229 - return markList;
4.230 - }
4.231 -
4.232 - private void processBlocks(List<PlsqlBlock> blocks, FoldHierarchyTransaction transaction) {
4.233 - List<FoldMarkInfo> markList = getMarkList(blocks);
4.234 - int markListSize;
4.235 - if (markList != null && ((markListSize = markList.size()) > 0)) {
4.236 - // Find the index for insertion
4.237 - int offset = (markList.get(0)).getOffset();
4.238 - int arrayMarkIndex = findMarkIndex(offset);
4.239 - // Remember the corresponding mark in the array as well
4.240 - FoldMarkInfo arrayMark;
4.241 - int arrayMarkOffset;
4.242 - if (arrayMarkIndex < getMarkCount()) {
4.243 - arrayMark = getMark(arrayMarkIndex);
4.244 - arrayMarkOffset = arrayMark.getOffset();
4.245 - } else { // at last mark
4.246 - arrayMark = null;
4.247 - arrayMarkOffset = Integer.MAX_VALUE;
4.248 - }
4.249 -
4.250 - for (int i = 0; i < markListSize; i++) {
4.251 - FoldMarkInfo listMark = markList.get(i);
4.252 - int listMarkOffset = listMark.getOffset();
4.253 - if (i == 0 || i == markListSize - 1) {
4.254 - // Update the update-offsets by the first and last marks in the list
4.255 - markUpdate(listMarkOffset);
4.256 - }
4.257 - while (listMarkOffset >= arrayMarkOffset) {
4.258 - if (listMarkOffset == arrayMarkOffset) {
4.259 - // At the same offset - likely the same mark
4.260 - // -> retain the collapsed state
4.261 - listMark.setCollapsed(arrayMark.isCollapsed());
4.262 - }
4.263 - if (!arrayMark.isReleased()) { // make sure that the mark is released
4.264 - arrayMark.release(false, transaction);
4.265 - }
4.266 - removeMark(arrayMarkIndex);
4.267 - if (LOG.isLoggable(Level.FINER)) {
4.268 - LOG.log(Level.FINER, "Removed dup mark from ind={0}: {1}", new Object[]{arrayMarkIndex, arrayMark}); // NOI18N
4.269 - }
4.270 - if (arrayMarkIndex < getMarkCount()) {
4.271 - arrayMark = getMark(arrayMarkIndex);
4.272 - arrayMarkOffset = arrayMark.getOffset();
4.273 - } else { // no more marks
4.274 - arrayMark = null;
4.275 - arrayMarkOffset = Integer.MAX_VALUE;
4.276 - }
4.277 - }
4.278 - // Insert the listmark
4.279 - insertMark(arrayMarkIndex, listMark);
4.280 - if (LOG.isLoggable(Level.FINER)) {
4.281 - LOG.log(Level.FINER, "Inserted mark at ind={0}: {1}", new Object[]{arrayMarkIndex, listMark}); // NOI18N
4.282 - }
4.283 - arrayMarkIndex++;
4.284 - }
4.285 - }
4.286 + removedFoldList.clear();
4.287 }
4.288
4.289 private void updateFolds(List<PlsqlBlock> blocks, FoldHierarchyTransaction transaction) {
4.290 -
4.291 - if (blocks != null && !blocks.isEmpty()) {
4.292 - processBlocks(blocks, transaction);
4.293 - }
4.294 -
4.295 - if (maxUpdateMarkOffset == -1) { // no updates
4.296 - return;
4.297 - }
4.298 -
4.299 - // Find the first mark to update and init the prevMark and parentMark prior the loop
4.300 - int index = findMarkIndex(minUpdateMarkOffset);
4.301 - FoldMarkInfo prevMark;
4.302 - FoldMarkInfo parentMark;
4.303 - if (index == 0) { // start from begining
4.304 - prevMark = null;
4.305 - parentMark = null;
4.306 - } else {
4.307 - prevMark = getMark(index - 1);
4.308 - parentMark = prevMark.getParentMark();
4.309 - }
4.310 -
4.311 - // Iterate through the changed marks in the mark array
4.312 - int markCount = getMarkCount();
4.313 - while (index < markCount) { // process the marks
4.314 - FoldMarkInfo mark = getMark(index);
4.315 -
4.316 - // If the mark was released then it must be removed
4.317 - if (mark.isReleased()) {
4.318 - if (LOG.isLoggable(Level.FINE)) {
4.319 - LOG.log(Level.FINE, "Removing released mark at ind={0}: {1}", new Object[]{index, mark}); // NOI18N
4.320 - }
4.321 - removeMark(index);
4.322 - markCount--;
4.323 - continue;
4.324 - }
4.325 -
4.326 - // Update mark's status (folds, parentMark etc.)
4.327 - if (mark.isStartMark()) { // starting a new fold
4.328 - if (prevMark == null || prevMark.isStartMark()) { // new level
4.329 - mark.setParentMark(prevMark); // prevMark == null means root level
4.330 - parentMark = prevMark;
4.331 -
4.332 - } // same level => parent to the parent of the prevMark
4.333 -
4.334 - } else { // end mark
4.335 - if (prevMark != null) {
4.336 - if (prevMark.isStartMark()) { // closing nearest fold
4.337 - prevMark.setEndMark(mark, false, transaction);
4.338 -
4.339 - } else { // prevMark is end mark - closing its parent fold
4.340 - if (parentMark != null) {
4.341 - // mark's parent gets set as well
4.342 - parentMark.setEndMark(mark, false, transaction);
4.343 - parentMark = parentMark.getParentMark();
4.344 -
4.345 - } else { // prevMark's parentMark is null (top level)
4.346 - mark.makeSolitaire(false, transaction);
4.347 - }
4.348 - }
4.349 -
4.350 - } else { // prevMark is null
4.351 - mark.makeSolitaire(false, transaction);
4.352 - }
4.353 - }
4.354 -
4.355 - // Set parent mark of the mark
4.356 - mark.setParentMark(parentMark);
4.357 -
4.358 -
4.359 - prevMark = mark;
4.360 - index++;
4.361 - }
4.362 -
4.363 - minUpdateMarkOffset = Integer.MAX_VALUE;
4.364 - maxUpdateMarkOffset = -1;
4.365 -
4.366 - if (LOG.isLoggable(Level.FINEST)) {
4.367 - LOG.log(Level.FINEST, "MARKS DUMP:\n{0}", this); //NOI18N
4.368 - }
4.369 - }
4.370 -
4.371 - public @Override
4.372 - String toString() {
4.373 - StringBuffer sb = new StringBuffer();
4.374 - int markCount = getMarkCount();
4.375 - int markCountDigitCount = Integer.toString(markCount).length();
4.376 - for (int i = 0; i < markCount; i++) {
4.377 - sb.append("["); // NOI18N
4.378 - String iStr = Integer.toString(i);
4.379 - appendSpaces(sb, markCountDigitCount - iStr.length());
4.380 - sb.append(iStr);
4.381 - sb.append("]:"); // NOI18N
4.382 - FoldMarkInfo mark = getMark(i);
4.383 -
4.384 - // Add extra indent regarding the depth in hierarchy
4.385 - int indent = 0;
4.386 - FoldMarkInfo parentMark = mark.getParentMark();
4.387 - while (parentMark != null) {
4.388 - indent += 4;
4.389 - parentMark = parentMark.getParentMark();
4.390 - }
4.391 - appendSpaces(sb, indent);
4.392 -
4.393 - sb.append(mark);
4.394 - sb.append('\n');
4.395 - }
4.396 - return sb.toString();
4.397 - }
4.398 -
4.399 - private static void appendSpaces(StringBuffer sb, int spaces) {
4.400 - while (--spaces >= 0) {
4.401 - sb.append(' ');
4.402 - }
4.403 - }
4.404 -
4.405 - private void scanBlocks(List<FoldMarkInfo> list, List<PlsqlBlock> blocks) throws BadLocationException {
4.406 for (PlsqlBlock block : blocks) {
4.407
4.408 FoldType foldType = null;
4.409 final PlsqlBlockType type = block.getType();
4.410 String description = null;
4.411 + try {
4.412 + if (!(type == PlsqlBlockType.COMMENT && doc.getText(block.getStartOffset(), block.getEndOffset() - block.getStartOffset()).indexOf("\n") == -1)) { // check for single line comments
4.413 + if (type == PlsqlBlockType.VIEW) {
4.414 + foldType = PlsqlFoldTypes.VIEW;
4.415 + description = block.getPrefix() + "VIEW " + block.getName();
4.416 + } else if (type == PlsqlBlockType.TABLE_COMMENT) {
4.417 + foldType = PlsqlFoldTypes.TABLECOMMENT;
4.418 + description = "COMMENT ON TABLE " + block.getName();
4.419 + } else if (type == PlsqlBlockType.COLUMN_COMMENT) {
4.420 + foldType = PlsqlFoldTypes.COLUMNCOMMENT;
4.421 + description = "COLUMN COMMENTS ON TABLE " + block.getName();
4.422 + } else if (type == PlsqlBlockType.COMMENT) {
4.423 + foldType = PlsqlFoldTypes.COMMENT;
4.424 + description = block.getName();
4.425 + } else if (type == PlsqlBlockType.PACKAGE) {
4.426 + foldType = PlsqlFoldTypes.PACKAGE;
4.427 + description = block.getPrefix() + "PACKAGE " + block.getName();
4.428 + } else if (type == PlsqlBlockType.PACKAGE_BODY) {
4.429 + foldType = PlsqlFoldTypes.PACKAGEBODY;
4.430 + description = block.getPrefix() + "PACKAGE BODY " + block.getName();
4.431 + } else if (type == PlsqlBlockType.PROCEDURE_IMPL) {
4.432 + foldType = PlsqlFoldTypes.PROCEDUREIMPL;
4.433 + description = block.getPrefix() + "PROCEDURE IMPLEMENTATION " + block.getName();
4.434 + } else if (type == PlsqlBlockType.FUNCTION_IMPL) {
4.435 + foldType = PlsqlFoldTypes.FUNCTIONIMPL;
4.436 + description = block.getPrefix() + "FUNCTION IMPLEMENTATION " + block.getName();
4.437 + } else if (type == PlsqlBlockType.PROCEDURE_DEF) {
4.438 + foldType = PlsqlFoldTypes.PROCEDUREDEF;
4.439 + description = "PROCEDURE DEFINITION " + block.getName();
4.440 + } else if (type == PlsqlBlockType.FUNCTION_DEF) {
4.441 + foldType = PlsqlFoldTypes.FUNCTIONDEF;
4.442 + description = "FUNCTION DEFINITION " + block.getName();
4.443 + } else if (type == PlsqlBlockType.DECLARE_END) {
4.444 + foldType = PlsqlFoldTypes.DECLAREEND;
4.445 + description = "DECLARE BLOCK";
4.446 + } else if (type == PlsqlBlockType.BEGIN_END) {
4.447 + foldType = PlsqlFoldTypes.BEGINEND;
4.448 + description = "BEGIN BLOCK";
4.449 + } else if (type == PlsqlBlockType.TRIGGER) {
4.450 + foldType = PlsqlFoldTypes.TRIGGER;
4.451 + description = block.getPrefix() + "TRIGGER " + block.getName();
4.452 + } else if (type == PlsqlBlockType.IF) {
4.453 + foldType = PlsqlFoldTypes.IF;
4.454 + description = block.getName();
4.455 + } else if (type == PlsqlBlockType.CASE) {
4.456 + foldType = PlsqlFoldTypes.CASE;
4.457 + description = block.getName();
4.458 + } else if (type == PlsqlBlockType.WHILE_LOOP) {
4.459 + foldType = PlsqlFoldTypes.WHILELOOP;
4.460 + description = "WHILE " + block.getName();
4.461 + } else if (type == PlsqlBlockType.FOR_LOOP) {
4.462 + foldType = PlsqlFoldTypes.FORLOOP;
4.463 + description = "FOR " + block.getName();
4.464 + } else if (type == PlsqlBlockType.LOOP) {
4.465 + foldType = PlsqlFoldTypes.LOOP;
4.466 + description = "LOOP ";
4.467 + } else if (type == PlsqlBlockType.CUSTOM_FOLD) {
4.468 + foldType = PlsqlFoldTypes.CUSTOM;
4.469 + description = block.getName();
4.470 + } else if (type == PlsqlBlockType.STATEMENT) {
4.471 + foldType = PlsqlFoldTypes.STATEMENT;
4.472 + description = block.getPrefix() + block.getName();
4.473 + } else if (type == PlsqlBlockType.CURSOR) {
4.474 + foldType = PlsqlFoldTypes.CURSOR;
4.475 + description = "CURSOR " + block.getName();
4.476 + } else if (type == PlsqlBlockType.JAVA_SOURCE) {
4.477 + foldType = PlsqlFoldTypes.JAVASOURCE;
4.478 + description = block.getPrefix() + "JAVA SOURCE";
4.479 + }
4.480
4.481 - if (!(type == PlsqlBlockType.COMMENT && doc.getText(block.getStartOffset(), block.getEndOffset() - block.getStartOffset()).indexOf("\n") == -1)) { // check for single line comments
4.482 - if (type == PlsqlBlockType.VIEW) {
4.483 - foldType = PlsqlFoldTypes.VIEW;
4.484 - description = block.getPrefix() + "VIEW " + block.getName();
4.485 - } else if (type == PlsqlBlockType.TABLE_COMMENT) {
4.486 - foldType = PlsqlFoldTypes.TABLECOMMENT;
4.487 - description = "COMMENT ON TABLE " + block.getName();
4.488 - } else if (type == PlsqlBlockType.COLUMN_COMMENT) {
4.489 - foldType = PlsqlFoldTypes.COLUMNCOMMENT;
4.490 - description = "COLUMN COMMENTS ON TABLE " + block.getName();
4.491 - } else if (type == PlsqlBlockType.COMMENT) {
4.492 - foldType = PlsqlFoldTypes.COMMENT;
4.493 - description = block.getName();
4.494 - } else if (type == PlsqlBlockType.PACKAGE) {
4.495 - foldType = PlsqlFoldTypes.PACKAGE;
4.496 - description = block.getPrefix() + "PACKAGE " + block.getName();
4.497 - } else if (type == PlsqlBlockType.PACKAGE_BODY) {
4.498 - foldType = PlsqlFoldTypes.PACKAGEBODY;
4.499 - description = block.getPrefix() + "PACKAGE BODY " + block.getName();
4.500 - } else if (type == PlsqlBlockType.PROCEDURE_IMPL) {
4.501 - foldType = PlsqlFoldTypes.PROCEDUREIMPL;
4.502 - description = block.getPrefix() + "PROCEDURE IMPLEMENTATION " + block.getName();
4.503 - } else if (type == PlsqlBlockType.FUNCTION_IMPL) {
4.504 - foldType = PlsqlFoldTypes.FUNCTIONIMPL;
4.505 - description = block.getPrefix() + "FUNCTION IMPLEMENTATION " + block.getName();
4.506 - } else if (type == PlsqlBlockType.PROCEDURE_DEF) {
4.507 - foldType = PlsqlFoldTypes.PROCEDUREDEF;
4.508 - description = "PROCEDURE DEFINITION " + block.getName();
4.509 - } else if (type == PlsqlBlockType.FUNCTION_DEF) {
4.510 - foldType = PlsqlFoldTypes.FUNCTIONDEF;
4.511 - description = "FUNCTION DEFINITION " + block.getName();
4.512 - } else if (type == PlsqlBlockType.DECLARE_END) {
4.513 - foldType = PlsqlFoldTypes.DECLAREEND;
4.514 - description = "DECLARE BLOCK";
4.515 - } else if (type == PlsqlBlockType.BEGIN_END) {
4.516 - foldType = PlsqlFoldTypes.BEGINEND;
4.517 - description = "BEGIN BLOCK";
4.518 - } else if (type == PlsqlBlockType.TRIGGER) {
4.519 - foldType = PlsqlFoldTypes.TRIGGER;
4.520 - description = block.getPrefix() + "TRIGGER " + block.getName();
4.521 - } else if (type == PlsqlBlockType.IF) {
4.522 - foldType = PlsqlFoldTypes.IF;
4.523 - description = block.getName();
4.524 - } else if (type == PlsqlBlockType.CASE) {
4.525 - foldType = PlsqlFoldTypes.CASE;
4.526 - description = block.getName();
4.527 - } else if (type == PlsqlBlockType.WHILE_LOOP) {
4.528 - foldType = PlsqlFoldTypes.WHILELOOP;
4.529 - description = "WHILE " + block.getName();
4.530 - } else if (type == PlsqlBlockType.FOR_LOOP) {
4.531 - foldType = PlsqlFoldTypes.FORLOOP;
4.532 - description = "FOR " + block.getName();
4.533 - } else if (type == PlsqlBlockType.LOOP) {
4.534 - foldType = PlsqlFoldTypes.LOOP;
4.535 - description = "LOOP ";
4.536 - } else if (type == PlsqlBlockType.CUSTOM_FOLD) {
4.537 - foldType = PlsqlFoldTypes.CUSTOM;
4.538 - description = block.getName();
4.539 - } else if (type == PlsqlBlockType.STATEMENT) {
4.540 - foldType = PlsqlFoldTypes.STATEMENT;
4.541 - description = block.getPrefix() + block.getName();
4.542 - } else if (type == PlsqlBlockType.CURSOR) {
4.543 - foldType = PlsqlFoldTypes.CURSOR;
4.544 - description = "CURSOR " + block.getName();
4.545 - } else if (type == PlsqlBlockType.JAVA_SOURCE) {
4.546 - foldType = PlsqlFoldTypes.JAVASOURCE;
4.547 - description = block.getPrefix() + "JAVA SOURCE";
4.548 + final FoldSearchObject foldSearchObject = new FoldSearchObject(block.getStartOffset(), block.getEndOffset());
4.549 + if (!foldSearchObjects.contains(foldSearchObject)) {
4.550 + try {
4.551 + final Fold fold = operation.addToHierarchy(foldType, description, isCollapsed(foldType), block.getStartOffset(), block.getEndOffset(), 0, 0, null, transaction);
4.552 + foldSearchObjects.add(new FoldSearchObject(new FoldAdapter(fold)));
4.553 + } catch (BadLocationException ex) {
4.554 + if (LOG.isLoggable(Level.FINE)) {
4.555 + LOG.log(Level.FINE, "Ignore BadLocationException", ex);
4.556 + }
4.557 + }
4.558 + }
4.559 + updateFolds(block.getChildBlocks(), transaction);
4.560 }
4.561 - //XXX: find out what offsets are needed (check CustomFoldManager when .php is run):
4.562 - final FoldMarkInfo foldMarkInfo = new FoldMarkInfo(foldType, true, block.getStartOffset(), 0, block.getName(), isCollapsed(foldType), description);
4.563 - // XXX: check if mark exist
4.564 - list.add(foldMarkInfo);
4.565 - list.add(new FoldMarkInfo(foldType, false, block.getEndOffset(), 0, null, false, null));
4.566 - scanBlocks(list, block.getChildBlocks());
4.567 - }
4.568 - }
4.569 - }
4.570 -
4.571 - private final class FoldMarkInfo {
4.572 -
4.573 - private boolean startMark;
4.574 - private Position pos;
4.575 - private int length;
4.576 - private String id;
4.577 - private boolean collapsed;
4.578 - private String description;
4.579 - /**
4.580 - * Matching pair mark used for fold construction
4.581 - */
4.582 - private FoldMarkInfo pairMark;
4.583 - /**
4.584 - * Parent mark defining nesting in the mark hierarchy.
4.585 - */
4.586 - private FoldMarkInfo parentMark;
4.587 - /**
4.588 - * Fold that corresponds to this mark (if it's start mark). It can be null if this mark is end mark or if it
4.589 - * currently does not have the fold assigned.
4.590 - */
4.591 - private Fold fold;
4.592 - private boolean released;
4.593 - private final FoldType foldType;
4.594 -
4.595 - private FoldMarkInfo(FoldType foldType, boolean startMark, int offset,
4.596 - int length, String id, boolean collapsed, String description)
4.597 - throws BadLocationException {
4.598 - this.foldType = foldType;
4.599 - this.startMark = startMark;
4.600 - this.pos = doc.createPosition(offset);
4.601 - this.length = length;
4.602 - this.id = id;
4.603 - this.collapsed = collapsed;
4.604 - this.description = description;
4.605 - }
4.606 -
4.607 - public String getId() {
4.608 - return id;
4.609 - }
4.610 -
4.611 - public String getDescription() {
4.612 - return description;
4.613 - }
4.614 -
4.615 - public boolean isStartMark() {
4.616 - return startMark;
4.617 - }
4.618 -
4.619 - public int getLength() {
4.620 - return length;
4.621 - }
4.622 -
4.623 - public int getOffset() {
4.624 - return pos.getOffset();
4.625 - }
4.626 -
4.627 - public int getEndOffset() {
4.628 - return getOffset() + getLength();
4.629 - }
4.630 -
4.631 - public boolean isCollapsed() {
4.632 - return (fold != null) ? fold.isCollapsed() : collapsed;
4.633 - }
4.634 -
4.635 - public boolean hasFold() {
4.636 - return (fold != null);
4.637 - }
4.638 -
4.639 - public void setCollapsed(boolean collapsed) {
4.640 - this.collapsed = collapsed;
4.641 - }
4.642 -
4.643 - public boolean isSolitaire() {
4.644 - return (pairMark == null);
4.645 - }
4.646 -
4.647 - public void makeSolitaire(boolean forced, FoldHierarchyTransaction transaction) {
4.648 - if (!isSolitaire()) {
4.649 - if (isStartMark()) {
4.650 - setEndMark(null, forced, transaction);
4.651 - } else { // end mark
4.652 - getPairMark().setEndMark(null, forced, transaction);
4.653 + } catch (BadLocationException ex) {
4.654 + if (LOG.isLoggable(Level.FINE)) {
4.655 + LOG.log(Level.FINE, "Ignore BadLocationException", ex);
4.656 }
4.657 }
4.658 }
4.659 -
4.660 - public boolean isReleased() {
4.661 - return released;
4.662 - }
4.663 -
4.664 - /**
4.665 - * Release this mark and mark for update.
4.666 - */
4.667 - public void release(boolean forced, FoldHierarchyTransaction transaction) {
4.668 - if (!released) {
4.669 - makeSolitaire(forced, transaction);
4.670 - released = true;
4.671 - markUpdate(this);
4.672 - }
4.673 - }
4.674 -
4.675 - public FoldMarkInfo getPairMark() {
4.676 - return pairMark;
4.677 - }
4.678 -
4.679 - private void setPairMark(FoldMarkInfo pairMark) {
4.680 - this.pairMark = pairMark;
4.681 - }
4.682 -
4.683 - public void setEndMark(FoldMarkInfo endMark, boolean forced,
4.684 - FoldHierarchyTransaction transaction) {
4.685 - if (!isStartMark()) {
4.686 - throw new IllegalStateException("Not start mark"); // NOI18N
4.687 - }
4.688 - if (pairMark == endMark) {
4.689 - return;
4.690 - }
4.691 -
4.692 - if (pairMark != null) { // is currently paired to an end mark
4.693 - releaseFold(forced, transaction);
4.694 - pairMark.setPairMark(null);
4.695 - }
4.696 -
4.697 - pairMark = endMark;
4.698 - if (endMark != null) {
4.699 - if (!endMark.isSolitaire()) { // make solitaire first
4.700 - endMark.makeSolitaire(false, transaction); // not forced here
4.701 - }
4.702 - endMark.setPairMark(this);
4.703 - endMark.setParentMark(this.getParentMark());
4.704 - ensureFoldExists(transaction);
4.705 - }
4.706 - }
4.707 -
4.708 - public FoldMarkInfo getParentMark() {
4.709 - return parentMark;
4.710 - }
4.711 -
4.712 - public void setParentMark(FoldMarkInfo parentMark) {
4.713 - this.parentMark = parentMark;
4.714 - }
4.715 -
4.716 - private void releaseFold(boolean forced, FoldHierarchyTransaction transaction) {
4.717 - if (isSolitaire() || !isStartMark()) {
4.718 - throw new IllegalStateException();
4.719 - }
4.720 -
4.721 - if (fold != null) {
4.722 - setCollapsed(fold.isCollapsed()); // serialize the collapsed info
4.723 - if (!forced) {
4.724 - getOperation().removeFromHierarchy(fold, transaction);
4.725 - }
4.726 - fold = null;
4.727 - }
4.728 - }
4.729 -
4.730 - public Fold getFold() {
4.731 - if (isSolitaire()) {
4.732 - return null;
4.733 - }
4.734 - if (!isStartMark()) {
4.735 - return pairMark.getFold();
4.736 - }
4.737 - return fold;
4.738 - }
4.739 -
4.740 - public void ensureFoldExists(FoldHierarchyTransaction transaction) {
4.741 - if (isSolitaire() || !isStartMark()) {
4.742 - throw new IllegalStateException();
4.743 - }
4.744 -
4.745 - if (fold == null) {
4.746 - try {
4.747 - if (!startMark) {
4.748 - throw new IllegalStateException("Not start mark: " + this); // NOI18N
4.749 - }
4.750 - if (pairMark == null) {
4.751 - throw new IllegalStateException("No pairMark for mark:" + this); // NOI18N
4.752 - }
4.753 - int startOffset = getOffset();
4.754 - int startGuardedLength = getLength();
4.755 - int endGuardedLength = pairMark.getLength();
4.756 - int endOffset = pairMark.getOffset() + endGuardedLength;
4.757 - // XXX: check if Fold exist before adding
4.758 - fold = getOperation().addToHierarchy(
4.759 - foldType, getDescription(), collapsed,
4.760 - startOffset, endOffset,
4.761 - startGuardedLength, endGuardedLength,
4.762 - this,
4.763 - transaction);
4.764 - } catch (BadLocationException e) {
4.765 - LOG.log(Level.WARNING, null, e);
4.766 - }
4.767 - }
4.768 - }
4.769 -
4.770 - @Override
4.771 - public String toString() {
4.772 - StringBuilder sb = new StringBuilder();
4.773 - sb.append(isStartMark() ? 'S' : 'E'); // NOI18N
4.774 -
4.775 - // Check whether this mark (or its pair) has fold
4.776 - if (hasFold() || (!isSolitaire() && getPairMark().hasFold())) {
4.777 - sb.append("F"); // NOI18N
4.778 -
4.779 - // Check fold's status
4.780 - if (isStartMark() && (isSolitaire()
4.781 - || getOffset() != fold.getStartOffset()
4.782 - || getPairMark().getEndOffset() != fold.getEndOffset())) {
4.783 - sb.append("!!<"); // NOI18N
4.784 - sb.append(fold.getStartOffset());
4.785 - sb.append(","); // NOI18N
4.786 - sb.append(fold.getEndOffset());
4.787 - sb.append(">!!"); // NOI18N
4.788 - }
4.789 - }
4.790 -
4.791 - // Append mark's internal status
4.792 - sb.append(" ("); // NOI18N
4.793 - sb.append("o="); // NOI18N
4.794 - sb.append(pos.getOffset());
4.795 - sb.append(", l="); // NOI18N
4.796 - sb.append(length);
4.797 - sb.append(", d='"); // NOI18N
4.798 - sb.append(description);
4.799 - sb.append('\'');
4.800 - if (getPairMark() != null) {
4.801 - sb.append(", <->"); // NOI18N
4.802 - sb.append(getPairMark().getOffset());
4.803 - }
4.804 - if (getParentMark() != null) {
4.805 - sb.append(", ^"); // NOI18N
4.806 - sb.append(getParentMark().getOffset());
4.807 - }
4.808 - sb.append(')');
4.809 -
4.810 - return sb.toString();
4.811 - }
4.812 }
4.813
4.814 /**
5.1 --- a/PLSQL/Folding/src/org/netbeans/modules/plsql/fold/PlsqlFoldManagerFactory.java Fri Mar 15 14:14:52 2013 +0100
5.2 +++ b/PLSQL/Folding/src/org/netbeans/modules/plsql/fold/PlsqlFoldManagerFactory.java Fri Mar 15 14:16:18 2013 +0100
5.3 @@ -60,6 +60,9 @@
5.4 if ("old".equals(property)) {
5.5 return new PlsqlFoldManager();
5.6 }
5.7 + if ("simple".equals(property)) {
5.8 + return new SimplePlsqlFoldManager();
5.9 + }
5.10 return new NewPlsqlFoldManager();
5.11 }
5.12 }
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/PLSQL/Folding/src/org/netbeans/modules/plsql/fold/SimplePlsqlFoldManager.java Fri Mar 15 14:16:18 2013 +0100
6.3 @@ -0,0 +1,366 @@
6.4 +/*
6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
6.6 + *
6.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
6.8 + *
6.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
6.10 + * Other names may be trademarks of their respective owners.
6.11 + *
6.12 + * The contents of this file are subject to the terms of either the GNU
6.13 + * General Public License Version 2 only ("GPL") or the Common
6.14 + * Development and Distribution License("CDDL") (collectively, the
6.15 + * "License"). You may not use this file except in compliance with the
6.16 + * License. You can obtain a copy of the License at
6.17 + * http://www.netbeans.org/cddl-gplv2.html
6.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
6.19 + * specific language governing permissions and limitations under the
6.20 + * License. When distributing the software, include this License Header
6.21 + * Notice in each file and include the License file at
6.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
6.23 + * particular file as subject to the "Classpath" exception as provided
6.24 + * by Oracle in the GPL Version 2 section of the License file that
6.25 + * accompanied this code. If applicable, add the following below the
6.26 + * License Header, with the fields enclosed by brackets [] replaced by
6.27 + * your own identifying information:
6.28 + * "Portions Copyrighted [year] [name of copyright owner]"
6.29 + *
6.30 + * If you wish your version of this file to be governed by only the CDDL
6.31 + * or only the GPL Version 2, indicate your decision by adding
6.32 + * "[Contributor] elects to include this software in this distribution
6.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
6.34 + * single choice of license, a recipient has the option to distribute
6.35 + * your version of this file under either the CDDL, the GPL Version 2 or
6.36 + * to extend the choice of license to its licensees as provided above.
6.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
6.38 + * Version 2 license, then the option applies only if the new code is
6.39 + * made subject to such option by the copyright holder.
6.40 + *
6.41 + * Contributor(s):
6.42 + *
6.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
6.44 + */
6.45 +package org.netbeans.modules.plsql.fold;
6.46 +
6.47 +import java.util.ArrayList;
6.48 +import java.util.List;
6.49 +import java.util.Observable;
6.50 +import java.util.Observer;
6.51 +import java.util.logging.Level;
6.52 +import java.util.logging.Logger;
6.53 +import javax.swing.event.DocumentEvent;
6.54 +import javax.swing.text.BadLocationException;
6.55 +import javax.swing.text.Document;
6.56 +import org.netbeans.api.editor.fold.Fold;
6.57 +import org.netbeans.api.editor.fold.FoldHierarchy;
6.58 +import org.netbeans.api.editor.fold.FoldType;
6.59 +import org.netbeans.api.editor.fold.FoldUtilities;
6.60 +import org.netbeans.editor.BaseDocument;
6.61 +import org.netbeans.modules.plsql.lexer.PlsqlBlock;
6.62 +import org.netbeans.modules.plsql.lexer.PlsqlBlockFactory;
6.63 +import org.netbeans.modules.plsql.lexer.PlsqlBlockType;
6.64 +import org.netbeans.modules.plsqlsupport.options.OptionsUtilities;
6.65 +import org.netbeans.spi.editor.fold.FoldHierarchyTransaction;
6.66 +import org.netbeans.spi.editor.fold.FoldManager;
6.67 +import org.netbeans.spi.editor.fold.FoldOperation;
6.68 +import org.openide.util.Lookup;
6.69 +import org.openide.util.RequestProcessor;
6.70 +
6.71 +/**
6.72 + *
6.73 + * @author chrlse
6.74 + */
6.75 +public class SimplePlsqlFoldManager implements FoldManager, Runnable, Observer {
6.76 +
6.77 + private static final Logger LOG = Logger.getLogger(SimplePlsqlFoldManager.class.getName());
6.78 + private static final int TASK_DELAY = 500;
6.79 + private FoldOperation operation;
6.80 + private Document doc;
6.81 + private static final RequestProcessor RP = new RequestProcessor(SimplePlsqlFoldManager.class.getName(), 1, false, false);
6.82 + private final RequestProcessor.Task task = RP.create(this);
6.83 + private PlsqlBlockFactory blockFactory;
6.84 +
6.85 + @Override
6.86 + public void init(FoldOperation operation) {
6.87 + this.operation = operation;
6.88 + if (LOG.isLoggable(Level.FINE)) {
6.89 + LOG.log(Level.FINE, "Initialized: {0}", System.identityHashCode(this));
6.90 + }
6.91 + }
6.92 +
6.93 + private FoldOperation getOperation() {
6.94 + return operation;
6.95 + }
6.96 +
6.97 + @Override
6.98 + public void initFolds(FoldHierarchyTransaction transaction) {
6.99 + doc = getOperation().getHierarchy().getComponent().getDocument();
6.100 + blockFactory = getBlockFactory();
6.101 + if (blockFactory != null) {
6.102 + blockFactory.addObserver(this);
6.103 + }
6.104 + task.schedule(TASK_DELAY);
6.105 + }
6.106 +
6.107 + @Override
6.108 + public void insertUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
6.109 +// task.schedule(300);
6.110 +// processRemovedFolds(transaction);
6.111 + if (LOG.isLoggable(Level.FINE)) {
6.112 + LOG.log(Level.FINE, "insertUpdate: {0}", System.identityHashCode(this));
6.113 + }
6.114 + }
6.115 +
6.116 + @Override
6.117 + public void removeUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
6.118 + if (LOG.isLoggable(Level.FINE)) {
6.119 + LOG.log(Level.FINE, "removeUpdate: {0}", System.identityHashCode(this));
6.120 + }
6.121 + task.schedule(TASK_DELAY);
6.122 +// processRemovedFolds(transaction);
6.123 +// removeAffectedMarks(evt, transaction);
6.124 + }
6.125 +
6.126 + @Override
6.127 + public void changedUpdate(DocumentEvent evt, FoldHierarchyTransaction transaction) {
6.128 + if (LOG.isLoggable(Level.FINE)) {
6.129 + LOG.log(Level.FINE, "changedUpdate: {0}", System.identityHashCode(this));
6.130 + }
6.131 +// task.schedule(300);
6.132 + }
6.133 +
6.134 + @Override
6.135 + public void removeEmptyNotify(Fold emptyFold) {
6.136 +// removeFoldNotify(emptyFold);
6.137 + }
6.138 +
6.139 + @Override
6.140 + public void removeDamagedNotify(Fold damagedFold) {
6.141 +// removeFoldNotify(damagedFold);
6.142 + }
6.143 +
6.144 + @Override
6.145 + public void expandNotify(Fold expandedFold) {
6.146 + }
6.147 +
6.148 + @Override
6.149 + public void release() {
6.150 + if (LOG.isLoggable(Level.FINE)) {
6.151 + LOG.log(Level.FINE, "release: {0}", System.identityHashCode(this));
6.152 + }
6.153 + }
6.154 +
6.155 + @Override
6.156 + public void update(Observable o, Object arg) {
6.157 + if (LOG.isLoggable(Level.FINE)) {
6.158 + LOG.log(Level.FINE, "update: {0}", System.identityHashCode(this));
6.159 + }
6.160 + task.schedule(TASK_DELAY);
6.161 + }
6.162 +
6.163 + @Override
6.164 + public void run() {
6.165 + if (operation.isReleased()) {
6.166 + if (LOG.isLoggable(Level.FINE)) {
6.167 + LOG.log(Level.FINE, "Update skipped, already released: {0}", System.identityHashCode(this));
6.168 + }
6.169 + return;
6.170 + }
6.171 + ((BaseDocument) doc).readLock();
6.172 + try {
6.173 +
6.174 + if (blockFactory != null) {
6.175 + FoldHierarchy hierarchy = getOperation().getHierarchy();
6.176 + hierarchy.lock();
6.177 + try {
6.178 + if (operation.isReleased()) {
6.179 + if (LOG.isLoggable(Level.FINE)) {
6.180 + LOG.log(Level.FINE, "Update skipped, already released: {0}", System.identityHashCode(this));
6.181 + }
6.182 + return;
6.183 + }
6.184 + if (LOG.isLoggable(Level.FINE)) {
6.185 + LOG.log(Level.FINE, "Updating: {0}", System.identityHashCode(this));
6.186 + LOG.log(Level.FINE, "blockFactory.getBlockHierarchy().size(): {0}", blockFactory.getBlockHierarchy().size());
6.187 + LOG.log(Level.FINE, "blockFactory.getNewBlocks().size(): {0}", blockFactory.getNewBlocks().size());
6.188 + LOG.log(Level.FINE, "blockFactory.getRemovedBlocks().size(): {0}", blockFactory.getRemovedBlocks().size());
6.189 + }
6.190 + FoldHierarchyTransaction transaction = getOperation().openTransaction();
6.191 + try {
6.192 + //Add new blocks to the hierarchy
6.193 + ArrayList<Fold> existingFolds = new ArrayList<Fold>();
6.194 + collectExistingFolds(hierarchy.getRootFold(), existingFolds);
6.195 + for (Fold f : existingFolds) {
6.196 + getOperation().removeFromHierarchy(f, transaction);
6.197 + }
6.198 + List<PlsqlBlock> blocks = blockFactory.getBlockHierarchy();
6.199 + createFolds(blocks, transaction);
6.200 + } finally {
6.201 + transaction.commit();
6.202 + }
6.203 + } finally {
6.204 + hierarchy.unlock();
6.205 + }
6.206 + }
6.207 + } finally {
6.208 + ((BaseDocument) doc).readUnlock();
6.209 + }
6.210 + }
6.211 +
6.212 + /**
6.213 + * Collects all folds from the hierarchy that were created by this manager and are not the root fold.
6.214 + *
6.215 + * @param fold
6.216 + * @param list
6.217 + */
6.218 + private void collectExistingFolds(Fold fold, List<Fold> list) {
6.219 + for (int i = 0; i < fold.getFoldCount(); i++) {
6.220 + collectExistingFolds(fold.getFold(i), list);
6.221 + }
6.222 + if (!FoldUtilities.isRootFold(fold) && getOperation().owns(fold)) {
6.223 + list.add(fold);
6.224 + }
6.225 + }
6.226 +
6.227 + /**
6.228 + * Creates a new fold and adds to the fold hierarchy.
6.229 + */
6.230 +// private Fold createFold(FoldType type, String description, boolean collapsed,
6.231 +// int startOffset, int endOffset, FoldHierarchyTransaction transaction)
6.232 +// throws BadLocationException {
6.233 +// Fold fold = null;
6.234 +// if ( startOffset >= 0 &&
6.235 +// endOffset >= 0 &&
6.236 +// startOffset < endOffset &&
6.237 +// endOffset <= getDocument().getLength() ) {
6.238 +// fold = getOperation().addToHierarchy(
6.239 +// type,
6.240 +// description.intern(), //save some memory
6.241 +// collapsed,
6.242 +// startOffset,
6.243 +// endOffset,
6.244 +// description.length(),
6.245 +// 0,
6.246 +// null,
6.247 +// transaction);
6.248 +// }
6.249 +// return fold;
6.250 +// }
6.251 + private void createFolds(List<PlsqlBlock> blocks, FoldHierarchyTransaction transaction) {
6.252 + for (PlsqlBlock block : blocks) {
6.253 +
6.254 + FoldType foldType = null;
6.255 + final PlsqlBlockType type = block.getType();
6.256 + String description = null;
6.257 + try {
6.258 + if (!(type == PlsqlBlockType.COMMENT && doc.getText(block.getStartOffset(), block.getEndOffset() - block.getStartOffset()).indexOf("\n") == -1)) { // check for single line comments
6.259 + if (type == PlsqlBlockType.VIEW) {
6.260 + foldType = PlsqlFoldTypes.VIEW;
6.261 + description = block.getPrefix() + "VIEW " + block.getName();
6.262 + } else if (type == PlsqlBlockType.TABLE_COMMENT) {
6.263 + foldType = PlsqlFoldTypes.TABLECOMMENT;
6.264 + description = "COMMENT ON TABLE " + block.getName();
6.265 + } else if (type == PlsqlBlockType.COLUMN_COMMENT) {
6.266 + foldType = PlsqlFoldTypes.COLUMNCOMMENT;
6.267 + description = "COLUMN COMMENTS ON TABLE " + block.getName();
6.268 + } else if (type == PlsqlBlockType.COMMENT) {
6.269 + foldType = PlsqlFoldTypes.COMMENT;
6.270 + description = block.getName();
6.271 + } else if (type == PlsqlBlockType.PACKAGE) {
6.272 + foldType = PlsqlFoldTypes.PACKAGE;
6.273 + description = block.getPrefix() + "PACKAGE " + block.getName();
6.274 + } else if (type == PlsqlBlockType.PACKAGE_BODY) {
6.275 + foldType = PlsqlFoldTypes.PACKAGEBODY;
6.276 + description = block.getPrefix() + "PACKAGE BODY " + block.getName();
6.277 + } else if (type == PlsqlBlockType.PROCEDURE_IMPL) {
6.278 + foldType = PlsqlFoldTypes.PROCEDUREIMPL;
6.279 + description = block.getPrefix() + "PROCEDURE IMPLEMENTATION " + block.getName();
6.280 + } else if (type == PlsqlBlockType.FUNCTION_IMPL) {
6.281 + foldType = PlsqlFoldTypes.FUNCTIONIMPL;
6.282 + description = block.getPrefix() + "FUNCTION IMPLEMENTATION " + block.getName();
6.283 + } else if (type == PlsqlBlockType.PROCEDURE_DEF) {
6.284 + foldType = PlsqlFoldTypes.PROCEDUREDEF;
6.285 + description = "PROCEDURE DEFINITION " + block.getName();
6.286 + } else if (type == PlsqlBlockType.FUNCTION_DEF) {
6.287 + foldType = PlsqlFoldTypes.FUNCTIONDEF;
6.288 + description = "FUNCTION DEFINITION " + block.getName();
6.289 + } else if (type == PlsqlBlockType.DECLARE_END) {
6.290 + foldType = PlsqlFoldTypes.DECLAREEND;
6.291 + description = "DECLARE BLOCK";
6.292 + } else if (type == PlsqlBlockType.BEGIN_END) {
6.293 + foldType = PlsqlFoldTypes.BEGINEND;
6.294 + description = "BEGIN BLOCK";
6.295 + } else if (type == PlsqlBlockType.TRIGGER) {
6.296 + foldType = PlsqlFoldTypes.TRIGGER;
6.297 + description = block.getPrefix() + "TRIGGER " + block.getName();
6.298 + } else if (type == PlsqlBlockType.IF) {
6.299 + foldType = PlsqlFoldTypes.IF;
6.300 + description = block.getName();
6.301 + } else if (type == PlsqlBlockType.CASE) {
6.302 + foldType = PlsqlFoldTypes.CASE;
6.303 + description = block.getName();
6.304 + } else if (type == PlsqlBlockType.WHILE_LOOP) {
6.305 + foldType = PlsqlFoldTypes.WHILELOOP;
6.306 + description = "WHILE " + block.getName();
6.307 + } else if (type == PlsqlBlockType.FOR_LOOP) {
6.308 + foldType = PlsqlFoldTypes.FORLOOP;
6.309 + description = "FOR " + block.getName();
6.310 + } else if (type == PlsqlBlockType.LOOP) {
6.311 + foldType = PlsqlFoldTypes.LOOP;
6.312 + description = "LOOP ";
6.313 + } else if (type == PlsqlBlockType.CUSTOM_FOLD) {
6.314 + foldType = PlsqlFoldTypes.CUSTOM;
6.315 + description = block.getName();
6.316 + } else if (type == PlsqlBlockType.STATEMENT) {
6.317 + foldType = PlsqlFoldTypes.STATEMENT;
6.318 + description = block.getPrefix() + block.getName();
6.319 + } else if (type == PlsqlBlockType.CURSOR) {
6.320 + foldType = PlsqlFoldTypes.CURSOR;
6.321 + description = "CURSOR " + block.getName();
6.322 + } else if (type == PlsqlBlockType.JAVA_SOURCE) {
6.323 + foldType = PlsqlFoldTypes.JAVASOURCE;
6.324 + description = block.getPrefix() + "JAVA SOURCE";
6.325 + }
6.326 + try {
6.327 + operation.addToHierarchy(foldType, description, isCollapsed(foldType), block.getStartOffset(), block.getEndOffset(), 0, 0, null, transaction);
6.328 + } catch (BadLocationException ex) {
6.329 + if (LOG.isLoggable(Level.FINE)) {
6.330 + LOG.log(Level.FINE, "Ignore BadLocationException", ex);
6.331 + }
6.332 + }
6.333 + createFolds(block.getChildBlocks(), transaction);
6.334 + }
6.335 + } catch (BadLocationException ex) {
6.336 + if (LOG.isLoggable(Level.FINE)) {
6.337 + LOG.log(Level.FINE, "Ignore BadLocationException", ex);
6.338 + }
6.339 + }
6.340 + }
6.341 + }
6.342 +
6.343 + /**
6.344 + * Method that will select and return the corresponding fold to parent from oldRoot fold hierarchy
6.345 + *
6.346 + * @param parent
6.347 + * @param foldInfoLst
6.348 + * @return
6.349 + */
6.350 + private boolean isCollapsed(final FoldType foldType) {
6.351 + if (OptionsUtilities.isPlSqlExpandFolds()) {
6.352 + return false;
6.353 + }
6.354 + return foldType == PlsqlFoldTypes.COMMENT;
6.355 + }
6.356 +
6.357 + /**
6.358 + * Method that will return the relevant block factory
6.359 + *
6.360 + * @return
6.361 + */
6.362 + private PlsqlBlockFactory getBlockFactory() {
6.363 + final Object obj = doc.getProperty(Document.StreamDescriptionProperty);
6.364 + if (obj instanceof Lookup.Provider) {
6.365 + return ((Lookup.Provider) obj).getLookup().lookup(PlsqlBlockFactory.class);
6.366 + }
6.367 + return null;
6.368 + }
6.369 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/PLSQL/Folding/test/unit/src/org/netbeans/modules/plsql/fold/FoldSearchObjectTest.java Fri Mar 15 14:16:18 2013 +0100
7.3 @@ -0,0 +1,28 @@
7.4 +/*
7.5 + * To change this template, choose Tools | Templates
7.6 + * and open the template in the editor.
7.7 + */
7.8 +package org.netbeans.modules.plsql.fold;
7.9 +
7.10 +import org.junit.Test;
7.11 +import static org.junit.Assert.*;
7.12 +import static org.mockito.Mockito.*;
7.13 +
7.14 +/**
7.15 + *
7.16 + * @author ChrLSE
7.17 + */
7.18 +public class FoldSearchObjectTest {
7.19 +
7.20 + @Test
7.21 + public void shouldBeEqualWithAndWithoutBackingFoldObject() {
7.22 + int startOffset = 100;
7.23 + int endOffset = 200;
7.24 + FoldSearchObject searchObject1 = new FoldSearchObject(startOffset, endOffset);
7.25 + FoldAdapter fold = mock(FoldAdapter.class);
7.26 + FoldSearchObject searchObject2 = new FoldSearchObject(fold);
7.27 + when(fold.getStartOffset()).thenReturn(startOffset);
7.28 + when(fold.getEndOffset()).thenReturn(endOffset);
7.29 + assertEquals(searchObject1, searchObject2);
7.30 + }
7.31 +}
7.32 \ No newline at end of file