package com.github.elucash.lambda4jdt; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Region; class RegionDemarkator { private LinkedList<RegionHandle> regions = new LinkedList<RegionHandle>(); private int startedOffset = -1; int initialOffset; int finalOffset; boolean wasZeroOffset = false; void start(int offset) { if (offset == 0) { if (wasZeroOffset) throw new IllegalStateException("zero offset"); wasZeroOffset = true; } offset += initialOffset; if (startedOffset >= 0) throw new IllegalStateException("allready started"); startedOffset = offset; started = true; } boolean started; RegionHandle end(int end) { end += initialOffset; if (startedOffset < 0 || end < startedOffset) throw new IllegalStateException("no start or illegal position"); int offset = startedOffset; startedOffset = -1; started = false; return range(offset, end - offset); } private RegionHandle range(int offset, int length) { RegionHandle region = new RegionHandle(offset, length); regions.add(region); return region; } IRegion[] toProcessedArray(IRegion prefix, IRegion suffix) { ArrayList<IRegion> processedList = processToList(); processedList.add(finalOffset, prefix); processedList.add(suffix); return processedList.toArray(new IRegion[processToList().size()]); } IRegion[] toProcessedArray() { return processToList().toArray(new IRegion[processToList().size()]); } private ArrayList<IRegion> processToList() { ArrayList<IRegion> result = new ArrayList<IRegion>(); Collections.sort(regions); RegionHandle lastRegion = null; for (RegionHandle r : regions) { if (!r.mergeIfPossibleTo(lastRegion)) { addIfNotObsolete(result, lastRegion); lastRegion = r; } } addIfNotObsolete(result, lastRegion); return result; } private void addIfNotObsolete(List<IRegion> result, RegionHandle region) { if (region != null) if (region.correct()) result.add(region.toRegion()); } class RegionHandle implements Comparable<RegionHandle> { int offset; int length; RegionHandle(int offset, int length) { this.offset = offset; this.length = length; } void reveal() { regions.remove(this); } public int compareTo(RegionHandle o) { return offset - o.offset; } private boolean correct() { if (length == 0) return false; if (finalOffset > initialOffset) { if (offset >= finalOffset) return false; if (offset + length > finalOffset) { length = finalOffset - offset; } } return true; } private boolean mergeIfPossibleTo(RegionHandle r) { if (r == null) return false; // goes after region r and begins before or just right after region r end int endOfR = r.offset + r.length; if (offset >= r.offset && offset <= endOfR) { int requiredLength = offset + length; if (requiredLength > endOfR) r.length = requiredLength - r.offset; return true; } return false; } private Region toRegion() { return new Region(offset, length); } public String toString() { return "[" + offset + '+' + length + ']'; } } }