Skip to content

Commit

Permalink
Added source coordinates
Browse files Browse the repository at this point in the history
Source coordinates encode location in source files and information about these locations.

They are used by parsers, debuggers, and other tools.

Signed-off-by: Stefan Marr <[email protected]>
  • Loading branch information
smarr committed Apr 27, 2019
1 parent 65b45ba commit 1c6adb6
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/bd/source/FullSourceCoordinate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package bd.source;

import java.net.URI;
import java.util.Objects;


/**
* Is a {@link SourceCoordinate} with an extra URI to identify it globally.
* Otherwise, behaves the same.
*/
public class FullSourceCoordinate extends SourceCoordinate {
public final URI uri;

protected FullSourceCoordinate(final URI uri, final int startLine,
final int startColumn, final int charIndex, final int length) {
super(startLine, startColumn, charIndex, length);
this.uri = uri;
}

protected FullSourceCoordinate() {
this(null, 0, 0, 0, 0);
}

@Override
public int hashCode() {
// ignore charIndex, not always set
return Objects.hash(uri, startLine, startColumn, /* charIndex, */ charLength);
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof FullSourceCoordinate)) {
return false;
}

FullSourceCoordinate sc = (FullSourceCoordinate) o;
// ignore charIndex, not always set
return sc.uri.equals(uri) &&
sc.startLine == startLine && sc.startColumn == startColumn &&
// sc.charIndex == charIndex &&
sc.charLength == charLength;
}

@Override
public String toString() {
return "SrcCoord(line: " + startLine + ", col: " + startColumn + ", charlength:"
+ charLength + ", uri: " + uri.getPath() + ")";
}
}
113 changes: 113 additions & 0 deletions src/bd/source/SourceCoordinate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package bd.source;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Set;

import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;


/**
* Represents a potentially empty range of source characters, for a potentially
* not yet loaded source.
*
* <p>
* The {@code charIndex} may not be set. It can be derived from startLine and startColumn,
* if the source file is present.
*/
public class SourceCoordinate {
public final int startLine;
public final int startColumn;
public final transient int charIndex;
public final int charLength;

protected SourceCoordinate(final int startLine, final int startColumn,
final int charIndex, final int length) {
this.startLine = startLine;
this.startColumn = startColumn;
this.charIndex = charIndex;
this.charLength = length;
assert startLine >= 0;
assert startColumn >= 0;
assert charIndex >= 0 || charIndex == -1;
}

@Override
public String toString() {
return "SrcCoord(line: " + startLine + ", col: " + startColumn + ", charlength:"
+ charLength + ")";
}

public static SourceCoordinate createEmpty() {
return new SourceCoordinate(0, 0, 0, 0);
}

public static SourceCoordinate create(final int startLine, final int startColumn,
final int charIndex) {
return new SourceCoordinate(startLine, startColumn, charIndex, 0);
}

public static SourceCoordinate create(final int startLine, final int startColumn,
final int charIndex, final int length) {
return new SourceCoordinate(startLine, startColumn, charIndex, length);
}

public static SourceCoordinate create(final SourceSection section) {
return new SourceCoordinate(section.getStartLine(), section.getStartColumn(),
section.getCharIndex(), section.getCharLength());
}

public static FullSourceCoordinate createFull(final SourceSection section) {
return new FullSourceCoordinate(section.getSource().getURI(),
section.getStartLine(), section.getStartColumn(),
section.getCharIndex(), section.getCharLength());
}

public static FullSourceCoordinate create(final URI sourceUri, final int startLine,
final int startColumn, final int charLength) {
return new FullSourceCoordinate(sourceUri, startLine, startColumn, -1, charLength);
}

public static FullSourceCoordinate create(final String sourceUri, final int startLine,
final int startColumn, final int charLength) {
try {
return create(new URI(sourceUri), startLine, startColumn, charLength);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}

public static FullSourceCoordinate create(final String sourceUri, final int startLine,
final int startColumn, final int charIndex, final int charLength) {
try {
return new FullSourceCoordinate(
new URI(sourceUri), startLine, startColumn, charIndex, charLength);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}

public static TaggedSourceCoordinate create(final SourceSection section,
final Set<Class<? extends Tag>> tags) {
String[] strTags = new String[tags.size()];

int i = 0;
for (Class<? extends Tag> tagClass : tags) {
strTags[i] = tagClass.getSimpleName();
i += 1;
}

return new TaggedSourceCoordinate(section.getStartLine(), section.getStartColumn(),
section.getCharIndex(), section.getCharLength(), strTags);
}

public static String getLocationQualifier(final SourceSection section) {
return ":" + section.getStartLine() + ":" + section.getStartColumn();
}

public static String getURI(final Source source) {
return source.getURI().toString();
}
}
15 changes: 15 additions & 0 deletions src/bd/source/TaggedSourceCoordinate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package bd.source;

/**
* Is a {@link SourceCoordinate} with additional tags to characterize the source range.
* Otherwise, behaves the same.
*/
public class TaggedSourceCoordinate extends SourceCoordinate {
public final String[] tags;

protected TaggedSourceCoordinate(final int startLine, final int startColumn,
final int charIndex, final int length, final String[] tags) {
super(startLine, startColumn, charIndex, length);
this.tags = tags;
}
}
37 changes: 37 additions & 0 deletions tests/source/SourceCoordinateTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package source;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import bd.source.SourceCoordinate;


public class SourceCoordinateTests {

@Test
public void testBasicEqualsHash() {
SourceCoordinate a = SourceCoordinate.create("file:///", 1, 2, 2, 4);
SourceCoordinate b = SourceCoordinate.create("file:///", 1, 2, 2, 4);

assertNotSame(a, b);
assertEquals(a.hashCode(), b.hashCode());

assertTrue(a.equals(b));
}

@Test
public void testEqualsHashWithUnsetCharIndex() {
SourceCoordinate a = SourceCoordinate.create("file:///", 1, 2, 2, 4);

// underlying source might not be loaded, should still match
SourceCoordinate b = SourceCoordinate.create("file:///", 1, 2, 4);

assertNotSame(a, b);
assertEquals(a.hashCode(), b.hashCode());

assertTrue(a.equals(b));
}
}

0 comments on commit 1c6adb6

Please sign in to comment.