Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .classpath
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
78 changes: 42 additions & 36 deletions src/edu/isnap/node/ASTNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -54,6 +53,11 @@ public class ASTNode implements INode {
* behavior.
*/
public String id;

/**
* Used to generate high-level hints
*/
public String annotation;

public SourceLocation startSourceLocation;
public SourceLocation endSourceLocation;
Expand All @@ -67,7 +71,7 @@ public class ASTNode implements INode {

public static class SourceLocation implements Comparable<SourceLocation>{
// TODO: Update this class to parse your new start and end locations
public final int line, col;
public int line, col;

@SuppressWarnings("unused")
private SourceLocation() {
Expand All @@ -81,30 +85,30 @@ public SourceLocation(int line, int col) {

public static SourceLocation getEarlier(SourceLocation a, SourceLocation b) {
if (a == null) return b;
return a.compareTo(b) == 1 ? b : a;
if (b == null) return a;

if (a.line < b.line) return a;
if (b.line < a.line) return b;

if (b.col < a.col) return b;
if (a.col < b.col) return a;
return null;
//TODO: need to investigate returning null if they are the same location. This could break callers.
}

public String markSource(String source, String with) {
String[] lines = source.split("\n");
int line = this.line;
int col = this.col;
// If there's an insertion at a newline at the end of the file, just add the newline
if (line == lines.length + 1 && col == 0) {
lines = Arrays.copyOf(lines, lines.length + 1);
lines[lines.length - 1] = "";
}
// If the line isn't present, cap it (note, line is 1-indexed, so it can be = to length)
if (line > lines.length) line = lines.length;
String sourceLine = lines[line - 1];
// Col is 0-indexed but we can insert at the end of the line, so it's capped at length
if (col > sourceLine.length()) col = sourceLine.length();
sourceLine = sourceLine.substring(0, col) + with + sourceLine.substring(col);
String sourceLine = lines[line - 1] + " ";
int insertPlace = col - 1;
if (with.equals("</span>")) insertPlace += 1;
sourceLine = sourceLine.substring(0, insertPlace) + with + sourceLine.substring(insertPlace);
lines[line - 1] = sourceLine;
if (line != this.line || col != this.col) {
System.err.printf("Truncating source location %s for source:\n%s\n", this, source);
}
return String.join("\n", lines);
}

public void updateCol(int pos) {
this.col += pos;
}

@Override
public String toString() {
Expand All @@ -113,10 +117,12 @@ public String toString() {

@Override
public final int compareTo(SourceLocation other) {
if (other == null) return 1;
int lineComp = Integer.compare(line, other.line);
if (lineComp != 0) return lineComp;
return Integer.compare(col, other.col);
SourceLocation earlier = getEarlier(this, other);
if (earlier == null) return 0;
else if (earlier == this) {
return 1; //the other location comes after this
}
return -1; //the other location comes before this, or they are at the same location
}

public SourceLocation copy() {
Expand Down Expand Up @@ -150,10 +156,15 @@ public List<ASTNode> children() {
}

public ASTNode(String type, String value, String id) {
this(type, value, id, null);
}

public ASTNode(String type, String value, String id, String annotation) {
if (type == null) throw new IllegalArgumentException("'type' cannot be null");
this.type = type;
this.value = value;
this.id = id;
this.annotation = annotation;
}

public boolean addChild(ASTNode child) {
Expand Down Expand Up @@ -225,14 +236,12 @@ public static ASTNode parse(String jsonSource) throws JSONException {
}

public static ASTNode parse(JSONObject object) {
if (!object.has("type")) {
System.err.println("Node missing type: " + object.toString());
}
String type = object.getString("type");
String value = object.has("value") ? object.getString("value") : null;
String id = object.has("id") ? object.getString("id") : null;
String annotation = object.has("annotation") ? object.getString("annotation") : null;

ASTNode node = new ASTNode(type, value, id);
ASTNode node = new ASTNode(type, value, id, annotation);

if (object.has("sourceStart")) {
try {
Expand All @@ -249,6 +258,7 @@ public static ASTNode parse(JSONObject object) {
}

JSONObject children = object.optJSONObject("children");
JSONArray childrenArray = object.optJSONArray("children");
if (children != null) {
JSONArray childrenOrder = object.optJSONArray("childrenOrder");

Expand All @@ -272,14 +282,10 @@ public static ASTNode parse(JSONObject object) {
ASTNode child = parse(children.getJSONObject(relation));
node.addChild(relation, child);
}
} else {
JSONArray childrenArray = object.optJSONArray("children");
if (childrenArray != null) {
for (int i = 0; i < childrenArray.length(); i++) {
JSONObject jsonObject = (JSONObject) childrenArray.get(i);
ASTNode child = parse(jsonObject);
node.addChild(String.valueOf(i), child);
}
} else if (childrenArray != null) {
for (int i = 0; i < childrenArray.length(); i++) {
ASTNode child = parse(childrenArray.getJSONObject(i));
node.addChild(i, child);
}
}

Expand Down Expand Up @@ -459,7 +465,7 @@ public ASTSnapshot toSnapshot() {
}

public ASTSnapshot toSnapshot(boolean isCorrect, String source) {
ASTSnapshot snapshot = new ASTSnapshot(type, value, id, isCorrect, source);
ASTSnapshot snapshot = new ASTSnapshot(type, value, id, annotation, isCorrect, source);
for (int i = 0; i < children.size(); i++) {
snapshot.addChild(childRelations.get(i), children.get(i));
}
Expand Down
23 changes: 22 additions & 1 deletion src/edu/isnap/node/ASTSnapshot.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ public class ASTSnapshot extends ASTNode {
* The source code that this snapshot was derived from, if available.
*/
public final String source;


public ASTSnapshot(String type, String value, String id, boolean isCorrect, String sourceCode) {
super(type, value, id);
this(type, value, id, null, isCorrect, sourceCode);
}

public ASTSnapshot(String type, String value, String id, String annotation, boolean isCorrect, String sourceCode) {
super(type, value, id, annotation);
this.isCorrect = isCorrect;
this.source = sourceCode;
}
Expand All @@ -36,6 +41,22 @@ public static ASTSnapshot parse(JSONObject json, String sourceOverride) {
ASTNode node = ASTNode.parse(json);
return node.toSnapshot(isCorrect, source);
}

/**
* New overloaded method that sets node.id
* @param json
* @param id
* @param sourceOverride
* @return
*/
public static ASTSnapshot parse(JSONObject json, String id, String sourceOverride) {
boolean isCorrect = json.optBoolean("isCorrect") || json.optBoolean("correct");
String source = sourceOverride;
ASTNode node = ASTNode.parse(json);
node.id = id;
return node.toSnapshot(isCorrect, source);
}


@Override
public JSONObject toJSON() {
Expand Down
24 changes: 14 additions & 10 deletions src/edu/isnap/util/map/BiMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,49 +19,49 @@ public BiMap(MapFactory factory) {
}

public U put(T from, U to) {
U removedFrom = fromMap.put(from, to);
U removedFrom = getFromMap().put(from, to);
T removedTo = toMap.put(to, from);
if (removedFrom != null && !equal(removedFrom, to)) toMap.remove(removedFrom);
if (removedTo != null && !equal(removedTo, from)) fromMap.remove(removedTo);
if (removedTo != null && !equal(removedTo, from)) getFromMap().remove(removedTo);
return removedFrom;
}

private boolean equal(Object a, Object b) {
if (fromMap instanceof IdentityHashMap) {
if (getFromMap() instanceof IdentityHashMap) {
return a == b;
}
if (a == null) return b == null;
return a.equals(b);
}

public U getFrom(T item) {
return fromMap.get(item);
return getFromMap().get(item);
}

public T getTo(U item) {
return toMap.get(item);
}

public boolean containsFrom(T item) {
return fromMap.containsKey(item);
return getFromMap().containsKey(item);
}

public boolean containsTo(U item) {
return toMap.containsKey(item);
}

public void removeFrom(T item) {
U pair = fromMap.remove(item);
U pair = getFromMap().remove(item);
if (pair != null) toMap.remove(pair);
}

public void removeTo(U item) {
T pair = toMap.remove(item);
if (pair != null) fromMap.remove(pair);
if (pair != null) getFromMap().remove(pair);
}

public Set<T> keysetFrom() {
return fromMap.keySet();
return getFromMap().keySet();
}

public Set<U> keysetTo() {
Expand All @@ -70,11 +70,15 @@ public Set<U> keysetTo() {

@Override
public String toString() {
return fromMap.toString();
return getFromMap().toString();
}

public void clear() {
fromMap.clear();
getFromMap().clear();
toMap.clear();
}

public Map<T, U> getFromMap() {
return fromMap;
}
}