/* * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered * by the modified BSD License. You should have received a copy of the * modified BSD license with this compiler. * * Copyright (c) 2005-2008, Torbjorn Ekman * All rights reserved. */ aspect ErrorCheck { protected String ASTNode.sourceFile() { ASTNode node = this; while(node != null && !(node instanceof CompilationUnit)) node = node.getParent(); if(node == null) return "Unknown file"; CompilationUnit u = (CompilationUnit)node; return u.relativeName(); } syn int ASTNode.lineNumber() { ASTNode n = this; while(n.getParent() != null && n.getStart() == 0) { n = n.getParent(); } return getLine(n.getStart()); } eq ClassDecl.lineNumber() = getLine(IDstart); eq MethodDecl.lineNumber() = getLine(IDstart); // set start and end position to the same as the argument and return self public ASTNode ASTNode.setLocation(ASTNode node) { setStart(node.getStart()); setEnd(node.getEnd()); return this; } public ASTNode ASTNode.setStart(int i) { start = i; return this; } public int ASTNode.start() { return start; } public ASTNode ASTNode.setEnd(int i) { end = i; return this; } public int ASTNode.end() { return end; } public String ASTNode.location() { return "" + lineNumber(); } public String ASTNode.errorPrefix() { return sourceFile() + ":" + location() + ":\n" + " *** Semantic Error: "; } public String ASTNode.warningPrefix() { return sourceFile() + ":" + location() + ":\n" + " *** WARNING: "; } protected java.util.ArrayList CompilationUnit.errors = new java.util.ArrayList(); protected java.util.ArrayList CompilationUnit.warnings = new java.util.ArrayList(); public Collection CompilationUnit.parseErrors() { return parseErrors; } public void CompilationUnit.addParseError(Problem msg) { parseErrors.add(msg); } protected Collection CompilationUnit.parseErrors = new ArrayList(); class Problem implements Comparable { public int compareTo(Object o) { if(o instanceof Problem) { Problem other = (Problem)o; if(!fileName.equals(other.fileName)) return fileName.compareTo(other.fileName); if(line != other.line) return line - other.line; return message.compareTo(other.message); } return 0; } public static class Severity { public static final Severity ERROR = new Severity(); public static final Severity WARNING = new Severity(); private Severity() { } } public static class Kind { public static final Kind OTHER = new Kind(); public static final Kind LEXICAL = new Kind(); public static final Kind SYNTACTIC = new Kind(); public static final Kind SEMANTIC = new Kind(); private Kind() { } } protected int line = -1; public int line() { return line; } protected int column = -1; public int column() { return column; } protected int endLine = -1; public int endLine() { return endLine; } protected int endColumn = -1; public int endColumn() { return endColumn; } protected String fileName; public String fileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } protected String message; public String message() { return message; } protected Severity severity = Severity.ERROR; public Severity severity() { return severity; } protected Kind kind = Kind.OTHER; public Kind kind() { return kind; } public Problem(String fileName, String message) { this.fileName = fileName; this.message = message; } public Problem(String fileName, String message, int line) { this(fileName, message); this.line = line; } public Problem(String fileName, String message, int line, Severity severity) { this(fileName, message); this.line = line; this.severity = severity; } public Problem(String fileName, String message, int line, int column, Severity severity) { this(fileName, message); this.line = line; this.column = column; this.severity = severity; } public Problem(String fileName, String message, int line, Severity severity, Kind kind) { this(fileName, message); this.line = line; this.kind = kind; this.severity = severity; } public Problem(String fileName, String message, int line, int column, Severity severity, Kind kind) { this(fileName, message); this.line = line; this.column = column; this.kind = kind; this.severity = severity; } public Problem(String fileName, String message, int line, int column, int endLine, int endColumn, Severity severity, Kind kind) { this(fileName, message); this.line = line; this.column = column; this.endLine = endLine; this.endColumn = endColumn; this.kind = kind; this.severity = severity; } public String toString() { String location = ""; if(line != -1 && column != -1) location = line + "," + column + ":"; else if(line != -1) location = line + ":"; String s = ""; if(this.kind == Kind.LEXICAL) s = "Lexical Error: "; else if(this.kind == Kind.SYNTACTIC) s = "Syntactic Error: "; else if(this.kind == Kind.SEMANTIC) s = "Semantic Error: "; return fileName + ":" + location + "\n" + " " + s + message; } } public void ASTNode.error(String s) { ASTNode node = this; while(node != null && !(node instanceof CompilationUnit)) node = node.getParent(); CompilationUnit cu = (CompilationUnit)node; if(getNumChild() == 0 && getStart() != 0 && getEnd() != 0) { int line = getLine(getStart()); int column = getColumn(getStart()); int endLine = getLine(getEnd()); int endColumn = getColumn(getEnd()); cu.errors.add(new Problem(sourceFile(), s, line, column, endLine, endColumn, Problem.Severity.ERROR, Problem.Kind.SEMANTIC)); } else cu.errors.add(new Problem(sourceFile(), s, lineNumber(), Problem.Severity.ERROR, Problem.Kind.SEMANTIC)); } public void ASTNode.warning(String s) { ASTNode node = this; while(node != null && !(node instanceof CompilationUnit)) node = node.getParent(); CompilationUnit cu = (CompilationUnit)node; cu.warnings.add(new Problem(sourceFile(), "WARNING: " + s, lineNumber(), Problem.Severity.WARNING)); } public void ASTNode.collectErrors() { nameCheck(); typeCheck(); accessControl(); exceptionHandling(); checkUnreachableStmt(); definiteAssignment(); checkModifiers(); for(int i = 0; i < getNumChild(); i++) { getChild(i).collectErrors(); } } public void Program.errorCheck(Collection collection) { for(Iterator iter = compilationUnitIterator(); iter.hasNext(); ) { CompilationUnit cu = (CompilationUnit)iter.next(); if(cu.fromSource()) { cu.collectErrors(); collection.addAll(cu.errors); } } } public void Program.errorCheck(Collection collection, Collection warn) { for(Iterator iter = compilationUnitIterator(); iter.hasNext(); ) { CompilationUnit cu = (CompilationUnit)iter.next(); if(cu.fromSource()) { cu.collectErrors(); collection.addAll(cu.errors); warn.addAll(cu.warnings); } } } public void CompilationUnit.errorCheck(Collection collection) { collectErrors(); collection.addAll(errors); } public void CompilationUnit.errorCheck(Collection err, Collection warn) { collectErrors(); err.addAll(errors); warn.addAll(warnings); } public boolean Program.errorCheck() { Collection collection = new LinkedList(); errorCheck(collection); if(collection.isEmpty()) return false; System.out.println("Errors:"); for(Iterator iter = collection.iterator(); iter.hasNext(); ) { String s = (String)iter.next(); System.out.println(s); } return true; } }