package com.redhat.ceylon.eclipse.core.builder; import static com.redhat.ceylon.eclipse.util.Nodes.getIdentifyingNode; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.net.URI; import java.net.URISyntaxException; import java.util.Locale; import com.redhat.ceylon.javax.lang.model.element.Modifier; import com.redhat.ceylon.javax.lang.model.element.NestingKind; import com.redhat.ceylon.javax.tools.Diagnostic; import com.redhat.ceylon.javax.tools.JavaFileObject; import org.antlr.runtime.Token; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import com.redhat.ceylon.compiler.typechecker.analyzer.AnalysisError; import com.redhat.ceylon.compiler.typechecker.tree.AnalysisMessage; import com.redhat.ceylon.compiler.typechecker.tree.Node; import com.redhat.ceylon.compiler.typechecker.tree.UnexpectedError; //This is bullshit. The IDE should have a nice way of converting //compilation units into objects that can be shown in the problems //view, and even a nice way of converting errors in nodes in the //typechecker into errors that can be shown in the problems view. //Right now I'm using this for the js compiler errors but I expect //to see other people wanting this and probably implementing their own //solution again. public class CeylonCompilationError implements Diagnostic<JavaFileObject> { private final AnalysisMessage err; private final IProject project; private final JavaFileObject jf; private final IFile file; public CeylonCompilationError(IProject proj, AnalysisMessage error) { err = error; this.project = proj; file = project.getFile(err.getTreeNode().getUnit().getFullPath()); jf = new JavaFileObject() { @Override public URI toUri() { try { return new URI(file.getFullPath().toString()); } catch (URISyntaxException e) { e.printStackTrace(); } return null; } @Override public Writer openWriter() throws IOException { return null; } @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { return null; } @Override public OutputStream openOutputStream() throws IOException { return null; } @Override public InputStream openInputStream() throws IOException { return null; } @Override public String getName() { return file.getLocation().toOSString(); } @Override public long getLastModified() { return file.getModificationStamp(); } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return null; } @Override public boolean delete() { return false; } @Override public boolean isNameCompatible(String simpleName, Kind kind) { return false; } @Override public NestingKind getNestingKind() { return NestingKind.TOP_LEVEL; } @Override public Kind getKind() { return Kind.SOURCE; } @Override public Modifier getAccessLevel() { return Modifier.FINAL; } }; } @Override public com.redhat.ceylon.javax.tools.Diagnostic.Kind getKind() { return (err instanceof AnalysisError || err instanceof UnexpectedError) ? Diagnostic.Kind.ERROR : Diagnostic.Kind.WARNING; } @Override public JavaFileObject getSource() { return jf; } @Override public long getPosition() { return getStartPosition(); } @Override public long getStartPosition() { int startOffset = 0; Node errorNode = getIdentifyingNode(err.getTreeNode()); if (errorNode == null) { errorNode = err.getTreeNode(); } Token token = errorNode.getToken(); if (token!=null) { startOffset = errorNode.getStartIndex(); } return startOffset; } @Override public long getEndPosition() { int endOffset = 0; Node errorNode = getIdentifyingNode(err.getTreeNode()); if (errorNode == null) { errorNode = err.getTreeNode(); } Token token = errorNode.getToken(); if (token!=null) { endOffset = errorNode.getEndIndex(); } return endOffset - 1; } @Override public long getLineNumber() { int line = err.getLine(); Node node = err.getTreeNode(); Node errorNode = getIdentifyingNode(node); if (errorNode == null) { errorNode = node; } Token token = errorNode.getToken(); if (token!=null) { line = token.getLine(); } return line; } @Override public long getColumnNumber() { int startCol = 0; Node node = err.getTreeNode(); Node errorNode = getIdentifyingNode(node); if (errorNode == null) { errorNode = node; } Token token = errorNode.getToken(); if (token!=null) { startCol = token.getCharPositionInLine(); } return startCol; } @Override public String getCode() { return String.valueOf(err.getCode()); } @Override public String getMessage(Locale locale) { return err.getMessage(); } }