package net.sf.eclipsefp.haskell.core.hlint;
import java.util.Map;
import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
import net.sf.eclipsefp.haskell.hlint.Severity;
import net.sf.eclipsefp.haskell.hlint.Suggestion;
import net.sf.eclipsefp.haskell.util.FileUtil;
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.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
/**
* HLint builder: calls HLint, parses the results and shows
* them as file markers in the editor.
*
* @author Alejandro Serrano
*/
public class HLintBuilder extends IncrementalProjectBuilder {
public static String BUILDER_ID = HLintBuilder.class.getName();
public HLintBuilder() {
// Do nothing
}
@Override
protected IProject[] build( final int kind, final Map<String,String> args,
final IProgressMonitor monitor ) throws CoreException {
if( kind == INCREMENTAL_BUILD || kind == AUTO_BUILD ) {
// Get delta
final IResourceDelta delta = getDelta( getProject() );
if( delta == null ) {
return null;
}
delta.accept( new DeltaVisitor() );
} else if( kind == CLEAN_BUILD ) {
clean( monitor );
} else if( kind == FULL_BUILD ) {
clean( monitor );
getProject().accept( new FullBuildVisitor() );
}
// Complete code here
return null;
}
@Override
protected void clean( final IProgressMonitor monitor ) throws CoreException {
getProject().accept( new CleanVisitor() );
}
@Override
public ISchedulingRule getRule( final int kind, final Map<String, String> args ) {
// prevent other project operations, but operations elsewhere in the workspace are fine
return getProject();
}
/**
* return a IFile representing the resource if needed, or null if not needed
* @param resource the resource
* @return the IFile object to analyze, or null if nothing to do
*/
static IFile getFileToVisit( final IResource resource ) {
if ( resource instanceof IFile
&& hasCorrectExtension( resource.getProjectRelativePath() )
&& ResourceUtil.isInSourceFolder( ( IFile )resource )
&& !resource.isDerived() ){
return (IFile)resource;
}
return null;
}
static boolean mustBeVisited( final IResource resource ) {
return getFileToVisit( resource )!=null;
}
static boolean hasCorrectExtension( final IPath path ) {
if( path == null ) {
return false;
}
String extension = path.getFileExtension();
if( extension == null ) {
return false;
}
return extension.equals( FileUtil.EXTENSION_HS );
}
/**
* show always the full text?
*/
private static boolean alwaysFull=false;
public static void setAlwaysFull( final boolean alwaysFull ) {
HLintBuilder.alwaysFull = alwaysFull;
}
static void createMarker( final IResource resource, final Suggestion s )
throws CoreException {
if( s.getSeverity() != Severity.IGNORE ) {
IMarker marker = resource
.createMarker( HaskellCorePlugin.ID_HLINT_MARKER );
marker.setAttribute( IMarker.MESSAGE, s.getMarkerText(alwaysFull) );
marker.setAttribute( IMarker.SEVERITY,getMarkerSeverity(s.getSeverity()) );
marker.setAttribute( IMarker.LINE_NUMBER, s.getLocation().getLine() );
marker.setAttribute( HaskellCorePlugin.ATT_HLINT_SUGGESTION, s.toString() );
}
}
private static int getMarkerSeverity(final Severity sev){
switch( sev ) {
case ERROR:
return IMarker.SEVERITY_WARNING;
case WARNING:
return IMarker.SEVERITY_WARNING;
default:
return IMarker.SEVERITY_INFO;
}
}
}