/******************************************************************************* * Copyright (c) 2009-2013 CWI * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI * * Tijs van der Storm - Tijs.van.der.Storm@cwi.nl * * Paul Klint - Paul.Klint@cwi.nl - CWI * * Mark Hills - Mark.Hills@cwi.nl (CWI) * * Arnold Lankamp - Arnold.Lankamp@cwi.nl * * Davy Landman - Davy.Landman@cwi.nl - CWI *******************************************************************************/ package org.rascalmpl.interpreter.result; import static org.rascalmpl.interpreter.result.ResultFactory.bool; import static org.rascalmpl.interpreter.result.ResultFactory.makeResult; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.Map; import org.rascalmpl.ast.Name; import org.rascalmpl.interpreter.IEvaluatorContext; import org.rascalmpl.interpreter.asserts.ImplementationError; import org.rascalmpl.interpreter.staticErrors.SyntaxError; import org.rascalmpl.interpreter.staticErrors.UndeclaredField; import org.rascalmpl.interpreter.staticErrors.UnexpectedType; import org.rascalmpl.interpreter.staticErrors.UnsupportedOperation; import org.rascalmpl.interpreter.utils.Names; import org.rascalmpl.interpreter.utils.RuntimeExceptionFactory; import org.rascalmpl.uri.URIResolverRegistry; import org.rascalmpl.uri.URIUtil; import org.rascalmpl.value.IBool; import org.rascalmpl.value.IInteger; import org.rascalmpl.value.IList; import org.rascalmpl.value.IListWriter; import org.rascalmpl.value.IMap; import org.rascalmpl.value.IMapWriter; import org.rascalmpl.value.ISourceLocation; import org.rascalmpl.value.IString; import org.rascalmpl.value.ITuple; import org.rascalmpl.value.IValue; import org.rascalmpl.value.IValueFactory; import org.rascalmpl.value.type.Type; import org.rascalmpl.value.type.TypeFactory; import org.rascalmpl.value.type.TypeStore; public class SourceLocationResult extends ElementResult<ISourceLocation> { private static final Type intTuple = TypeFactory.getInstance().tupleType(TypeFactory.getInstance().integerType(), "line", TypeFactory.getInstance().integerType(), "column"); public SourceLocationResult(Type type, ISourceLocation loc, IEvaluatorContext ctx) { super(type, loc, ctx); } @Override public Result<IValue> call(Type[] argTypes, IValue[] actuals, Map<String, IValue> keyArgValues) { if (actuals.length >= 2) { if (!argTypes[0].isSubtypeOf(getTypeFactory().integerType())) { throw new UnexpectedType(getTypeFactory().integerType(), argTypes[0], ctx.getCurrentAST()); } if (!argTypes[1].isSubtypeOf(getTypeFactory().integerType())) { throw new UnexpectedType(getTypeFactory().integerType(), argTypes[1], ctx.getCurrentAST()); } if (actuals.length == 4) { if (!argTypes[2].isSubtypeOf(intTuple)) { throw new UnexpectedType(intTuple, argTypes[2], ctx.getCurrentAST()); } if (!argTypes[3].isSubtypeOf(intTuple)) { throw new UnexpectedType(intTuple, argTypes[3], ctx.getCurrentAST()); } } else if (actuals.length != 2) { throw new SyntaxError("location constructor", ctx.getCurrentAST().getLocation()); } } else { throw new SyntaxError("location constructor", ctx.getCurrentAST().getLocation()); } int iLength = Integer.parseInt(actuals[1].toString()); int iOffset = Integer.parseInt(actuals[0].toString()); if (iLength < 0) { throw RuntimeExceptionFactory.illegalArgument(actuals[1], ctx.getCurrentAST(), ctx.getStackTrace()); } if (iOffset < 0) { throw RuntimeExceptionFactory.illegalArgument(actuals[0], ctx.getCurrentAST(), ctx.getStackTrace()); } if (actuals.length == 4) { int iBeginLine = Integer.parseInt(((ITuple) actuals[2]).get(0).toString()); int iBeginColumn = Integer.parseInt(((ITuple) actuals[2]).get(1).toString()); int iEndLine = Integer.parseInt(((ITuple) actuals[3]).get(0).toString()); int iEndColumn = Integer.parseInt(((ITuple) actuals[3]).get(1).toString()); if (iBeginLine < 0) { throw RuntimeExceptionFactory.illegalArgument(((ITuple) actuals[2]).get(0), ctx.getCurrentAST(), ctx.getStackTrace()); } if (iBeginColumn < 0) { throw RuntimeExceptionFactory.illegalArgument(((ITuple) actuals[2]).get(1), ctx.getCurrentAST(), ctx.getStackTrace()); } if (iEndLine < 0) { throw RuntimeExceptionFactory.illegalArgument(((ITuple) actuals[3]).get(0), ctx.getCurrentAST(), ctx.getStackTrace()); } if (iEndColumn < 0) { throw RuntimeExceptionFactory.illegalArgument(((ITuple) actuals[3]).get(1), ctx.getCurrentAST(), ctx.getStackTrace()); } return makeResult(getTypeFactory().sourceLocationType(), getValueFactory().sourceLocation(getValue(), iOffset, iLength, iBeginLine, iEndLine, iBeginColumn, iEndColumn), ctx); } else { return makeResult(getTypeFactory().sourceLocationType(), getValueFactory().sourceLocation(getValue(), iOffset, iLength), ctx); } } @Override public Result<IBool> isDefined(Name name) { IValueFactory vf = getValueFactory(); TypeFactory tf = getTypeFactory(); URI uri = value.getURI(); String path = value.hasPath() ? value.getPath() : ""; ISourceLocation value = getValue(); String stringResult = null; Integer intResult = null; Integer tupleA = null; Integer tupleB = null; switch (Names.name(name)) { case "host": case "user": case "port": if (!URIResolverRegistry.getInstance().supportsHost(value)) { return makeResult(tf.boolType(), vf.bool(false), ctx); } case "path": case "scheme": case "authority": case "query": case "fragment": case "uri": case "top": case "params" : case "extension": return makeResult(tf.boolType(), vf.bool(true), ctx); case "length": case "offset": return makeResult(tf.boolType(), vf.bool(value.hasOffsetLength()), ctx); case "begin": case "end": return makeResult(tf.boolType(), vf.bool(value.hasLineColumn()), ctx); case "parent": return makeResult(tf.boolType(), vf.bool(!path.equals("") && !path.equals("/")), ctx); case "file": { int i = path.lastIndexOf((int)'/'); if (i != -1) { stringResult = path.substring(i+1); } else { stringResult = path; } return makeResult(tf.boolType(), vf.bool(!path.equals("")), ctx); } case "ls": return makeResult(tf.boolType(), vf.bool(URIResolverRegistry.getInstance().exists(value) && URIResolverRegistry.getInstance().isDirectory(value) ), ctx); default: return makeResult(tf.boolType(), vf.bool(false), ctx); } } @Override public <U extends IValue> Result<U> fieldAccess(String name, TypeStore store) { IValueFactory vf = getValueFactory(); TypeFactory tf = getTypeFactory(); ISourceLocation value = getValue(); String stringResult = null; Integer intResult = null; Integer tupleA = null; Integer tupleB = null; switch (name) { case "scheme": stringResult = value.getScheme(); break; case "authority": stringResult = value.hasAuthority() ? value.getAuthority() : ""; break; case "host": case "user": case "port": URI uri = value.getURI(); if (!URIResolverRegistry.getInstance().supportsHost(value)) { throw new UndeclaredField(name, "The scheme " + uri.getScheme() + " does not support the " + name + " field, use authority instead.", tf.sourceLocationType(), ctx.getCurrentAST()); } if (name.equals("host")) { stringResult = uri.getHost(); } else if (name.equals("user")) { stringResult = uri.getUserInfo(); } else { intResult = uri.getPort(); } if (stringResult == null && intResult == null) { stringResult = ""; } break; case "path": stringResult = value.hasPath() ? value.getPath() : "/"; break; case "query": stringResult = value.hasQuery() ? value.getQuery() : ""; break; case "fragment": stringResult = value.hasFragment() ? value.getFragment() : ""; break; case "length": if (value.hasOffsetLength()) { intResult = value.getLength(); break; } throw RuntimeExceptionFactory.unavailableInformation(ctx.getCurrentAST(), ctx.getStackTrace()); case "offset": if (value.hasOffsetLength()) { intResult = value.getOffset(); break; } throw RuntimeExceptionFactory.unavailableInformation(ctx.getCurrentAST(), ctx.getStackTrace()); case "begin": if (value.hasLineColumn()) { tupleA = value.getBeginLine(); tupleB = value.getBeginColumn(); break; } throw RuntimeExceptionFactory.unavailableInformation(ctx.getCurrentAST(), ctx.getStackTrace()); case "end": if (value.hasLineColumn()) { tupleA = value.getEndLine(); tupleB = value.getEndColumn(); break; } throw RuntimeExceptionFactory.unavailableInformation(ctx.getCurrentAST(), ctx.getStackTrace()); case "uri": stringResult = value.getURI().toString(); break; case "top": return makeResult(tf.sourceLocationType(), value.top(), ctx); // now the calculated fields case "parent": { String path = value.hasPath() ? value.getPath() : ""; if (path.equals("") || path.equals("/")) { throw RuntimeExceptionFactory.noParent(getValue(), ctx.getCurrentAST(), ctx.getStackTrace()); } // remove one or more /'s at the end if (path.endsWith("/")) { path = path.substring(0, path.length() -1); } int i = path.lastIndexOf((int)'/'); if (i != -1) { path = path.substring(0, i); if (value.getScheme().equalsIgnoreCase("file")) { // there is a special case for file references to windows paths. // the root path should end with a / (c:/ not c:) if (path.lastIndexOf((int)'/') == 0 && path.endsWith(":")) { path += "/"; } } return fieldUpdate("path", makeResult(tf.stringType(), vf.string(path), ctx), store); } throw RuntimeExceptionFactory.noParent(getValue(), ctx.getCurrentAST(), ctx.getStackTrace()); } case "file": { String path = value.hasPath() ? value.getPath() : ""; int i = path.lastIndexOf((int)'/'); if (i != -1) { stringResult = path.substring(i+1); } else { stringResult = path; } break; } case "ls": { try { if (!URIResolverRegistry.getInstance().exists(value)) { throw RuntimeExceptionFactory.io(vf.string("You can only access ls on an existing location."), ctx.getCurrentAST(), ctx.getStackTrace()); } if (!URIResolverRegistry.getInstance().isDirectory(value)) { throw RuntimeExceptionFactory.io(vf.string("You can only access ls on a directory, or a container."), ctx.getCurrentAST(), ctx.getStackTrace()); } IListWriter w = ctx.getValueFactory().listWriter(); for (ISourceLocation elem : URIResolverRegistry.getInstance().list(value)) { w.append(elem); } IList result = w.done(); // a list of loc's return makeResult(result.getType(), result, ctx); } catch (IOException e) { throw RuntimeExceptionFactory.io(vf.string(e.getMessage()), ctx.getCurrentAST(), ctx.getStackTrace()); } } case "extension" : { String path = value.hasPath() ? value.getPath() : ""; int i = path.lastIndexOf((int)'.'); if (i != -1) { stringResult = path.substring(i + 1); } else { stringResult = ""; } break; } case "params" : { String query = value.hasQuery() ? value.getQuery() : ""; IMapWriter res = vf.mapWriter(); if (query != null && query.length() > 0) { String[] params = query.split("&"); for (String param : params) { String[] keyValue = param.split("="); res.put(vf.string(keyValue[0]), vf.string(keyValue[1])); } } IMap map = res.done(); return makeResult(map.getType(), map, ctx); } default: throw new UndeclaredField(name, getTypeFactory().sourceLocationType(), ctx.getCurrentAST()); } if (stringResult != null) { return makeResult(tf.stringType(), vf.string(stringResult), ctx); } if (intResult != null) { return makeResult(tf.integerType(), vf.integer(intResult), ctx); } if (tupleA != null && tupleB != null) { return makeResult(intTuple, vf.tuple(vf.integer(tupleA), vf.integer(tupleB)), ctx); } throw new RuntimeException("A case not handled? " + name); } @Override public <U extends IValue, V extends IValue> Result<U> fieldUpdate(String name, Result<V> repl, TypeStore store) { ISourceLocation loc = getValue(); int iLength = loc.hasOffsetLength() ? loc.getLength() : -1; int iOffset = loc.hasOffsetLength() ? loc.getOffset() : -1; int iBeginLine = loc.hasLineColumn() ? loc.getBeginLine() : -1; int iBeginColumn = loc.hasLineColumn() ? loc.getBeginColumn() : -1; int iEndLine = loc.hasLineColumn() ? loc.getEndLine() : -1; int iEndColumn = loc.hasLineColumn() ? loc.getEndColumn() : -1; //URI uri = loc.getURI(); boolean uriPartChanged = false; String scheme = loc.getScheme(); String authority = loc.hasAuthority() ? loc.getAuthority() : null; String path = loc.hasPath() ? loc.getPath() : null; String query = loc.hasQuery() ? loc.getQuery() : null; String fragment = loc.hasFragment() ? loc.getFragment() : null; Type replType = repl.getType(); IValue replValue = repl.getValue(); try { String newStringValue = null; if (replType.isString()) { newStringValue = ((IString)replValue).getValue(); } if (name.equals("uri")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } URI uri = URIUtil.createFromEncoded(newStringValue); // now destruct it again scheme = uri.getScheme(); authority = uri.getAuthority(); path = uri.getPath(); query = uri.getQuery(); fragment = uri.getFragment(); uriPartChanged = true; } else if (name.equals("scheme")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } scheme = newStringValue; uriPartChanged = true; } else if (name.equals("authority")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } authority = newStringValue; uriPartChanged = true; } else if (name.equals("host")) { URI uri = value.getURI(); if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } if (!URIResolverRegistry.getInstance().supportsHost(value)) { throw new UndeclaredField(name, "The scheme " + uri.getScheme() + " does not support the host field, use authority instead.", getTypeFactory().sourceLocationType(), ctx.getCurrentAST()); } uri = URIUtil.changeHost(uri, newStringValue); authority = uri.getAuthority(); uriPartChanged = true; } else if (name.equals("path")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } path = newStringValue; uriPartChanged = true; } else if (name.equals("file")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } int i = path.lastIndexOf("/"); if (i != -1) { path = path.substring(0, i) + "/" + newStringValue; } else { path = path + "/" + newStringValue; } uriPartChanged = true; } else if (name.equals("parent")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } int i = path.lastIndexOf("/"); String parent = newStringValue; if (!parent.startsWith("/")) { parent = "/" + parent; } if (i != -1) { path =parent + path.substring(i); } else { path = parent; } uriPartChanged = true; } else if (name.equals("ls")) { throw new UnsupportedOperation("can not update the children of a location", ctx.getCurrentAST()); } else if (name.equals("extension")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } String ext = newStringValue; if (path.length() > 1) { int index = path.lastIndexOf('.'); if (index == -1 && !ext.isEmpty()) { path = path + (!ext.startsWith(".") ? "." : "") + ext; } else if (!ext.isEmpty()) { path = path.substring(0, index) + (!ext.startsWith(".") ? "." : "") + ext; } else { path = path.substring(0, index); } } uriPartChanged = true; } else if (name.equals("top")) { if (replType.isString()) { URI uri = URIUtil.assumeCorrect(newStringValue); scheme = uri.getScheme(); authority = uri.getAuthority(); path = uri.getPath(); query = uri.getQuery(); fragment = uri.getFragment(); } else if (replType.isSourceLocation()) { ISourceLocation rep = ((ISourceLocation) repl.getValue()); scheme = rep.getScheme(); authority = rep.hasAuthority() ? rep.getAuthority() : null; path = rep.hasPath() ? rep.getPath() : null; query = rep.hasQuery() ? rep.getQuery() : null; fragment = rep.hasFragment() ? rep.getFragment() : null; } else { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } uriPartChanged = true; } else if (name.equals("fragment")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } fragment = newStringValue; uriPartChanged = true; } else if (name.equals("query")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } query= newStringValue; uriPartChanged = true; } else if (name.equals("user")) { if (!replType.isString()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } URI uri = loc.getURI(); if (!URIResolverRegistry.getInstance().supportsHost(value)) { throw new UndeclaredField(name, "The scheme " + uri.getScheme() + " does not support the user field, use authority instead.", getTypeFactory().sourceLocationType(), ctx.getCurrentAST()); } if (uri.getHost() != null) { uri = URIUtil.changeUserInformation(uri, newStringValue); } authority = uri.getAuthority(); uriPartChanged = true; } else if (name.equals("port")) { if (!replType.isInteger()) { throw new UnexpectedType(getTypeFactory().stringType(), replType, ctx.getCurrentAST()); } URI uri = loc.getURI(); if (!URIResolverRegistry.getInstance().supportsHost(value)) { throw new UndeclaredField(name, "The scheme " + uri.getScheme() + " does not support the port field, use authority instead.", getTypeFactory().sourceLocationType(), ctx.getCurrentAST()); } if (uri.getHost() != null) { int port = Integer.parseInt(((IInteger) repl.getValue()).getStringRepresentation()); uri = URIUtil.changePort(uri, port); } authority = uri.getAuthority(); uriPartChanged = true; } else if (name.equals("length")){ if (!replType.isInteger()) { throw new UnexpectedType(getTypeFactory().integerType(), replType, ctx.getCurrentAST()); } iLength = ((IInteger) replValue).intValue(); if (iLength < 0) { throw RuntimeExceptionFactory.illegalArgument(replValue, ctx.getCurrentAST(), ctx.getStackTrace()); } } else if (name.equals("offset")){ if (!replType.isInteger()) { throw new UnexpectedType(getTypeFactory().integerType(), replType, ctx.getCurrentAST()); } iOffset = ((IInteger) replValue).intValue(); if (iOffset < 0) { RuntimeExceptionFactory.illegalArgument(replValue, ctx.getCurrentAST(), ctx.getStackTrace()); } } else if (name.equals("begin")) { if (!replType.isSubtypeOf(intTuple)) { throw new UnexpectedType(intTuple, replType, ctx.getCurrentAST()); } iBeginLine = ((IInteger) ((ITuple) replValue).get(0)).intValue(); iBeginColumn = ((IInteger) ((ITuple) replValue).get(1)).intValue(); if (iBeginColumn < 0 || iBeginLine < 0) { throw RuntimeExceptionFactory.illegalArgument(replValue, ctx.getCurrentAST(), ctx.getStackTrace()); } } else if (name.equals("end")) { if (!replType.isSubtypeOf(intTuple)) { throw new UnexpectedType(intTuple, replType, ctx.getCurrentAST()); } iEndLine = ((IInteger) ((ITuple) replValue).get(0)).intValue(); iEndColumn = ((IInteger) ((ITuple) replValue).get(1)).intValue(); if (iEndLine < 0 || iEndColumn < 0) { throw RuntimeExceptionFactory.illegalArgument(replValue, ctx.getCurrentAST(), ctx.getStackTrace()); } } else { // TODO: is this the right exception? How so "undeclared"? throw new UndeclaredField(name, getTypeFactory().sourceLocationType(), ctx.getCurrentAST()); } ISourceLocation newLoc = loc; if (uriPartChanged) { newLoc = getValueFactory().sourceLocation(scheme, authority, path, query, fragment); } if (loc.hasLineColumn()) { // was a complete loc, and thus will be now return makeResult(getType(), getValueFactory().sourceLocation(newLoc, iOffset, iLength, iBeginLine, iEndLine, iBeginColumn, iEndColumn), ctx); } if (loc.hasOffsetLength()) { // was a partial loc if (iBeginLine != -1 || iBeginColumn != -1) { //will be complete now. iEndLine = iBeginLine; iEndColumn = iBeginColumn; return makeResult(getType(), getValueFactory().sourceLocation(newLoc, iOffset, iLength, iBeginLine, iEndLine, iBeginColumn, iEndColumn), ctx); } else if (iEndLine != -1 || iEndColumn != -1) { // will be complete now. iBeginLine = iEndLine; iBeginColumn = iEndColumn; return makeResult(getType(), getValueFactory().sourceLocation(newLoc, iOffset, iLength, iBeginLine, iEndLine, iBeginColumn, iEndColumn), ctx); } else { // remains a partial loc return makeResult(getType(), getValueFactory().sourceLocation(newLoc, iOffset, iLength), ctx); } } // used to have no offset/length or line/column info, if we are here if (iBeginColumn != -1 || iEndColumn != -1 || iBeginLine != -1 || iBeginColumn != -1) { // trying to add line/column info to a uri that has no offset length throw RuntimeExceptionFactory.invalidUseOfLocation("Can not add line/column information without offset/length", ctx.getCurrentAST(), ctx.getStackTrace()); } // trying to set offset that was not there before, adding length automatically if (iOffset != -1 ) { if (iLength == -1) { iLength = 0; } } // trying to set length that was not there before, adding offset automatically if (iLength != -1) { if (iOffset == -1) { iOffset = 0; } } if (iOffset != -1 || iLength != -1) { // used not to no offset/length, but do now return makeResult(getType(), getValueFactory().sourceLocation(newLoc, iOffset, iLength), ctx); } // no updates to offset/length or line/column, and did not used to have any either: return makeResult(getType(), newLoc, ctx); } catch (IllegalArgumentException e) { throw RuntimeExceptionFactory.illegalArgument(getValue(), ctx.getCurrentAST(), ctx.getStackTrace(), "can not update field " + name + ": " + e.getMessage()); } catch (URISyntaxException e) { throw RuntimeExceptionFactory.parseError(ctx.getCurrentAST().getLocation(), ctx.getCurrentAST(), ctx.getStackTrace()); } } @Override public <V extends IValue> Result<IBool> equals(Result<V> that) { return that.equalToSourceLocation(this); } @Override public <V extends IValue> Result<IBool> nonEquals(Result<V> that) { return that.nonEqualToSourceLocation(this); } @Override public <V extends IValue> Result<IBool> lessThan(Result<V> that) { return that.lessThanSourceLocation(this); } @Override public <V extends IValue> LessThanOrEqualResult lessThanOrEqual(Result<V> that) { return that.lessThanOrEqualSourceLocation(this); } @Override protected Result<IBool> lessThanSourceLocation(SourceLocationResult that) { LessThanOrEqualResult loe = lessThanOrEqualSourceLocation(that); return bool(loe.isLess().getValue().getValue() && !loe.isEqual().isTrue(), ctx); } @Override protected Result<IBool> greaterThanSourceLocation(SourceLocationResult that) { return that.lessThanSourceLocation(this); } @Override protected Result<IBool> greaterThanOrEqualSourceLocation(SourceLocationResult that) { return that.lessThanSourceLocation(this); } @Override protected LessThanOrEqualResult lessThanOrEqualSourceLocation(SourceLocationResult that) { ISourceLocation left = that.getValue(); ISourceLocation right = this.getValue(); int compare = left.top().toString().compareTo(right.top().toString()); if (compare < 0) { return new LessThanOrEqualResult(true, false, ctx); } else if (compare > 0) { return new LessThanOrEqualResult(false, false, ctx); } // but the uri's are the same // note that line/column information is superfluous and does not matter for ordering if (left.hasOffsetLength()) { if (!right.hasOffsetLength()) { return new LessThanOrEqualResult(false, false, ctx); } int roffset = right.getOffset(); int rlen = right.getLength(); int loffset = left.getOffset(); int llen = left.getLength(); if (loffset == roffset) { return new LessThanOrEqualResult(llen < rlen, llen == rlen, ctx); } return new LessThanOrEqualResult(roffset < loffset && roffset + rlen >= loffset + llen, false, ctx); } else if (compare == 0) { return new LessThanOrEqualResult(false, true, ctx); } if (!right.hasOffsetLength()) { throw new ImplementationError("assertion failed"); } return new LessThanOrEqualResult(false, false, ctx); } ///// @Override protected Result<IBool> equalToSourceLocation(SourceLocationResult that) { return that.equalityBoolean(this); } @Override protected Result<IBool> nonEqualToSourceLocation(SourceLocationResult that) { return that.nonEqualityBoolean(this); } protected int compareSourceLocationInt(SourceLocationResult that) { // Note args have already been reversed. ISourceLocation left = this.getValue(); ISourceLocation right = that.getValue(); if (left.isEqual(right)) { return 0; } // they are not the same int compare = left.top().toString().compareTo(right.top().toString()); if (compare != 0) { return compare; } // but the uri's are the same // note that line/column information is superfluous and does not matter for ordering if (left.hasOffsetLength()) { if (!right.hasOffsetLength()) { return 1; } int roffset = right.getOffset(); int rlen = right.getLength(); int loffset = left.getOffset(); int llen = left.getLength(); if(loffset == roffset){ return (llen < rlen) ? -1 : ((llen == rlen) ? 0 : 1); } if(roffset < loffset && roffset + rlen >= loffset + llen) return -1; else return 1; } if (!right.hasOffsetLength()) { throw new ImplementationError("assertion failed"); } return -1; } @Override public <U extends IValue, V extends IValue> Result<U> add(Result<V> that) { return that.addSourceLocation(this); } @Override protected <U extends IValue> Result<U> addListRelation(ListRelationResult that) { return that.addSourceLocation(this); } @Override protected <U extends IValue> Result<U> addRelation(RelationResult that) { return that.addSourceLocation(this); } }