All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.ceylon.compiler.js.ErrorCollectingVisitor Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
package com.redhat.ceylon.compiler.js;

import static com.redhat.ceylon.compiler.typechecker.tree.TreeUtil.isForBackend;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import com.redhat.ceylon.common.Backend;
import com.redhat.ceylon.common.OSUtil;
import com.redhat.ceylon.compiler.typechecker.TypeChecker;
import com.redhat.ceylon.compiler.typechecker.analyzer.AnalysisError;
import com.redhat.ceylon.compiler.typechecker.analyzer.UsageWarning;
import com.redhat.ceylon.compiler.typechecker.io.VirtualFile;
import com.redhat.ceylon.compiler.typechecker.parser.RecognitionError;
import com.redhat.ceylon.compiler.typechecker.tree.AnalysisMessage;
import com.redhat.ceylon.compiler.typechecker.tree.Message;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.TreeUtil;
import com.redhat.ceylon.compiler.typechecker.tree.UnexpectedError;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;

public class ErrorCollectingVisitor extends Visitor {
    private TypeChecker tc;
    
    private List analErrors = new ArrayList();
    private List recogErrors = new ArrayList();
    
    public static class PositionedMessage {
        public Node node;
        public Message message;
        
        PositionedMessage(Node that, RecognitionError err) {
            node = that;
            message = err;
        }
        
        PositionedMessage(AnalysisMessage msg) {
            node = msg.getTreeNode();
            message = msg;
        }
    }
    
    public ErrorCollectingVisitor(TypeChecker tc) {
        this.tc = tc;
    }

    public int getErrorCount() {
        int errCount = 0;
        for (PositionedMessage pm : analErrors) {
            if (pm.message instanceof AnalysisError ||
                pm.message instanceof UnexpectedError) {
                errCount++;
            }
        }
        return errCount;
    }
    
    public Set getErrors() {
        Set result = new LinkedHashSet();
        if (!recogErrors.isEmpty()) {
            for (PositionedMessage pm : recogErrors) {
                result.add(pm.message);
            }
        } else {
            for (PositionedMessage pm : analErrors) {
                result.add(pm.message);
            }
        }
        return result;
    }

    public void clear() {
        recogErrors.clear();
        analErrors.clear();
    }
    
    private void addErrors(Node that) {
        for (Message m: that.getErrors()) {
            if (m instanceof AnalysisMessage) {
                analErrors.add(new PositionedMessage((AnalysisMessage)m));
            } else {
                recogErrors.add(new PositionedMessage(that, (RecognitionError)m));
            }
        }
    }
    @Override
    public void visitAny(Node that) {
        super.visitAny(that);
        addErrors(that);
    }
    @Override
    public void visit(Tree.Declaration that) {
        if (isForBackend(that.getAnnotationList(), Backend.JavaScript, that.getUnit())
                || isForBackend(that.getAnnotationList(), Backend.Header, that.getUnit())) {
            super.visit(that);
        }
    }
    @Override
    public void visit(Tree.ModuleDescriptor that) {
        if (isForBackend(that.getAnnotationList(), Backend.JavaScript, that.getUnit())
                || isForBackend(that.getAnnotationList(), Backend.Header, that.getUnit())) {
            super.visit(that);
        } else {
            addErrors(that);
        }
    }
    @Override
    public void visit(Tree.ImportModule that) {
        if (isForBackend(that.getAnnotationList(), Backend.JavaScript, that.getUnit())
                || isForBackend(that.getAnnotationList(), Backend.Header, that.getUnit())) {
            super.visit(that);
        }
    }

    public int printErrors(boolean printWarnings, boolean printCount) throws IOException {
        return printErrors(new OutputStreamWriter(System.out), null, printWarnings, printCount);
    }

    public int printErrors(Writer out, DiagnosticListener diagnosticListener, boolean printWarnings, boolean printCount) throws IOException {
        int warnings = 0;
        int count = 0;
        List errors = (!recogErrors.isEmpty()) ? recogErrors : analErrors;
        for (PositionedMessage pm : errors) {
            Message err = pm.message;
            if (err instanceof UsageWarning) {
                if (!printWarnings || ((UsageWarning)err).isSuppressed()) {
                    continue;
                }
            }
            Node node = TreeUtil.getIdentifyingNode(pm.node);
            int line = err.getLine();
            int position = -1;
            if(err instanceof AnalysisMessage){
                if(node != null && node.getToken() != null)
                    position = node.getToken().getCharPositionInLine();
            }else if(err instanceof RecognitionError){
                position = ((RecognitionError) err).getCharacterInLine();
            }
            String fileName = (node.getUnit() != null) ? node.getUnit().getFullPath() : "unknown";
            out.write(OSUtil.color(fileName, OSUtil.Color.blue));
            out.write(":");
            out.write(String.format("%d", line));
            out.write(": ");
            if (err instanceof UsageWarning) {
                out.write(OSUtil.color("warning", OSUtil.Color.yellow));
                warnings++;
            } else {
                out.write(OSUtil.color("error", OSUtil.Color.red));
                count++;
            }
            out.write(": ");
            out.write(err.getMessage());
            out.write(System.lineSeparator());
            String ln = getErrorSourceLine(pm);
            if (ln != null) {
                out.write(ln);
                out.write(System.lineSeparator());
                out.write(getErrorMarkerLine(position));
                out.write(System.lineSeparator());
            }
            
            if(diagnosticListener != null){
                File file = null;
                boolean warning = err instanceof UsageWarning;
                if(node.getUnit() != null && node.getUnit().getFullPath() != null)
                    file = new File(node.getUnit().getFullPath()).getAbsoluteFile();
                if(position != -1)
                    position++; // make it 1-based
                if(warning)
                    diagnosticListener.warning(file, line, position, err.getMessage());
                else
                    diagnosticListener.error(file, line, position, err.getMessage());
            }
        }
        if (printCount) {
            if (count > 0)
                out.write(String.format("%d %s%n", count, count==1?"error":"errors"));
            if (warnings > 0)
                out.write(String.format("%d %s%n", warnings, warnings==1?"warning":"warnings"));
        }
        out.flush();
        return count;
    }

    private String getErrorSourceLine(PositionedMessage pm) {
        if (pm.node.getUnit() != null) {
            int lineNr = pm.message.getLine();
            File file = new File(pm.node.getUnit().getFullPath());
            VirtualFile vfile = tc.getContext().getVfs().getFromFile(file);
            try (BufferedReader br = new BufferedReader(new InputStreamReader(vfile.getInputStream()))) {
                String line;
                while ((line = br.readLine()) != null) {
                    if (--lineNr <= 0) {
                        return line;
                    }
                }
            } catch (IOException e) {
                // Ignore
            }
        }
        return null;
    }

    private String getErrorMarkerLine(int position) {
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < position; i++) {
            str.append(" ");
        }
        str.append("^");
        return str.toString();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy