/*******************************************************************************
* Copyright (c) 2012 Lars Kroll.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Lars Kroll - initial API and implementation
******************************************************************************/
package se.sics.kompics.ide.builder;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import se.sics.kompics.ide.Activator;
import se.sics.kompics.ide.Model;
public class KompicsModelBuilder extends IncrementalProjectBuilder {
private List<ASTNode> deferredUnits = new LinkedList<ASTNode>();
private IProject curProject = null;
public void defer(ASTNode astn) {
deferredUnits.add(astn);
}
private void retryDeferred() {
ASTNode[] dv = deferredUnits.toArray(new ASTNode[deferredUnits.size()]);
deferredUnits.clear();
for (ASTNode astn : dv) {
ModelVisitor mv = new ModelVisitor(astn, this);
astn.accept(mv);
}
}
// class SampleDeltaVisitor implements IResourceDeltaVisitor {
// /*
// * (non-Javadoc)
// *
// * @see
// * org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse
// * .core.resources.IResourceDelta)
// */
// public boolean visit(IResourceDelta delta) throws CoreException {
// IResource resource = delta.getResource();
// switch (delta.getKind()) {
// case IResourceDelta.ADDED:
// // handle added resource
// checkModel(resource);
// break;
// case IResourceDelta.REMOVED:
// // handle removed resource
// break;
// case IResourceDelta.CHANGED:
// // handle changed resource
// checkModel(resource);
// break;
// }
// // return true to continue visiting children.
// return true;
// }
// }
// class SampleResourceVisitor implements IResourceVisitor {
// public boolean visit(IResource resource) {
// checkModel(resource);
// // return true to continue visiting children.
// return true;
// }
// }
public static final String BUILDER_ID = "KompicsIDE.kompicsModelBuilder";
private static final String MARKER_TYPE = "KompicsIDE.modelProblem";
private final Map<String, IMarker> markers = new HashMap<String, IMarker>();
void addMarker(String id, IResource file, String message, int lineNumber, int severity) {
if (file == null) {
file = curProject;
}
if (file == null) {
return; // No idea where to add the marker
}
if (markers.get(id) != null) return; // marker has already been added
try {
IMarker marker = file.createMarker(MARKER_TYPE);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, severity);
if (lineNumber == -1) {
lineNumber = 1;
}
marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
} catch (CoreException e) {
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.internal.events.InternalBuilder#build(int,
* java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
*/
protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException {
// if (kind == FULL_BUILD) {
// fullBuild(monitor);
// } else {
// IResourceDelta delta = getDelta(getProject());
// if (delta == null) {
// fullBuild(monitor);
// } else {
// incrementalBuild(delta, monitor);
// }
// }
fullBuild(monitor);
return null;
}
void checkModel(IResource resource) {
IProject project = resource.getProject();
curProject = project;
deleteMarkers(project);
markers.clear();
String header = "***********************\n";
header += "****** NEW BUILD ******\n";
header += "***********************\n";
Activator.log("\n" + header);
try {
IPackageFragment[] packages = JavaCore.create(project).getPackageFragments();
// parse(JavaCore.create(project));
for (IPackageFragment mypackage : packages) {
if (mypackage.getKind() == IPackageFragmentRoot.K_SOURCE) {
createAST(mypackage);
}
}
int defNum = deferredUnits.size() + 1; // just to get it started^^
while (deferredUnits.size() < defNum) {
defNum = deferredUnits.size();
retryDeferred();
}
if (deferredUnits.size() != 0) {
String error = "Sorry it appears that we have hit a dead end";
error += " while retrying deferred compilation units.";
error += "\n This is most likely due to a circular dependency in the model.";
Activator.log(error);
}
Activator.log("\n *** Validating Model ***");
ModelValidator mv = new ModelValidator(this);
mv.validate();
} catch (JavaModelException e) {
Activator.log(IStatus.ERROR, e.getMessage());
}
}
private void createAST(IPackageFragment mypackage) throws JavaModelException {
for (ICompilationUnit unit : mypackage.getCompilationUnits()) {
// Now create the AST for the ICompilationUnits
CompilationUnit parse = parse(unit);
ModelVisitor visitor = new ModelVisitor(parse, this);
parse.accept(visitor);
}
}
/**
* * Reads a ICompilationUnit and creates the AST DOM for manipulating the *
* Java source file * * @param unit * @return
*/
private static CompilationUnit parse(ICompilationUnit unit) {
ASTParser parser = ASTParser.newParser(AST.JLS4);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(unit);
parser.setResolveBindings(true);
return (CompilationUnit) parser.createAST(null); // parse
}
private void deleteMarkers(IResource file) {
try {
file.deleteMarkers(MARKER_TYPE, false, IResource.DEPTH_INFINITE);
} catch (CoreException ce) {
}
}
protected void fullBuild(final IProgressMonitor monitor) throws CoreException {
Model.clearAll();
checkModel(getProject());
}
// protected void incrementalBuild(IResourceDelta delta, IProgressMonitor
// monitor)
// throws CoreException {
// // the visitor does the work.
// delta.accept(new SampleDeltaVisitor());
// }
}