/* * Copyright (c) 2013, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.engine.utilities.source; import com.google.dart.engine.element.Element; import com.google.dart.engine.source.Source; /** * A source range defines an {@link Element}'s source coordinates relative to its {@link Source}. * * @coverage dart.engine.utilities */ public final class SourceRange { /** * An empty {@link SourceRange} with offset {@code 0} and length {@code 0}. */ public static final SourceRange EMPTY = new SourceRange(0, 0); /** * The 0-based index of the first character of the source code for this element, relative to the * source buffer in which this element is contained. */ private final int offset; /** * The number of characters of the source code for this element, relative to the source buffer in * which this element is contained. */ private final int length; /** * Initialize a newly created source range using the given offset and the given length. * * @param offset the given offset * @param length the given length */ public SourceRange(int offset, int length) { this.offset = offset; this.length = length; } /** * @return {@code true} if <code>x</code> is in [offset, offset + length) interval. */ public boolean contains(int x) { return offset <= x && x < offset + length; } /** * @return {@code true} if <code>x</code> is in (offset, offset + length) interval. */ public boolean containsExclusive(int x) { return offset < x && x < offset + length; } /** * @return {@code true} if <code>otherRange</code> covers this {@link SourceRange}. */ public boolean coveredBy(SourceRange otherRange) { return otherRange.covers(this); } /** * @return {@code true} if this {@link SourceRange} covers <code>otherRange</code>. */ public boolean covers(SourceRange otherRange) { return getOffset() <= otherRange.getOffset() && otherRange.getEnd() <= getEnd(); } /** * @return {@code true} if this {@link SourceRange} ends in <code>otherRange</code>. */ public boolean endsIn(SourceRange otherRange) { int thisEnd = getEnd(); return otherRange.contains(thisEnd); } @Override public boolean equals(Object obj) { if (!(obj instanceof SourceRange)) { return false; } SourceRange sourceRange = (SourceRange) obj; return sourceRange.getOffset() == offset && sourceRange.getLength() == length; } /** * @return the 0-based index of the after-last character of the source code for this element, * relative to the source buffer in which this element is contained. */ public int getEnd() { return offset + length; } /** * @return the expanded instance of {@link SourceRange}, which has the same center. */ public SourceRange getExpanded(int delta) { return new SourceRange(offset - delta, delta + length + delta); } /** * Returns the number of characters of the source code for this element, relative to the source * buffer in which this element is contained. * * @return the number of characters of the source code for this element, relative to the source * buffer in which this element is contained */ public int getLength() { return length; } /** * @return the instance of {@link SourceRange} with end moved on "delta". */ public SourceRange getMoveEnd(int delta) { return new SourceRange(offset, length + delta); } /** * Returns the 0-based index of the first character of the source code for this element, relative * to the source buffer in which this element is contained. * * @return the 0-based index of the first character of the source code for this element, relative * to the source buffer in which this element is contained */ public int getOffset() { return offset; } /** * @return the expanded translated of {@link SourceRange}, with moved start and the same length. */ public SourceRange getTranslated(int delta) { return new SourceRange(offset + delta, length); } /** * @return the minimal {@link SourceRange} that cover this and the given {@link SourceRange}s. */ public SourceRange getUnion(SourceRange other) { int newOffset = Math.min(offset, other.offset); int newEnd = Math.max(offset + length, other.offset + other.length); return new SourceRange(newOffset, newEnd - newOffset); } @Override public int hashCode() { return 31 * offset + length; } /** * @return {@code true} if this {@link SourceRange} intersects with given. */ public boolean intersects(SourceRange other) { if (other == null) { return false; } if (getEnd() <= other.getOffset()) { return false; } if (getOffset() >= other.getEnd()) { return false; } return true; } /** * @return {@code true} if this {@link SourceRange} starts in <code>otherRange</code>. */ public boolean startsIn(SourceRange otherRange) { return otherRange.contains(offset); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("[offset="); builder.append(offset); builder.append(", length="); builder.append(length); builder.append("]"); return builder.toString(); } }