Skip to content

Commit

Permalink
added basic cabal builder
Browse files Browse the repository at this point in the history
darcs-hash:20080301164509-34f1c-2dec13104484ade4b4f145d885800ca396fb1e98.gz
  • Loading branch information
Leif Frenzel committed Mar 1, 2008
1 parent a74c001 commit b7f3286
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 32 deletions.
3 changes: 1 addition & 2 deletions net.sf.eclipsefp.haskell.cabal.core/META-INF/MANIFEST.MF
Expand Up @@ -7,8 +7,7 @@ Bundle-ClassPath: cabalcore.jar
Bundle-Activator: net.sf.eclipsefp.haskell.cabal.core.internal.CabalCorePlugin
Bundle-Vendor: %bundleVendor
Bundle-Localization: plugin
Require-Bundle: net.sf.eclipsefp.common.core,
net.sf.eclipsefp.haskell.core,
Require-Bundle: net.sf.eclipsefp.haskell.core,
org.eclipse.core.resources,
org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)"
Eclipse-LazyStart: true
Expand Down
Expand Up @@ -3,23 +3,55 @@
package net.sf.eclipsefp.haskell.cabal.core;

import java.util.Map;

import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
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.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;

public class CabalBuilder extends IncrementalProjectBuilder {

// interface methods of IncrementalProjectBuilder
/////////////////////////////////////////////////

@Override
protected IProject[] build( final int kind,
final Map args,
protected IProject[] build( final int kind,
final Map args,
final IProgressMonitor monitor )
throws CoreException {
System.out.println("CabalBuilder.build()");
return null;
deleteAllMarkers();
checkCabalFileExists();
return null; // null means no deltas requested from other projects
}


// helping functions
////////////////////

private void deleteAllMarkers() throws CoreException {
String id = HaskellCorePlugin.ID_PROJECT_PROBLEM_MARKER;
getProject().deleteMarkers( id, false, IResource.DEPTH_INFINITE );
}

private void checkCabalFileExists() throws CoreException {
IFile cabalFile = getCabalFile();
if( !cabalFile.exists() ) {
String id = HaskellCorePlugin.ID_PROJECT_PROBLEM_MARKER;
IMarker marker = getProject().createMarker( id );
marker.setAttribute( IMarker.MESSAGE, "No cabal file in this project (or cabal file has a different name)" );
marker.setAttribute( IMarker.SEVERITY, IMarker.SEVERITY_WARNING );
}
}

private IFile getCabalFile() {
String ext = ResourceUtil.EXTENSION_CABAL;
IPath path = new Path( getProject().getName() ).addFileExtension( ext );
return getProject().getFile( path );
}
}
Expand Up @@ -7,6 +7,7 @@
import net.sf.eclipsefp.haskell.core.test.halamo.HaskellModelManager_PDETest;
import net.sf.eclipsefp.haskell.core.test.halamo.ProjectChangeMonitor_PDETest;
import net.sf.eclipsefp.haskell.core.test.halamo.WorkspaceChangeMonitor_PDETest;
import net.sf.eclipsefp.haskell.core.test.internal.project.CabalBuilder_PDETest;
import net.sf.eclipsefp.haskell.core.test.internal.project.ProjectCreationOperation_PDETest;
import net.sf.eclipsefp.haskell.core.test.project.HaskellProjectCreationOperation_PDETest;
import net.sf.eclipsefp.haskell.core.test.project.ImportLibraries_PDETest;
Expand All @@ -15,6 +16,7 @@ public class AllTests_PDESuite {

public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite( CabalBuilder_PDETest.class );
suite.addTestSuite( SourceFileGenerator_PDETest.class );
suite.addTestSuite( HaskellPropertyTester_PDETest.class );
suite.addTestSuite( HaskellModelManager_PDETest.class );
Expand Down
@@ -0,0 +1,116 @@
package net.sf.eclipsefp.haskell.core.test.internal.project;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import junit.framework.TestCase;
import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
import net.sf.eclipsefp.haskell.core.internal.project.ProjectCreationOperation;
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.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;

public class CabalBuilder_PDETest extends TestCase {

private static final String PROJECT_NAME = "p1";
private IProject project;

@Override
protected void setUp() throws Exception {
ProjectCreationOperation op = new ProjectCreationOperation();
op.setProjectName( PROJECT_NAME );
op.run( null );

IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
project = wsRoot.getProject( PROJECT_NAME );
}

@Override
protected void tearDown() throws Exception {
project.delete( true, null );
}


// actual test cases
////////////////////

public void testNoCabalFileWarning() throws CoreException {
assertTrue( project.exists() );
assertFalse( project.getFile( PROJECT_NAME + ".cabal" ).exists() );
waitForAutoBuild();

// no cabal file -> warning
assertMarker( IMarker.SEVERITY_WARNING, "Cabal file" );
// cabal file -> no warning
IFile cabalFile = createCabalFile();
waitForAutoBuild();
assertEquals( 0, getAllMarkers().length );

// again no cabal file -> warning
cabalFile.delete( true, null );
waitForAutoBuild();
assertMarker( IMarker.SEVERITY_WARNING, "Cabal file" );
}

private IFile createCabalFile() throws CoreException {
IFile result = project.getFile( PROJECT_NAME + ".cabal" );
InputStream is = new ByteArrayInputStream( "".getBytes() );
result.create( is, true, null );
return result;
}



// helping functions
////////////////////

// there is a marker on the project or one of its resources with the
// specified severity and the message snipped is part or the marker message
private boolean assertMarker( final int severity,
final String msg ) throws CoreException {
IMarker[] markers = getAllMarkers();
boolean result = false;
for( IMarker marker: markers ) {
Object sev = marker.getAttribute( IMarker.SEVERITY );
if( sev instanceof Integer ) {
Integer integer = ( Integer )sev;
if( integer.intValue() == severity ) {
String message = marker.getAttribute( IMarker.MESSAGE, "" );
result |= message.indexOf( msg ) != -1;
}
}
}
return result;
}

private IMarker[] getAllMarkers() throws CoreException {
String id = HaskellCorePlugin.ID_PROJECT_PROBLEM_MARKER;
return project.findMarkers( id, true, IResource.DEPTH_INFINITE );
}

private void waitForAutoBuild() throws CoreException {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.build( IncrementalProjectBuilder.CLEAN_BUILD, null );
System.out.print( " Waiting for autobuild to complete ..." ); //$NON-NLS-1$
IJobManager jobMan = Job.getJobManager();
boolean retry = true;
while( retry ) {
try {
jobMan.join( ResourcesPlugin.FAMILY_AUTO_REFRESH, null );
jobMan.join( ResourcesPlugin.FAMILY_AUTO_BUILD, null );
jobMan.join( ResourcesPlugin.FAMILY_MANUAL_BUILD, null );
retry = false;
} catch (Exception exc) {
// ignore and retry
}
}
System.out.print( " OK.\n" ); //$NON-NLS-1$
}
}
1 change: 1 addition & 0 deletions net.sf.eclipsefp.haskell.core/plugin.properties
Expand Up @@ -10,6 +10,7 @@ extPtParsers_name = Haskell Parsers
haskellNature_name = Haskell project nature
haskellBuilder_name = Haskell Builder
haskellProblem_name = Haskell Problem
haskellProjectProblem_name = Haskell Project Problem
haskellApplicationLaunchType_name = Haskell application

pfRefactoring_name = Pointfree refactoring
7 changes: 7 additions & 0 deletions net.sf.eclipsefp.haskell.core/plugin.xml
Expand Up @@ -69,6 +69,13 @@
<super type="org.eclipse.core.resources.problemmarker"/>
<super type="org.eclipse.core.resources.textmarker"/>
</extension>
<extension
id="projectProblem"
name="%haskellProjectProblem_name"
point="org.eclipse.core.resources.markers">
<persistent value="true"/>
<super type="net.sf.eclipsefp.haskell.core.problem"/>
</extension>

<!-- Refactoring support -->

Expand Down
Expand Up @@ -31,6 +31,7 @@ public class HaskellCorePlugin extends Plugin {
public static final String ID_EXT_POINT_COMPILERS = "haskellCompilers"; //$NON-NLS-1$
public static final String ID_EXT_POINT_PARSERS = "haskellParsers"; //$NON-NLS-1$
public static final String ID_PROBLEM_MARKER = "net.sf.eclipsefp.haskell.core.problem"; //$NON-NLS-1$
public static final String ID_PROJECT_PROBLEM_MARKER = "net.sf.eclipsefp.haskell.core.projectProblem"; //$NON-NLS-1$

private static final String ATT_ID = "id"; //$NON-NLS-1$

Expand Down
Expand Up @@ -9,24 +9,30 @@
import org.eclipse.core.runtime.CoreException;

/** <p>The project nature that indicates Haskell projects.</p>
*
*
* @author Leif Frenzel
*/
public class HaskellNature implements IProjectNature {

public static final String NATURE_ID = HaskellNature.class.getName();

private IProject project;
// TODO lf bad design (tacit dependency to a plugin we not openy depend on)
private static final String CABAL_BUILDER_ID
= "net.sf.eclipsefp.haskell.cabal.core.CabalBuilder"; //$NON-NLS-1$

private IProject project;


// interface methods of IProjectNature
//////////////////////////////////////

public void configure() throws CoreException {
addBuilder( HaskellBuilder.BUILDER_ID );
addBuilder( CABAL_BUILDER_ID );
}

public void deconfigure() throws CoreException {
removeBuilder( CABAL_BUILDER_ID );
removeBuilder( HaskellBuilder.BUILDER_ID );
}

Expand All @@ -37,23 +43,23 @@ public IProject getProject() {
public void setProject( final IProject project ) {
this.project = project;
}


// helping methods
//////////////////

private void addBuilder( final String builderID ) throws CoreException {
IProjectDescription desc = getProject().getDescription();
ICommand[] commands = desc.getBuildSpec();
boolean found = false;

for( int i = 0; !found && i < commands.length; ++i ) {
String builderName = commands[ i ].getBuilderName();
String builderName = commands[ i ].getBuilderName();
if( builderName.equals( builderID ) ) {
found = true;
}
}
if( !found ) {
if( !found ) {
//add builder to project
ICommand command = desc.newCommand();
command.setBuilderName( builderID );
Expand All @@ -74,10 +80,10 @@ private void removeBuilder( final String builderID ) throws CoreException {
if( commands[ i ].getBuilderName().equals( builderID ) ) {
ICommand[] newCommands = new ICommand[ commands.length - 1 ];
System.arraycopy( commands, 0, newCommands, 0, i );
System.arraycopy( commands,
i + 1,
newCommands,
i,
System.arraycopy( commands,
i + 1,
newCommands,
i,
commands.length - i - 1 );
description.setBuildSpec( newCommands );
getProject().setDescription( description, null );
Expand Down
Expand Up @@ -54,7 +54,7 @@ private String createDescriptorContent() {
}

private boolean createFolders() {
final String prefKey = ICorePreferenceNames.FOLDERS_IN_NEW_PROJECT;
String prefKey = ICorePreferenceNames.FOLDERS_IN_NEW_PROJECT;
return getStore().getBoolean(prefKey);
}

Expand Down
Expand Up @@ -29,19 +29,9 @@
*/
public class ResourceUtil {

/**
* <p>
* the file extension of Haskell source files.
* </p>
*/
public static final String EXTENSION_HS = "hs"; //$NON-NLS-1$

/**
* <p>
* the file extension of literate Haskell source files.
* </p>
*/
public static final String EXTENSION_LHS = "lhs"; //$NON-NLS-1$
public static final String EXTENSION_CABAL = "cabal"; //$NON-NLS-1$

/**
* <p>
Expand Down

0 comments on commit b7f3286

Please sign in to comment.