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; |