/*******************************************************************************
* Copyright (c) 2009-2011 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* * Mark Hills - Mark.Hills@cwi.nl (CWI)
*******************************************************************************/
package org.rascalmpl.eclipse.library.util;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.progress.IProgressService;
import org.rascalmpl.eclipse.Activator;
import org.rascalmpl.eclipse.IRascalResources;
import org.rascalmpl.interpreter.IEvaluatorContext;
import org.rascalmpl.interpreter.control_exceptions.Throw;
import org.rascalmpl.interpreter.utils.RuntimeExceptionFactory;
import org.rascalmpl.uri.URIResolverRegistry;
import org.rascalmpl.uri.URIResourceResolver;
import io.usethesource.vallang.IConstructor;
import io.usethesource.vallang.ISet;
import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.IString;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.IValueFactory;
public class ResourceMarkers {
public ResourceMarkers(IValueFactory values){
super();
}
public void removeMessageMarkers(ISourceLocation loc, IEvaluatorContext ctx) {
try {
loc = URIResolverRegistry.getInstance().logicalToPhysical(loc);
}
catch (IOException e) {
// couldn't resolve it, must be a physical one already.
}
IResource resource = URIResourceResolver.getResource(loc);
if (resource instanceof IFile) {
IFile file = (IFile) resource;
try {
file.deleteMarkers(IRascalResources.ID_RASCAL_MARKER, false, IResource.DEPTH_ZERO);
} catch (CoreException ce) {
throw RuntimeExceptionFactory.javaException(ce, null, null);
}
}
else if (resource instanceof IFolder) {
try {
resource.accept(new IResourceVisitor() {
@Override
public boolean visit(IResource resource) throws CoreException {
if (resource instanceof IFile) {
IFile file = (IFile) resource;
file.deleteMarkers(IRascalResources.ID_RASCAL_MARKER, false, IResource.DEPTH_ZERO);
return false;
}
return true;
}
}, IResource.DEPTH_INFINITE, false);
} catch (CoreException e) {
Activator.log("could not remove markers", e);
}
}
}
private void removeMessageMarkers(ISet markers, IEvaluatorContext ctx) {
for (IValue msg : markers) {
IConstructor marker = (IConstructor) msg;
if (! marker.getType().getName().equals("Message"))
throw RuntimeExceptionFactory.illegalArgument(marker, null, null);
removeMessageMarkers((ISourceLocation)marker.get(1), ctx);
}
return;
}
public void addMessageMarkers(final ISet markers, final IEvaluatorContext ctx) {
// we need two locks, one for the UI and one for the resources
// because we know we might need to lock a lot of resources we lock the entire workspace here
// and prevent lock starvation where for every file and every ui operation to add a marker we
// need to get a new lock. The resulting code is complex but its fast.
final WorkspaceModifyOperation wmo = new WorkspaceModifyOperation(ResourcesPlugin.getWorkspace().getRoot()) {
public void execute(IProgressMonitor monitor) {
removeMessageMarkers(markers, ctx);
for (IValue msg : markers) {
IConstructor marker = (IConstructor) msg;
if (! marker.getType().getName().equals("Message"))
throw RuntimeExceptionFactory.illegalArgument(marker, null, null);
ISourceLocation loc = (ISourceLocation)marker.get(1);
try {
loc = URIResolverRegistry.getInstance().logicalToPhysical(loc);
}
catch (IOException e) {
// couldn't resolve it, must be a physical one already.
}
IResource resource = URIResourceResolver.getResource(loc);
if (resource instanceof IFile) {
IFile file = (IFile) resource;
try {
int severity = IMarker.SEVERITY_INFO;
if (marker.getName().equals("error"))
severity = IMarker.SEVERITY_ERROR;
else if (marker.getName().equals("warning"))
severity = IMarker.SEVERITY_WARNING;
IString markerMessage = (IString)marker.get(0);
ISourceLocation markerLocation = loc;
String[] attributeNames= new String[] {
IMarker.LINE_NUMBER,
IMarker.CHAR_START,
IMarker.CHAR_END,
IMarker.MESSAGE,
IMarker.PRIORITY,
IMarker.SEVERITY
};
Object[] values= new Object[] {
markerLocation.getBeginLine(),
markerLocation.getOffset(),
markerLocation.getOffset() + markerLocation.getLength(),
markerMessage.getValue(),
IMarker.PRIORITY_HIGH,
severity
};
IMarker m = file.createMarker(IRascalResources.ID_RASCAL_MARKER);
m.setAttributes(attributeNames, values);
} catch (CoreException ce) {
throw RuntimeExceptionFactory.javaException(ce, null, null);
}
}
}
}
};
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
IProgressService ips = PlatformUI.getWorkbench().getProgressService();
try {
ips.run(false, true, wmo);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof Throw) {
throw (Throw) e.getTargetException();
}
else {
throw RuntimeExceptionFactory.javaException(e.getTargetException(), null, null);
}
} catch (InterruptedException e) {
Activator.getInstance().logException("??", e);
}
}
});
}
}