/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * SourceRange.java * Creation date: (Feb 13, 2006) * By: James Wright */ package org.openquark.cal.compiler; /** * Identifies a continuous range of positions in a CAL source stream. * This is an immutable value class. * * @author Jawright */ public final class SourceRange { private final SourcePosition startSourcePosition; private final SourcePosition endSourcePosition; SourceRange(SourcePosition startPosition, SourcePosition endPosition) { if(startPosition == null || endPosition == null) { throw new NullPointerException(); } if(!equalsObject(startPosition.getSourceName(), endPosition.getSourceName())) { throw new IllegalArgumentException(); } if(SourcePosition.compareByPosition.compare(startPosition, endPosition) > 0) { throw new IllegalArgumentException(); } startSourcePosition = startPosition; endSourcePosition = endPosition; } SourceRange(SourcePosition startPosition, String rangeText) { if(startPosition == null || rangeText == null) { throw new NullPointerException(); } startSourcePosition = startPosition; endSourcePosition = startPosition.offsetPositionByText(rangeText); } // SourceRange that is just associated with a file. SourceRange(String sourceName) { startSourcePosition = new SourcePosition(-1, -1, sourceName); endSourcePosition = new SourcePosition(-1, -1, sourceName); } /** * Constructor for a SourceRange associated with a module but having no source positions. * @param moduleName the name of the module with which the SourceRange is associated */ SourceRange(ModuleName moduleName) { this(moduleName.toSourceText()); } /** * @return true only if both arguments are null, or both are not null, and obj.equals(obj2) is true. */ private static boolean equalsObject(final Object obj1, final Object obj2) { if (obj1 == null) { return obj2 == null; } if (obj2 == null) { return false; } return obj1.equals(obj2); } /** @return SourcePosition of the start of the range (inclusive) */ public SourcePosition getStartSourcePosition() { return startSourcePosition; } /** @return SourcePosition of the end of the range (exclusive) */ public SourcePosition getEndSourcePosition() { return endSourcePosition; } /** @return Line number in the stream where the range begins (inclusive) */ public int getStartLine() { return startSourcePosition.getLine(); } /** @return Column number in the stream where the range begins (inclusive) */ public int getStartColumn() { return startSourcePosition.getColumn(); } /** @return Line number in the stream where the range ends (exclusive) */ public int getEndLine() { return endSourcePosition.getLine(); } /** @return Column number in the stream where the range ends (exclusive) */ public int getEndColumn() { return endSourcePosition.getColumn(); } /** @return Optional name of the source stream (this can be null) */ public String getSourceName() { return startSourcePosition.getSourceName(); } @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("source: "); stringBuilder.append(startSourcePosition.getSourceName()); stringBuilder.append(" (line "); stringBuilder.append(startSourcePosition.getLine()); stringBuilder.append(" column "); stringBuilder.append(startSourcePosition.getColumn()); stringBuilder.append(") to (line "); stringBuilder.append(endSourcePosition.getLine()); stringBuilder.append(" column "); stringBuilder.append(endSourcePosition.getColumn()); stringBuilder.append(")"); return stringBuilder.toString(); } /** * Returns whether this source range contains the given source position. * @param pos the source position to check. * @return true if this source range contains the given source position; false otherwise. */ public boolean containsPosition(SourcePosition pos) { return SourcePosition.compareByPosition.compare(pos, startSourcePosition) >= 0 && SourcePosition.compareByPosition.compare(pos, endSourcePosition) < 0; } /** * Returns whether this source range contains the given source position. Includes both the start * and the end column. * @param pos the source position to check. * @return true if this source range contains the given source position; false otherwise. */ public boolean containsPositionInclusive(SourcePosition pos) { return SourcePosition.compareByPosition.compare(pos, startSourcePosition) >= 0 && SourcePosition.compareByPosition.compare(pos, endSourcePosition) <= 0; } /** * return true if the sourcerange is contained entirely within this source * range. * * @param sourceRange * @return true if the sourceRange is contained */ public boolean contains(SourceRange sourceRange) { return containsPositionInclusive(sourceRange.getStartSourcePosition()) && containsPositionInclusive(sourceRange.getEndSourcePosition()); } /** * Returns true if this SourceRange overlaps with the given SourceRange. * * @param sourceRange * the source range to check for overlap */ public boolean overlaps(SourceRange sourceRange){ if (containsPositionInclusive(sourceRange.getStartSourcePosition())){ return true; } if (containsPositionInclusive(sourceRange.getEndSourcePosition())){ return true; } if (sourceRange.containsPositionInclusive(getStartSourcePosition())){ return true; } if (sourceRange.containsPositionInclusive(getEndSourcePosition())){ return true; } return false; } /** * @param sourceText sourceText that the source range refers to * @return the text in the sourceText string covered by this source range. */ public String getSelection(String sourceText){ final int startIndex = getStartSourcePosition().getPosition(sourceText); final int endIndex = getEndSourcePosition().getPosition(sourceText); return sourceText.substring(startIndex, endIndex); } }