View | Details | Raw Unified | Return to bug 234583 | Differences between
and this patch

Collapse All | Expand All

(-)formatter/org/eclipse/jdt/internal/formatter/Scribe.java (-17 / +178 lines)
Lines 165-190 Link Here
165
			if (index >= 0) {
165
			if (index >= 0) {
166
				// the offset of the region is inside a comment => restart the region from the comment start
166
				// the offset of the region is inside a comment => restart the region from the comment start
167
				adaptedOffset = this.commentPositions[index][0];
167
				adaptedOffset = this.commentPositions[index][0];
168
				if (adaptedOffset < 0) adaptedOffset = -adaptedOffset;
168
				if (adaptedOffset >= 0) {
169
				adaptedLength = length + offset - adaptedOffset;
169
					// adapt only javadoc or block commments. Since fix for bug
170
				commentIndex = index;
170
					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=238210
171
				// include also the indentation edit just before the comment if any
171
					// edits in line comments only concerns whitespaces hence can be
172
				for (int j=0; j<this.editsIndex; j++) {
172
					// treated as edits in code
173
					int editOffset = this.edits[j].offset;
173
					adaptedLength = length + offset - adaptedOffset;
174
					int editEnd = editOffset + this.edits[j].length;
174
					commentIndex = index;
175
					if (editEnd == adaptedOffset) {
175
					// include also the indentation edit just before the comment if any
176
						if (j > 0 && this.edits[j].replacement.trim().length() == 0) {
176
					for (int j=0; j<this.editsIndex; j++) {
177
							adaptedLength += adaptedOffset - this.edits[j].offset;
177
						int editOffset = this.edits[j].offset;
178
							adaptedOffset = editOffset;
178
						int editEnd = editOffset + this.edits[j].length;
179
						if (editEnd == adaptedOffset) {
180
							if (j > 0 && this.edits[j].replacement.trim().length() == 0) {
181
								adaptedLength += adaptedOffset - this.edits[j].offset;
182
								adaptedOffset = editOffset;
183
								break;
184
							}
185
						} else if (editEnd > adaptedOffset) {
179
							break;
186
							break;
180
						}
187
						}
181
					} else if (editEnd > adaptedOffset) {
182
						break;
183
					}
188
					}
184
				}
189
				}
185
			}
190
			}
186
			index = getCommentIndex(commentIndex, offset+length-1);
191
			index = getCommentIndex(commentIndex, offset+length-1);
187
			if (index >= 0) {
192
			if (index >= 0 && this.commentPositions[index][0] >= 0) { // only javadoc or block comment
188
				// the region end is inside a comment => set the region end at the comment end
193
				// the region end is inside a comment => set the region end at the comment end
189
				int commentEnd = this.commentPositions[index][1];
194
				int commentEnd = this.commentPositions[index][1];
190
				if (commentEnd < 0) commentEnd = -commentEnd;
195
				if (commentEnd < 0) commentEnd = -commentEnd;
Lines 194-202 Link Here
194
			if (adaptedLength != length) {
199
			if (adaptedLength != length) {
195
				// adapt the region and jump to next one
200
				// adapt the region and jump to next one
196
				this.adaptedRegions[i] = new Region(adaptedOffset, adaptedLength);
201
				this.adaptedRegions[i] = new Region(adaptedOffset, adaptedLength);
197
				continue;
202
//				continue;
203
			} else {
204
				this.adaptedRegions[i] = aRegion;
198
			}
205
			}
199
206
207
			/*
200
			if (offset > 0) {
208
			if (offset > 0) {
201
				if (isAdaptableRegion(offset, length)) {
209
				if (isAdaptableRegion(offset, length)) {
202
					// if we have a selection, search for overlapping edits
210
					// if we have a selection, search for overlapping edits
Lines 254-262 Link Here
254
			} else {
262
			} else {
255
				this.adaptedRegions[i] = this.regions[i];
263
				this.adaptedRegions[i] = this.regions[i];
256
			}
264
			}
265
			*/
266
		}
267
	}
268
269
	/*
270
	 * Adapt edits to regions.
271
	 * 
272
	 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=234583#c2"
273
	 * 	for more details
274
	 */
275
	private void adaptEdits() {
276
277
		// See if adapting edits is really necessary
278
		int max = this.regions.length;
279
		if (max == 1) {
280
			if (this.regions[0].getOffset() == 0 && this.regions[0].getLength() == this.scannerEndPosition) {
281
				// No need to adapt as the regions covers the whole source
282
				return;
283
			}
284
		}
285
286
		// Sort edits
287
		OptimizedReplaceEdit[] sortedEdits = new OptimizedReplaceEdit[this.editsIndex];
288
		System.arraycopy(this.edits, 0, sortedEdits, 0, this.editsIndex);
289
//		long start = System.currentTimeMillis();
290
		Arrays.sort(sortedEdits, new Comparator() {
291
			public int compare(Object o1, Object o2) {
292
		    	OptimizedReplaceEdit edit1 = (OptimizedReplaceEdit) o1;
293
		    	OptimizedReplaceEdit edit2 = (OptimizedReplaceEdit) o2;
294
				return edit1.offset - edit2.offset;
295
            }
296
		});
297
//		System.out.println("Time to sort edits = "+(System.currentTimeMillis()-start));
298
299
		// Adapt overlapping edits
300
		int currentEdit = -1;
301
		for (int i = 0; i < max; i++) {
302
			IRegion region = this.regions[i];
303
			int offset = region.getOffset();
304
			int length = region.getLength();
305
306
			// modify overlapping edits on the region (if any)
307
			if (length > 1) { // nothing can be done for region which have only one character...
308
				int index = modifyOverlappingEdit(sortedEdits, currentEdit, offset, offset+length);
309
				if (index != -1) {
310
					currentEdit = index;
311
				}
312
			}
257
		}
313
		}
258
	}
314
	}
259
315
316
260
	private final void addDeleteEdit(int start, int end) {
317
	private final void addDeleteEdit(int start, int end) {
261
		if (this.edits.length == this.editsIndex) {
318
		if (this.edits.length == this.editsIndex) {
262
			// resize
319
			// resize
Lines 607-612 Link Here
607
    	return -1;
664
    	return -1;
608
    }
665
    }
609
666
667
	/*
668
     *
669
     */
670
    private int modifyOverlappingEdit(OptimizedReplaceEdit[] sortedEdits, int start, int regionStart, int regionEnd) {
671
    	int bottom = start==-1?0:start, top = sortedEdits.length - 1;
672
    	int topEnd = top;
673
    	int i = 0;
674
    	OptimizedReplaceEdit edit = null;
675
    	int overlapIndex = -1;
676
    	int currentLine = 1;
677
    	
678
    	// Look for an edit overlapping the region start 
679
    	while (bottom <= top) {
680
    		i = bottom + (top - bottom) /2;
681
    		edit = sortedEdits[i];
682
    		int editStart = edit.offset;
683
   			int editEnd = editStart + edit.length;
684
    		if (regionStart < editStart) {
685
    			top = i-1;
686
    			if (regionEnd < editStart) {
687
    				topEnd = top;
688
    			}
689
    		} else {
690
    			if (regionStart >= editEnd) {
691
	    			bottom = i+1;
692
				} else {
693
					
694
					// restart the edit at the beginning of the line where the region start
695
					currentLine = Util.getLineNumber(regionStart, this.lineEnds, currentLine<2?0:currentLine-2, this.maxLines);
696
					int lineStart = currentLine == 1 ? 0 : getLineEnd(currentLine-1) + 1;
697
					edit.offset = lineStart;
698
					edit.length -= edit.offset - editStart;
699
700
					// keep the end of replacement after the last line break
701
					int length = edit.replacement.length();
702
					if (length > 0) {
703
						int idx = length - 1;
704
						char ch = edit.replacement.charAt(idx);
705
						while (ch != '\r' && ch != '\n') {
706
							if (--idx < 0) break;
707
							ch = edit.replacement.charAt(idx);
708
						}
709
						if (idx > 0) {
710
							if ((idx+1)==length) {
711
								edit.replacement = ""; //$NON-NLS-1$
712
							} else {
713
								edit.replacement = edit.replacement.substring(idx+1);
714
							}
715
						}
716
					}
717
					overlapIndex = i;
718
					break;
719
				}
720
			}
721
    	}
722
    	
723
    	// Look for an edit overlapping the region end 
724
    	if (overlapIndex != -1) bottom = overlapIndex;
725
    	while (bottom <= topEnd) {
726
    		i = bottom + (topEnd - bottom) /2;
727
    		edit = sortedEdits[i];
728
    		int editStart = edit.offset;
729
   			int editEnd = editStart + edit.length;
730
    		if (regionEnd < editStart) {
731
    			topEnd = i-1;
732
    		} else {
733
    			if (regionEnd >= editEnd) {
734
	    			bottom = i+1;
735
				} else {
736
					// count lines between region and edits ends
737
					int lineRegionEnd = Util.getLineNumber(regionEnd, this.lineEnds, currentLine<2?0:currentLine-2, this.maxLines);
738
					currentLine = Util.getLineNumber(editEnd, this.lineEnds, lineRegionEnd<2?0:lineRegionEnd-2, this.maxLines);
739
					int delta = currentLine - lineRegionEnd;
740
741
					// try to keep the same number of lines in the new replacement string
742
					int length = edit.replacement.length();
743
					if (length > 0) {
744
						int idx = 0;
745
						int count = 0;
746
						char ch = edit.replacement.charAt(idx);
747
						while (ch == '\r' || ch == '\n') {
748
							if (ch == '\n') count++;
749
							if (count == delta || ++idx == length) break;
750
							ch = edit.replacement.charAt(idx);
751
						}
752
						if (idx > 0) {
753
							if (idx == length) {
754
								edit.replacement = ""; //$NON-NLS-1$
755
							} else {
756
								edit.replacement = edit.replacement.substring(idx);
757
							}
758
						}
759
					}
760
					edit.length -= editEnd - regionEnd;
761
					return i;
762
				}
763
			}
764
    	}
765
    	return overlapIndex;
766
    }
767
610
	private IRegion getCoveringAdaptedRegion(int offset, int end) {
768
	private IRegion getCoveringAdaptedRegion(int offset, int end) {
611
		int index = getIndexOfAdaptedRegionAt(offset);
769
		int index = getIndexOfAdaptedRegionAt(offset);
612
770
Lines 805-810 Link Here
805
	public TextEdit getRootEdit() {
963
	public TextEdit getRootEdit() {
806
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=208541
964
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=208541
807
		adaptRegions();
965
		adaptRegions();
966
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=234583
967
		adaptEdits();
808
968
809
		MultiTextEdit edit = null;
969
		MultiTextEdit edit = null;
810
		int regionsLength = this.adaptedRegions.length;
970
		int regionsLength = this.adaptedRegions.length;
Lines 951-957 Link Here
951
		this.formatterCommentParser.scanner.linePtr = this.maxLines;
1111
		this.formatterCommentParser.scanner.linePtr = this.maxLines;
952
	}
1112
	}
953
1113
954
	/**
1114
	/*
955
	 * Returns whether the given region should be adpated of not.
1115
	 * Returns whether the given region should be adpated of not.
956
	 * A region should be adapted only if:
1116
	 * A region should be adapted only if:
957
	 * - region does not exceed the page width
1117
	 * - region does not exceed the page width
Lines 959-965 Link Here
959
	 * @param offset the offset of the region to consider
1119
	 * @param offset the offset of the region to consider
960
	 * @param length the length of the region to consider
1120
	 * @param length the length of the region to consider
961
	 * @return boolean true if line should be adapted, false otherwhise
1121
	 * @return boolean true if line should be adapted, false otherwhise
962
	 */
1122
	 *
963
	private boolean isAdaptableRegion(int offset, int length) {
1123
	private boolean isAdaptableRegion(int offset, int length) {
964
		int regionEnd = offset + length;
1124
		int regionEnd = offset + length;
965
1125
Lines 1000-1005 Link Here
1000
		}
1160
		}
1001
		return false;
1161
		return false;
1002
	}
1162
	}
1163
	*/
1003
1164
1004
	private boolean isOnFirstColumn(int start) {
1165
	private boolean isOnFirstColumn(int start) {
1005
		if (this.lineEnds == null) return start == 0;
1166
		if (this.lineEnds == null) return start == 0;

Return to bug 234583