Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

BWLocation have complete spans if possible (patch from Martijn Schrage)

  • Loading branch information...
commit 1e889e5b53a51520947639e4d1a781f63374eed2 1 parent 72c5081
@JPMoresmau authored
View
4 net.sf.eclipsefp.haskell.buildwrapper/plugin.properties
@@ -1,3 +1,3 @@
-# bundle manifest
-bundleVendor = The EclipseFP Project
+# bundle manifest
+bundleVendor = The EclipseFP Project
bundleName = Haskell BuildWrapper Utilities
View
10 ...sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/BWFacade.java
@@ -689,7 +689,13 @@ private boolean parseNotes(JSONArray notes,Set<IResource> ress){
String f=ol.getString("f");
int line=ol.getInt("l");
int col=ol.getInt("c");
- Location loc=new Location(f, line, col, line, col);
+ int endline=ol.getInt("el");
+ int endcol=ol.getInt("ec");
+ //ow.addMessage("\nParsed location: src="+f+" "+line+":"+col+" to "+endline+":"+endcol+" msg:"+o.getString("t"));
+
+ Location loc=new Location(project, f, line, col, endline, endcol);
+ //ow.addMessage("\nCreated location: "+loc.getStartLine()+":"+loc.getStartColumn()+" to "+loc.getEndLine()+":"+loc.getEndColumn());
+
Note n=new Note(k,loc,o.getString("t"),"");
IResource res=project.findMember(f);
// linker errors may have full path
@@ -720,7 +726,7 @@ private boolean parseNotes(JSONArray notes,Set<IResource> ress){
}
return buildOK;
}
-
+
private Component parseComponent(JSONObject obj){
boolean buildable=false;
try {
View
494 ...ipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/types/Location.java
@@ -1,206 +1,288 @@
-package net.sf.eclipsefp.haskell.buildwrapper.types;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.ui.texteditor.MarkerUtilities;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * A span of text within a file, in line:column format.
- * Lines and columns are zero-based.
- * The start is inclusive; the end is exclusive.
- *
- * @author Thomas ten Cate
- */
-public class Location {
- private String fileName;
- private String otherName;
-
- private int startLine, startColumn, endLine, endColumn;
-
- public Location(JSONObject json) throws JSONException {
- this(null,json);
- }
-
- public Location(IFile f, JSONArray json) throws JSONException {
- this(f!=null?f.getLocation().toOSString():"",json);
- }
-
- public Location(String fn, JSONArray json) throws JSONException {
- startLine=json.getInt(0);
- startColumn=json.getInt(1)-1; // we're zero based, Haskell code 1 based
- if (json.length()>3){
- endLine=json.getInt(2);
- endColumn=json.getInt(3)-1;// we're zero based, Haskell code 1 based
- } else if (json.length()>2){
- endLine=startLine;
- endColumn=json.getInt(2)-1;// we're zero based, Haskell code 1 based
- } else {
- endLine=startLine;
- endColumn=startColumn+1;
- }
- if (endColumn==-1 && endLine>startLine){
- endLine--;
- }
- this.fileName = fn;
- }
-
- public Location(IFile f, JSONObject json) throws JSONException {
- this.fileName = json.optString("file");
- this.otherName = json.optString("other");
-
- if ( f != null
- && (this.fileName == null || this.fileName.length() == 0)
- && (this.otherName == null || this.otherName.length() == 0) ) {
- // Default the file name to the Java file resource
- this.fileName = f.getLocation().toOSString();
- }
-
- if (json.optString("no-location").length() == 0) {
- JSONArray region = json.getJSONArray("region");
- startLine = region.getInt(0);
- startColumn = region.getInt(1);
- if (startColumn<0){
- startColumn=0;
- }
- endLine = region.getInt(2);
- endColumn = region.getInt(3);
- }
- }
-
- public Location(String fileName, int startLine, int startColumn, int endLine, int endColumn) {
- this.fileName = fileName;
- this.startLine = startLine;
- this.startColumn = startColumn;
- int mv=0;
- if (startColumn<0){
- mv=0-startColumn;
- this.startColumn=0;
- }
- this.endLine = endLine;
- this.endColumn = endColumn+mv;
- }
-
-
- public Location(String fileName, IDocument document, IRegion region) throws BadLocationException {
- this.fileName = fileName;
- int startOffset = region.getOffset();
- int endOffset = startOffset + region.getLength();
- int docLine=document.getLineOfOffset(startOffset);
- this.startLine =docLine+1 ;
- this.startColumn = startOffset - document.getLineOffset(docLine);
- docLine=document.getLineOfOffset(endOffset);
- this.endLine = docLine+1;
- this.endColumn = endOffset - document.getLineOffset(docLine);
- }
-
-
-
-
- /**
- * Returns the offset within the given document
- * that the start of this {@link Location} object represents.
- */
- public int getStartOffset(IDocument document) throws BadLocationException {
- return document.getLineOffset(startLine-1) + startColumn;
- }
-
- /**
- * Returns the offset within the given document
- * that the end of this {@link Location} object represents.
- */
- public int getEndOffset(IDocument document) throws BadLocationException {
- return document.getLineOffset(endLine-1) + endColumn;
- }
-
- public int getLength(IDocument document) throws BadLocationException {
- return getEndOffset(document) - getStartOffset(document);
- }
-
- public String getContents(IDocument document) throws BadLocationException {
- int st=getStartOffset(document);
- return document.get(st,getEndOffset(document)-st);
- }
-
- public String getFileName() {
- return fileName;
- }
-
- public String getOtherName() {
- return otherName;
- }
-
- public int getStartLine() {
- return startLine;
- }
-
- public int getStartColumn() {
- return startColumn;
- }
-
- public int getEndLine() {
- return endLine;
- }
-
- public int getEndColumn() {
- return endColumn;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Location)) {
- return false;
- }
- Location other = (Location)obj;
- return
- fileName.equals(other.fileName) &&
- startLine == other.startLine && startColumn == other.startColumn &&
- endLine == other.endLine && endColumn == other.endColumn;
- }
-
- @Override
- public int hashCode() {
- return fileName.hashCode()<<16+startLine<<8+startColumn;
- }
-
- @Override
- public String toString() {
- return String.format("%d:%d-%d:%d", startLine, startColumn, endLine, endColumn);
- }
-
-
- public IFile getIFile(IProject p){
- String pl=p.getLocation().toOSString();
- String loc=getFileName();
- if (loc!=null && loc.startsWith(pl)){
- return (IFile)p.getFile(loc.substring(pl.length()));
- }
- return null;
- }
-
- public Map<Object,Object> getMarkerProperties(int maxLines){
- int line= Math.min(getStartLine(),maxLines);
- final Map<Object,Object> attributes=new HashMap<Object,Object>();
- MarkerUtilities.setLineNumber(attributes, line);
- int start=getStartColumn();
- int end=getEndColumn();
- // if we have startColumn==endColumn we could take end+1
- // BUT if end goes over the document size, or start is zero, or if Eclipse feels like it, the marker is not shown on the document
- // so it's better to just show the line without more info
- if (end>start){
- MarkerUtilities.setCharStart(attributes, start);
- // exclusive
- MarkerUtilities.setCharEnd(attributes, end-1);
- }
- return attributes;
- }
-
-}
+package net.sf.eclipsefp.haskell.buildwrapper.types;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sf.eclipsefp.haskell.buildwrapper.BWFacade;
+import net.sf.eclipsefp.haskell.buildwrapper.BuildWrapperPlugin;
+import net.sf.eclipsefp.haskell.buildwrapper.util.BWText;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.ui.texteditor.MarkerUtilities;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * A span of text within a file, in line:column format.
+ * Lines are one-based, columns are zero-based.
+ * The start is inclusive; the end is exclusive.
+ *
+ * @author Thomas ten Cate
+ */
+public class Location {
+ private String fileName;
+ private String otherName;
+
+ private int startLine, startColumn, endLine, endColumn;
+
+ public Location(JSONObject json) throws JSONException {
+ this(null,json);
+ }
+
+ public Location(IFile f, JSONArray json) throws JSONException {
+ this(f!=null?f.getLocation().toOSString():"",json);
+ }
+
+ public Location(String fn, JSONArray json) throws JSONException {
+ startLine=json.getInt(0);
+ startColumn=json.getInt(1)-1; // we're zero based, Haskell code 1 based
+ if (json.length()>3){
+ endLine=json.getInt(2);
+ endColumn=json.getInt(3)-1;// we're zero based, Haskell code 1 based
+ } else if (json.length()>2){
+ endLine=startLine;
+ endColumn=json.getInt(2)-1;// we're zero based, Haskell code 1 based
+ } else {
+ endLine=startLine;
+ endColumn=startColumn+1;
+ }
+ if (endColumn==-1 && endLine>startLine){
+ endLine--;
+ }
+ this.fileName = fn;
+ }
+
+ public Location(IFile f, JSONObject json) throws JSONException {
+ this.fileName = json.optString("file");
+ this.otherName = json.optString("other");
+
+ if ( f != null
+ && (this.fileName == null || this.fileName.length() == 0)
+ && (this.otherName == null || this.otherName.length() == 0) ) {
+ // Default the file name to the Java file resource
+ this.fileName = f.getLocation().toOSString();
+ }
+
+ if (json.optString("no-location").length() == 0) {
+ JSONArray region = json.getJSONArray("region");
+ startLine = region.getInt(0);
+ startColumn = region.getInt(1);
+ if (startColumn<0){
+ startColumn=0;
+ }
+ endLine = region.getInt(2);
+ endColumn = region.getInt(3);
+ }
+ }
+
+ public Location(String fileName, int startLine, int startColumn, int endLine, int endColumn) {
+ this.fileName = fileName;
+ this.startLine = startLine;
+ this.startColumn = startColumn;
+ int mv=0;
+ if (startColumn<0){
+ mv=0-startColumn;
+ this.startColumn=0;
+ }
+ this.endLine = endLine;
+ this.endColumn = endColumn+mv;
+ }
+
+ public Location(String fileName, IDocument document, IRegion region) throws BadLocationException {
+ this.fileName = fileName;
+ int startOffset = region.getOffset();
+ int endOffset = startOffset + region.getLength();
+ int docLine=document.getLineOfOffset(startOffset);
+ this.startLine =docLine+1 ;
+ this.startColumn = startOffset - document.getLineOffset(docLine);
+ docLine=document.getLineOfOffset(endOffset);
+ this.endLine = docLine+1;
+ this.endColumn = endOffset - document.getLineOffset(docLine);
+ }
+
+
+ /**
+ * Create a location from a buildwrapper location, expanding empty spans when possible.
+ */
+ public Location(IProject project, String fileName, int startLin, int startCol, int endLin, int endCol) {
+ this.fileName = fileName;
+ startLine = startLin;
+ startColumn = startCol - 1; // Buildwrapper columns start at 1
+ endLine = endLin;
+ endColumn = endCol - 1; // Buildwrapper columns start at 1
+
+ if (endLine > startLine) { // IMarker does not support multi-line spans, so we reduce it to an empty span
+ endLine = startLine;
+ endColumn = startColumn;
+ }
+
+ // If the span is empty, we try to extend it to extend it to a single character span.
+ ILineTracker lineTracker = getLineTracker(project.getLocation().toOSString() +"/"+ BWFacade.DIST_FOLDER+"/"+fileName);
+ if (lineTracker != null) {
+ try {
+ //System.err.println("Initial span: "+startLine+":"+startColumn+" to "+endLine+":"+endColumn);
+ int lineLength = lineTracker.getLineLength(startLine-1 /*LineTracker is 0 based*/ )
+ - lineTracker.getLineDelimiter(startLine-1).length(); // subtract the delimiter length
+ if (startLine==endLine && startColumn==endColumn) { // span is empty
+ if (startColumn < lineLength) { // not past the last character, so we can extend to the right.
+ endColumn += 1;
+ } else {
+ if (startColumn > 0) { // past last character, but there are characters to the left.
+ startColumn -= 1;
+ }
+ // else, we have startColumn == lineLength == 0, so the line is empty and we cannot extend the span.
+ }
+ }
+ //System.err.println("Fixed span: "+startLine+":"+startColumn+" to "+endLine+":"+endColumn);
+
+ } catch (BadLocationException e){
+ BuildWrapperPlugin.logError(BWText.process_parse_note_error, e);
+ }
+ } else {
+ //System.err.println("LineTracker is null for file "+fileName);
+ }
+ }
+
+ /**
+ * Create a LineTracker for the file at filePath, for easy querying line lengths.
+ * If any exception occurs, we simply return null.
+ * Note that line numbers are 0 based, and the returned length includes the separator.
+ */
+ private static ILineTracker getLineTracker(String filePath) {
+ ILineTracker lineTracker;
+ InputStream input = null;
+
+ try {
+ lineTracker = new DefaultLineTracker();
+ input = new FileInputStream( filePath );
+
+ byte[] contents = new byte[input.available()];
+ input.read(contents);
+ String stringContents = new String(contents);
+ lineTracker.set(stringContents);
+ }
+ catch(Exception e) { // CoreException or IOException
+ lineTracker = null;
+ }
+ finally {
+ if (input != null)
+ try {
+ input.close();
+ }
+ catch (IOException e) {
+ lineTracker = null;
+ }
+ }
+ return lineTracker;
+ }
+
+
+ /**
+ * Returns the offset within the given document
+ * that the start of this {@link Location} object represents.
+ */
+ public int getStartOffset(IDocument document) throws BadLocationException {
+ return document.getLineOffset(startLine-1) + startColumn;
+ }
+
+ /**
+ * Returns the offset within the given document
+ * that the end of this {@link Location} object represents.
+ */
+ public int getEndOffset(IDocument document) throws BadLocationException {
+ return document.getLineOffset(endLine-1) + endColumn;
+ }
+
+ public int getLength(IDocument document) throws BadLocationException {
+ return getEndOffset(document) - getStartOffset(document);
+ }
+
+ public String getContents(IDocument document) throws BadLocationException {
+ int st=getStartOffset(document);
+ return document.get(st,getEndOffset(document)-st);
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public String getOtherName() {
+ return otherName;
+ }
+
+ public int getStartLine() {
+ return startLine;
+ }
+
+ public int getStartColumn() {
+ return startColumn;
+ }
+
+ public int getEndLine() {
+ return endLine;
+ }
+
+ public int getEndColumn() {
+ return endColumn;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Location)) {
+ return false;
+ }
+ Location other = (Location)obj;
+ return
+ fileName.equals(other.fileName) &&
+ startLine == other.startLine && startColumn == other.startColumn &&
+ endLine == other.endLine && endColumn == other.endColumn;
+ }
+
+ @Override
+ public int hashCode() {
+ return fileName.hashCode()<<16+startLine<<8+startColumn;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%d:%d-%d:%d", startLine, startColumn, endLine, endColumn);
+ }
+
+
+ public IFile getIFile(IProject p){
+ String pl=p.getLocation().toOSString();
+ String loc=getFileName();
+ if (loc!=null && loc.startsWith(pl)){
+ return (IFile)p.getFile(loc.substring(pl.length()));
+ }
+ return null;
+ }
+
+ public Map<Object,Object> getMarkerProperties(int maxLines){
+ int line= Math.min(getStartLine(),maxLines);
+ final Map<Object,Object> attributes=new HashMap<Object,Object>();
+ MarkerUtilities.setLineNumber(attributes, line);
+ int start=getStartColumn();
+ int end=getEndColumn();
+ // if we have startColumn==endColumn we could take end+1
+ // BUT if end goes over the document size, or start is zero, or if Eclipse feels like it, the marker is not shown on the document
+ // so it's better to just show the line without more info
+ if (end>start){
+ MarkerUtilities.setCharStart(attributes, start);
+ // exclusive
+ MarkerUtilities.setCharEnd(attributes, end-1);
+ }
+ return attributes;
+ }
+
+}
Please sign in to comment.
Something went wrong with that request. Please try again.