Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 8 commits
  • 80 files changed
  • 0 commit comments
  • 1 contributor
Commits on Aug 01, 2009
@ttencate ttencate Refactored HaskellProject in preparation of storing more info in the …
…Cabal file, if present.

A separate interface, IHaskellProjectInfo, can now be implemented in two ways:
as a simple thing that stores the info in the .hsproject file (current implementation),
or as a more fancy thing that updates the Cabal file with the new information (to be implemented).
a55ab7d
@ttencate ttencate Writing the new HaskellProject structure to the .hsproject XML file.
Two unit tests fail, but this is expected behaviour.
5085c4c
Commits on Aug 08, 2009
@ttencate ttencate Labeled all my own TODOs with TtC for future reference.
Implemented some small things for Windows (untested).
8ba97b2
@ttencate ttencate Added a Build Targets node under the project in the Project Explorer.
The idea is that build targets can be added, removed, configured and run from here.
118607c
@ttencate ttencate Removed needless special tree node classes; now using label provider. ecebd61
Commits on Aug 20, 2009
@ttencate ttencate Added "New Build Target" wizard.
The new build target does not yet show up until the tree is refreshed, though.
ea0241d
Commits on Aug 25, 2009
@ttencate ttencate Fixed bug extracting wrong name from build target wizard. aded104
@ttencate ttencate Added scion plugin to the Haskell feature. 37dc52c
Showing with 1,639 additions and 483 deletions.
  1. +17 −0 net.sf.eclipsefp.haskell-feature/compile.net.sf.eclipsefp.haskell.xml
  2. +7 −0 net.sf.eclipsefp.haskell-feature/feature.xml
  3. +30 −22 ....eclipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/internal/project/HaskellProject_PDETest.java
  4. +1 −0  ...askell.core.test/src/net/sf/eclipsefp/haskell/core/internal/project/TestHaskellProjectMetaTest_PDETest.java
  5. +3 −2 net.sf.eclipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/internal/util/ResourceUtil_PDETest.java
  6. +2 −1  net.sf.eclipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/internal/util/TestHaskellProject.java
  7. +8 −5 ...fp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/project/HaskellProjectCreationOperation_PDETest.java
  8. +23 −0 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/BuildTarget.java
  9. +1 −1  net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/CabalBuilder.java
  10. +91 −75 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/DescriptorFile.java
  11. +0 −31 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/DescriptorFileInfo.java
  12. +25 −0 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/ExecutableBuildTarget.java
  13. +74 −32 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/HaskellProject.java
  14. +18 −0 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/IExecutableBuildTarget.java
  15. +14 −11 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/IXMLNames.java
  16. +108 −42 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/Parser.java
  17. +9 −22 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/ProjectCreationOperation.java
  18. +70 −0 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/SimpleHaskellProjectInfo.java
  19. +2 −1  net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/CorePreferenceInitializer.java
  20. +1 −0  net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/ICorePreferenceNames.java
  21. +29 −23 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/HaskellProjectCreationOperation.java
  22. +4 −44 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/HaskellProjectManager.java
  23. +25 −0 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/IBuildTarget.java
  24. +14 −17 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/IHaskellProject.java
  25. +67 −0 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/IHaskellProjectInfo.java
  26. +3 −12 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/util/GHCSyntax.java
  27. +1 −1  net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/util/QueryUtil.java
  28. +32 −6 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/util/ResourceUtil.java
  29. +4 −4 ...L/java/test/net/sf/eclipsefp/haskell/debug/ui/internal/launch/ghci/GhciLaunchOperationDelegate_PDETest.java
  30. +10 −7 net.sf.eclipsefp.haskell.ghccompiler/src/net/sf/eclipsefp/haskell/ghccompiler/core/GhcCompiler.java
  31. +1 −1  net.sf.eclipsefp.haskell.ghccompiler/src/net/sf/eclipsefp/haskell/ghccompiler/core/GhcOutputParser.java
  32. +1 −1  net.sf.eclipsefp.haskell.scion.client/src/net/sf/eclipsefp/haskell/scion/client/ScionInstance.java
  33. +0 −1  net.sf.eclipsefp.haskell.scion.client/src/net/sf/eclipsefp/haskell/scion/client/ScionPlugin.java
  34. +1 −1  ...clipsefp.haskell.scion.client/src/net/sf/eclipsefp/haskell/scion/internal/commands/DefinedNamesCommand.java
  35. +1 −1  net.sf.eclipsefp.haskell.scion.client/src/net/sf/eclipsefp/haskell/scion/types/Location.java
  36. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/executable_obj.gif
  37. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/executablestanza.gif
  38. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/lambda.gif
  39. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/library.gif
  40. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/library_obj.gif
  41. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/librarystanza.gif
  42. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/projexe.gif
  43. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/target_obj.gif
  44. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/targets_obj.gif
  45. +3 −0  net.sf.eclipsefp.haskell.ui/plugin.properties
  46. +63 −0 net.sf.eclipsefp.haskell.ui/plugin.xml
  47. +26 −4 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/Validator.java
  48. +14 −1 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/ValidatorManager.java
  49. +1 −1  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/dialogfields/DialogField.java
  50. +8 −5 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/dialogfields/StringDialogField.java
  51. +1 −1  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/handlers/OpenDefinitionHandler.java
  52. +65 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/dialogs/EditBuildTargetDialog.java
  53. +41 −0 ....eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/dialogs/EditExecutableBuildTargetDialog.java
  54. +1 −3 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/cabal/forms/CabalFormSection.java
  55. +1 −1  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellEditor.java
  56. +1 −1  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/HaskellTextHover.java
  57. +1 −3 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/text/CodeFolding.java
  58. +1 −3 ...skell.ui/src/net/sf/eclipsefp/haskell/ui/internal/editors/haskell/text/HaskellFoldingStructureProvider.java
  59. +64 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/handlers/AddBuildTargetHandler.java
  60. +4 −5 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/preferences/scion/ScionPP.java
  61. +1 −2  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/refactoring/MakePointFreeDelegate.java
  62. +1 −2  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/refactoring/RenameDelegate.java
  63. +61 −21 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/util/FileUtil.java
  64. +16 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/util/UITexts.java
  65. +16 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/util/uitexts.properties
  66. +1 −2  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/views/outline/HaskellOutlinePage.java
  67. +4 −2 ...p.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/views/projectexplorer/HaskellResourceExtensionCP.java
  68. +12 −2 ...p.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/views/projectexplorer/HaskellResourceExtensionLP.java
  69. +46 −0 ...eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/views/projectexplorer/model/BuildTargets.java
  70. +28 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/wizards/BuildTargetWizardPage.java
  71. +17 −15 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/wizards/CabalPackageImportWP.java
  72. +119 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/wizards/CommonBuildTargetWizardPage.java
  73. +60 −0 ....eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/wizards/ExecutableBuildTargetWizardPage.java
  74. +44 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/wizards/LibraryBuildTargetWizardPage.java
  75. +91 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/wizards/NewBuildTargetWizard.java
  76. +16 −40 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/wizards/NewProjectWizardPage.java
  77. +63 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/internal/wizards/ValidatedWizardPage.java
  78. +7 −4 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/util/HaskellUIImages.java
  79. +4 −1 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/util/IImageNames.java
  80. +40 −0 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/wizards/AddBuildTargetOperation.java
View
17 net.sf.eclipsefp.haskell-feature/compile.net.sf.eclipsefp.haskell.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="Compile net.sf.eclipsefp.haskell" default="main">
+ <target name="main">
+ <ant antfile="build.xml" dir="../org.antlr" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.doc.user" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.debug.core" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.scion.client" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.core" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.ui" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.ghccompiler" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.debug.ui" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.hugs" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.core.jparser" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell.haddock" target="build.jars"/>
+ <ant antfile="build.xml" dir="../net.sf.eclipsefp.haskell" target="build.jars"/>
+ </target>
+</project>
View
7 net.sf.eclipsefp.haskell-feature/feature.xml
@@ -118,4 +118,11 @@ available at http://www.eclipse.org/legal/epl-v10.html.
version="1.106.0"
unpack="false"/>
+ <plugin
+ id="net.sf.eclipsefp.haskell.scion.client"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
View
52 ...lipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/internal/project/HaskellProject_PDETest.java
@@ -6,6 +6,7 @@
import net.sf.eclipsefp.haskell.core.project.HaskellProjectManager;
import net.sf.eclipsefp.haskell.core.test.TestCaseWithProject;
import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
+import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
@@ -38,7 +39,7 @@ public void testSingleSourcePath() {
public void testMultipleSourcePaths() {
HaskellProject hp = ( HaskellProject )HaskellProjectManager.get( project );
- hp.addSourcePath( "test" );
+ hp.addSourcePath( new Path("test") );
assertEquals( 2, hp.getSourcePaths().size() );
// TODO lf we should really get two here
// assertEquals( project.getFolder( "src" ), hp.getSourceFolder() );
@@ -51,35 +52,42 @@ public void testMultipleSourcePaths() {
public void testTargetExecutable_single() throws CoreException {
HaskellProject hp = ( HaskellProject )HaskellProjectManager.get( project );
// atm one target exe is added automatically during project creation
- assertEquals( 1, hp.getTargetNames().size() );
+ assertEquals( 1, hp.getTargets().size() );
- IPath path = new Path( "bla.exe" );
+ IPath path = new Path( "bla" );
InputStream is = new ByteArrayInputStream( new byte[ 0 ] );
- project.getFile( path ).create( is, true, null );
- hp.addTargetName( path );
- assertEquals( 2, hp.getTargetNames().size() );
-
- assertTrue( ResourceUtil.isProjectExecutable( project.getFile( "bla.exe" ) ) );
- assertFalse( ResourceUtil.isProjectExecutable( project.getFile( "blubb.exe" ) ) );
+ IFolder out = project.getFolder( "out" );
+ out.getFile( ResourceUtil.executableName( path ) ).create( is, true, null );
+ hp.addTarget( new ExecutableBuildTarget( path, "Main.main" ) );
+ assertEquals( 2, hp.getTargets().size() );
+
+ assertTrue( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "out/bla" ) ) ) );
+ assertFalse( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "bla" ) ) ) );
+ assertFalse( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "out/blubb" ) ) ) );
}
public void testTargetExecutable_multiple() throws CoreException {
HaskellProject hp = ( HaskellProject )HaskellProjectManager.get( project );
// atm one target exe is added automatically during project creation
- assertEquals( 1, hp.getTargetNames().size() );
+ assertEquals( 1, hp.getTargets().size() );
- IPath path = new Path( "bin/bli.exe" );
- IPath path2 = new Path( "bla.exe" );
+ IPath path = new Path( "bli" );
+ IPath path2 = new Path( "sub/bla" );
InputStream is = new ByteArrayInputStream( new byte[ 0 ] );
- project.getFolder( "bin" ).create( true, true, null );
- project.getFile( path ).create( is, true, null );
- project.getFile( path2 ).create( is, true, null );
- hp.addTargetName( path );
- hp.addTargetName( path2 );
- assertEquals( 3, hp.getTargetNames().size() );
-
- assertTrue( ResourceUtil.isProjectExecutable( project.getFile( "bla.exe" ) ) );
- assertTrue( ResourceUtil.isProjectExecutable( project.getFile( "bin/bli.exe" ) ) );
- assertFalse( ResourceUtil.isProjectExecutable( project.getFile( "blubb.exe" ) ) );
+ IFolder out = project.getFolder( "out" );
+ out.getFolder( "sub" ).create( true, true, null );
+ out.getFile( ResourceUtil.executableName( path ) ).create( is, true, null );
+ out.getFile( ResourceUtil.executableName( path2 ) ).create( is, true, null );
+ hp.addTarget( new ExecutableBuildTarget( path, "Main.main" ) );
+ hp.addTarget( new ExecutableBuildTarget( path2, "Main.main" ) );
+ assertEquals( 3, hp.getTargets().size() );
+
+ assertTrue( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "out/bli" ) ) ) );
+ assertTrue( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "out/sub/bla" ) ) ) );
+ assertFalse( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "bli" ) ) ) );
+ assertFalse( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "out/sub/bli" ) ) ) );
+ assertFalse( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "bla" ) ) ) );
+ assertFalse( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "out/bla" ) ) ) );
+ assertFalse( ResourceUtil.isProjectExecutable( project.getFile( ResourceUtil.executableName( "out/blubb" ) ) ) );
}
}
View
1  ...ell.core.test/src/net/sf/eclipsefp/haskell/core/internal/project/TestHaskellProjectMetaTest_PDETest.java
@@ -56,6 +56,7 @@ public void testUsesDefaultCompiler() throws CoreException {
TestHaskellProject project = new TestHaskellProject("yet-another-project", getCorePrefs());
IHaskellProject hsprj = HaskellProjectManager.get(getProject("yet-another-project"));
+ // TODO TtC this fails, but will soon be unnecessary with the new Build Configuration architecture
assertEquals(DefaultHaskellCompiler.class, hsprj.getCompiler().getClass());
project.destroy();
View
5 ...sf.eclipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/internal/util/ResourceUtil_PDETest.java
@@ -4,6 +4,7 @@
import net.sf.eclipsefp.haskell.core.test.TestCaseWithProject;
import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.Path;
public class ResourceUtil_PDETest extends TestCaseWithProject {
@@ -17,7 +18,7 @@ public void testExtractModuleNameFromLiterateFileName() {
public void testGetSourceDirRelativeName() throws Exception {
HaskellProject hp = new HaskellProject( project );
- hp.addSourcePath( "src" );
+ hp.addSourcePath( new Path( "src" ) );
IFile file = null;
try {
@@ -47,7 +48,7 @@ public void testGetSourceDirRelativeName() throws Exception {
// expected
}
- hp.addSourcePath( "test" );
+ hp.addSourcePath( new Path( "test" ) );
file = project.getFile( "test/Path/A.hs" );
assertEquals( "Path/A.hs",
ResourceUtil.getSourceDirRelativeName( file, hp ) );
View
3  net.sf.eclipsefp.haskell.core.test/src/net/sf/eclipsefp/haskell/core/internal/util/TestHaskellProject.java
@@ -36,7 +36,8 @@ private void setPreferences(final IEclipsePreferences corePrefs) {
corePrefs.put( SELECTED_COMPILER, "null" );
corePrefs.put( FOLDERS_SRC, "src" );
corePrefs.put( FOLDERS_OUT, "out" );
- corePrefs.put( TARGET_BINARY, "bin/theResult" );
+ corePrefs.put( FOLDERS_BUILD, "build" );
+ corePrefs.put( TARGET_BINARY, "theResult" );
corePrefs.putBoolean( FOLDERS_IN_NEW_PROJECT, true );
}
View
13 ...haskell.core.test/src/net/sf/eclipsefp/haskell/core/project/HaskellProjectCreationOperation_PDETest.java
@@ -38,12 +38,14 @@ public void testCreatesDirectoriesFromPreferences()
throws InvocationTargetException, InterruptedException {
getCorePrefs().put( ICorePreferenceNames.FOLDERS_SRC, "customSrc" );
getCorePrefs().put( ICorePreferenceNames.FOLDERS_OUT, "customOut" );
+ getCorePrefs().put( ICorePreferenceNames.FOLDERS_BUILD, "customBuild" );
runOperation();
IProject prj = getWorkspaceRoot().getProject( PROJECT_NAME );
assertValid( prj.getFolder( "customSrc" ) );
assertValid( prj.getFolder( "customOut" ) );
+ assertValid( prj.getFolder( "customBuild" ) );
}
public void testCreatesDescriptorFile() throws InvocationTargetException,
@@ -59,17 +61,17 @@ public void testCreatesDescriptorFile() throws InvocationTargetException,
public void testSetsUpProjectFoldersFromPreferences() throws Exception {
getCorePrefs().put( ICorePreferenceNames.FOLDERS_SRC, "mySrc" );
- getCorePrefs().put( ICorePreferenceNames.FOLDERS_OUT, "myOut" );
+ getCorePrefs().put( ICorePreferenceNames.FOLDERS_OUT, "myOut" );
+ getCorePrefs().put( ICorePreferenceNames.FOLDERS_BUILD, "myBuild" );
getCorePrefs().put( ICorePreferenceNames.TARGET_BINARY, "myBinary" );
getCorePrefs().put( ICorePreferenceNames.SELECTED_COMPILER, "null" );
runOperation();
+ // TODO TtC currently broken; create mock IHaskellProject that returns the right values
IProject prj = getWorkspaceRoot().getProject( PROJECT_NAME );
IFile f = prj.getFile( HaskellProjectManager.HASKELL_PROJECT_DESCRIPTOR );
- final String expectedContents = HaskellProjectManager
- .createDescriptorContent( "mySrc", "myOut", "myBinary", "null" );
+ final String expectedContents = ""; // HaskellProjectManager.createDescriptorContent( "mySrc", "myOut", "myBin", "myBinary", "null" );
assertEquals( expectedContents, readContents( f ) );
-
}
public void testDoNotCreateFoldersWhenPreferenceDisabled() throws Exception {
@@ -84,7 +86,8 @@ public void testDoNotCreateFoldersWhenPreferenceDisabled() throws Exception {
IFile f = prj.getFile( HaskellProjectManager.HASKELL_PROJECT_DESCRIPTOR );
assertValid( f );
- assertEquals( "", readContents( f ) );
+ // Why would this be empty? -- TtC
+ // assertEquals( "", readContents( f ) );
}
View
23 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/BuildTarget.java
@@ -0,0 +1,23 @@
+package net.sf.eclipsefp.haskell.core.internal.project;
+
+import net.sf.eclipsefp.haskell.core.project.IBuildTarget;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * The canonical implementation of {@link IBuildTarget}.
+ *
+ * @author Thomas ten Cate
+ */
+public abstract class BuildTarget implements IBuildTarget {
+
+ private final IPath path;
+
+ public BuildTarget(final IPath path) {
+ this.path = path;
+ }
+
+ public IPath getPath() {
+ return path;
+ }
+
+}
View
2  net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/CabalBuilder.java
@@ -39,7 +39,7 @@
////////////////////
private void checkCabalFile() throws CoreException {
- // TODO replace by something not Cohatoe-based
+ // TODO TtC replace by something not Cohatoe-based
/*
if( getCabalFile().exists() ) {
CohatoeServer server = CohatoeServer.getInstance();
View
166 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/DescriptorFile.java
@@ -1,6 +1,20 @@
// Copyright (c) 2003-2008 by Leif Frenzel - see http://leiffrenzel.de
package net.sf.eclipsefp.haskell.core.internal.project;
+import java.io.StringWriter;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
+import net.sf.eclipsefp.haskell.core.project.IBuildTarget;
+import net.sf.eclipsefp.haskell.core.project.IHaskellProject;
+import org.eclipse.core.runtime.IPath;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
/**
* <p>
* contains naming constants and default XML generator functionality for the
@@ -9,32 +23,16 @@
* </p>
*
* @author Leif Frenzel
+ * @author Thomas ten Cate
*/
public class DescriptorFile implements IXMLNames {
- private static final String OPEN_TAG = "<haskellProject>"; //$NON-NLS-1$
-
- private static final String CLOSE_TAG = "</haskellProject>"; //$NON-NLS-1$
-
- private static final String XML_PREFIX = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$
-
- private static final String NL = "\n"; //$NON-NLS-1$
+ private final IHaskellProject project;
- private static final String INDENT = " "; //$NON-NLS-1$
+ private Document document; // used while building
- private String fSourcePath;
- private String fOutputPath;
- private String fTargetName;
- private final String fCompiler;
-
- DescriptorFile(final String sourcePath, final String outputPath,
- final String targetName,
- final String compiler)
- {
- fSourcePath = sourcePath;
- fOutputPath = outputPath;
- fTargetName = targetName;
- fCompiler = compiler;
+ public DescriptorFile(final IHaskellProject haskellProject) {
+ project = haskellProject;
}
/**
@@ -43,64 +41,82 @@
* write it to the .hsproject file.
* </p>
*/
- String toXML() {
- StringBuffer result = new StringBuffer( XML_PREFIX );
- result.append( NL );
- result.append( OPEN_TAG );
- result.append( NL );
-
- renderTag( result, SOURCE_PATH_ELEMENT, PATH_ATT, fSourcePath );
- renderTag( result, OUTPUT_PATH_ELEMENT, PATH_ATT, fOutputPath );
- renderTag( result, TARGET_NAME_ELEMENT, NAME_ATT, fTargetName );
- result.append( "<" ); //$NON-NLS-1$
- result.append( COMPILER_ELEMENT );
- result.append( ">" ); //$NON-NLS-1$
- result.append( fCompiler );
- result.append( "</" ); //$NON-NLS-1$
- result.append( COMPILER_ELEMENT );
- result.append( ">" ); //$NON-NLS-1$
-
- result.append( CLOSE_TAG );
- result.append( NL );
- return result.toString();
- }
-
- void setSourcePath( final String sourcePath ) {
- fSourcePath = sourcePath;
+ public String toXMLString() {
+ DOMSource source = new DOMSource(toXML());
+ StringWriter stringWriter = new StringWriter();
+ StreamResult result = new StreamResult(stringWriter);
+ try {
+ TransformerFactory.newInstance().newTransformer().transform( source, result );
+ } catch( Exception ex ) {
+ HaskellCorePlugin.log( ex );
+ return null;
+ }
+ return stringWriter.toString();
}
- void setOutputPath( final String outputPath ) {
- fOutputPath = outputPath;
- }
+ public Document toXML() {
+ DocumentBuilder documentBuilder;
+ try {
+ documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ } catch( ParserConfigurationException e ) {
+ HaskellCorePlugin.log( e );
+ return null;
+ }
+
+ document = documentBuilder.newDocument();
+ Element root = document.createElement( DOCUMENT_ELEMENT );
+ document.appendChild( root );
+
+ if (project.getCabalFile() != null) {
+ createCabalProjectElement(root);
+ } else {
+ createSimpleProjectElement(root);
+ }
+
+ // TODO TtC replace this by Build Configurations
+// Element compilerElement = addChild( root, COMPILER_ELEMENT );
+// compilerElement.setTextContent( CompilerManager.getInstance().getCompilerName( project.getCompiler().getClass().getName() ) );
+
+ return document;
+ }
- void setTargetName( final String targetName ) {
- fTargetName = targetName;
- }
+ protected void createCabalProjectElement(final Element documentElement) {
+ Element cabalProjectElement = addChild( documentElement, CABAL_PROJECT_ELEMENT );
+ cabalProjectElement.setTextContent( project.getCabalFile().getProjectRelativePath().toPortableString() );
+ }
- public static String createDescriptorContent( final String sourcePath,
- final String outputPath, final String targetName,
- final String compiler ) {
- return new DescriptorFile( sourcePath, outputPath, targetName,
- compiler ).toXML();
- }
+ protected void createSimpleProjectElement(final Element documentElement) {
+ Element simpleProjectElement = addChild( documentElement, SIMPLE_PROJECT_ELEMENT );
+
+ Element sourcePathsElement = addChild( simpleProjectElement, SOURCE_PATHS_ELEMENT );
+ for (IPath path : project.getSourcePaths()) {
+ Element pathElement = addChild( sourcePathsElement, PATH_ELEMENT);
+ pathElement.setTextContent( path.toPortableString() );
+ }
+
+ Element binPathElement = addChild( simpleProjectElement, BIN_PATH_ELEMENT );
+ binPathElement.setTextContent( project.getBuildPath().toPortableString() );
+
+ Element outputPathElement = addChild( simpleProjectElement, OUTPUT_PATH_ELEMENT );
+ outputPathElement.setTextContent( project.getOutputPath().toPortableString() );
+
+ Element targetsElement = addChild( simpleProjectElement, TARGETS_ELEMENT );
+ for (IBuildTarget target : project.getTargets()) {
+ if (target instanceof IExecutableBuildTarget) {
+ IExecutableBuildTarget executableTarget = (IExecutableBuildTarget)target;
+ Element executableTargetElement = addChild(targetsElement, EXECUTABLE_TARGET_ELEMENT);
+ addChild( executableTargetElement, PATH_ELEMENT ).setTextContent( executableTarget.getPath().toPortableString() );
+ addChild( executableTargetElement, MAIN_ELEMENT ).setTextContent( executableTarget.getMain() );
+ } else {
+ // TODO TtC libraries
+ }
+ }
+ }
- public static String createEmptyDescriptorContent() {
- return createDescriptorContent( "", "", "", "" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- }
+ protected Element addChild( final Element parent, final String childName ) {
+ Element child = document.createElement( childName );
+ parent.appendChild( child );
+ return child;
+ }
- // helping methods
- // ////////////////
-
- private void renderTag( final StringBuffer result, final String tagName,
- final String attName, final String value ) {
- result.append( INDENT );
- result.append( "<" ); //$NON-NLS-1$
- result.append( tagName );
- result.append( " " ); //$NON-NLS-1$
- result.append( attName );
- result.append( "=\"" ); //$NON-NLS-1$
- result.append( value );
- result.append( "\"/>" ); //$NON-NLS-1$
- result.append( NL );
- }
}
View
31 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/DescriptorFileInfo.java
@@ -1,31 +0,0 @@
-// Copyright (c) 2003-2008 by Leif Frenzel - see http://leiffrenzel.de
-package net.sf.eclipsefp.haskell.core.internal.project;
-
-/** <p>Encapsulates information about and contents of the descriptor file
- * that is created in the project. FP Projects store informations like
- * path settings etc. in these descriptor files.</p>
- *
- * @author Leif Frenzel
- */
-public class DescriptorFileInfo {
-
- private final String name;
- private final String content;
-
- public DescriptorFileInfo( final String name, final String content ) {
- this.name = name;
- this.content = content;
- }
-
-
- // getters
- //////////
-
- String getName() {
- return name;
- }
-
- String getContent() {
- return content;
- }
-}
View
25 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/ExecutableBuildTarget.java
@@ -0,0 +1,25 @@
+package net.sf.eclipsefp.haskell.core.internal.project;
+
+import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
+import org.eclipse.core.runtime.IPath;
+
+
+public class ExecutableBuildTarget extends BuildTarget implements
+ IExecutableBuildTarget {
+
+ private final String main;
+
+ public ExecutableBuildTarget( final IPath path, final String main ) {
+ super( path );
+ this.main = main;
+ }
+
+ public IPath getPlatformPath() {
+ return ResourceUtil.executableName( getPath() );
+ }
+
+ public String getMain() {
+ return main;
+ }
+
+}
View
106 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/HaskellProject.java
@@ -1,20 +1,24 @@
// Copyright (c) 2003-2008 by Leif Frenzel - see http://leiffrenzel.de
package net.sf.eclipsefp.haskell.core.internal.project;
-import java.util.Collections;
-import java.util.HashSet;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
import java.util.Set;
+import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
import net.sf.eclipsefp.haskell.core.compiler.CompilerManager;
import net.sf.eclipsefp.haskell.core.compiler.DefaultHaskellCompiler;
import net.sf.eclipsefp.haskell.core.compiler.IHaskellCompiler;
import net.sf.eclipsefp.haskell.core.project.HaskellProjectManager;
+import net.sf.eclipsefp.haskell.core.project.IBuildTarget;
import net.sf.eclipsefp.haskell.core.project.IHaskellProject;
+import net.sf.eclipsefp.haskell.core.project.IHaskellProjectInfo;
import net.sf.eclipsefp.haskell.core.project.IImportLibrary;
import net.sf.eclipsefp.haskell.core.project.ImportLibrariesList;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
/**
@@ -26,18 +30,18 @@
*
* @author Leif Frenzel
*/
-public final class HaskellProject implements IHaskellProject {
+public final class HaskellProject implements IHaskellProject, IHaskellProjectInfo {
private final IProject project;
- private final Set<IPath> sourcePaths = new HashSet<IPath>();
- private final Set<IPath> targetNames = new HashSet<IPath>();
- private String outputPath = ""; //$NON-NLS-1$
- private final String binPath = ""; //$NON-NLS-1$
+ private IFile cabalFile;
+ private final IHaskellProjectInfo projectInfo;
private IHaskellCompiler compiler;
public HaskellProject( final IProject project ) {
compiler = CompilerManager.getInstance().getCompiler();
this.project = project;
+ this.cabalFile = null;
+ this.projectInfo = new SimpleHaskellProjectInfo();
}
@@ -48,20 +52,30 @@ public IProject getResource() {
return project;
}
+ public IFile getCabalFile() {
+ // TODO TtC implement IHaskellProjectInfo that reads from a Cabal file
+ return cabalFile;
+ }
+
+ public void setCabalFile(final IFile file) {
+ // TODO TtC implement IHaskellProjectInfo that reads from a Cabal file
+ cabalFile = file;
+ }
+
public Set<IPath> getSourcePaths() {
- return Collections.unmodifiableSet( sourcePaths );
+ return projectInfo.getSourcePaths();
}
- public Set<IPath> getTargetNames() {
- return Collections.unmodifiableSet( targetNames );
+ public Set<IBuildTarget> getTargets() {
+ return projectInfo.getTargets();
}
public IPath getOutputPath() {
- return getProjectRelativePath(outputPath);
+ return projectInfo.getOutputPath();
}
- public IPath getBinPath() {
- return getProjectRelativePath(binPath);
+ public IPath getBuildPath() {
+ return projectInfo.getBuildPath();
}
public IImportLibrary[] getImportLibraries() {
@@ -83,40 +97,58 @@ public Object getAdapter( final Class required ) {
// internal setters
// /////////////////
- public void addSourcePath( final String sourcePath ) {
- check( sourcePath );
-
+ public void addSourcePath( final IPath sourcePath ) {
String name = IHaskellProject.PROPERTY_SOURCE_PATH;
ProjectPropertiesEvent event = new ProjectPropertiesEvent( this, name );
event.setOldValue( getSourcePaths() );
- sourcePaths.add( getProjectRelativePath( sourcePath ) );
+ projectInfo.addSourcePath( sourcePath );
event.setNewValue( getSourcePaths() );
HaskellProjectManager.broadcast( event );
}
- public void setOutputPath( final String outputPath ) {
- check( outputPath );
-
+ public void setOutputPath( final IPath outputPath ) {
String name = IHaskellProject.PROPERTY_OUTPUT_PATH;
ProjectPropertiesEvent event = new ProjectPropertiesEvent( this, name );
event.setOldValue( getOutputPath() );
- this.outputPath = outputPath;
+ projectInfo.setOutputPath( outputPath );
event.setNewValue( getOutputPath() );
HaskellProjectManager.broadcast( event );
}
- public void addTargetName( final IPath targetName ) {
- String name = IHaskellProject.PROPERTY_TARGET_NAME;
+ public void setBuildPath( final IPath binPath ) {
+ String name = IHaskellProject.PROPERTY_BIN_PATH;
+ ProjectPropertiesEvent event = new ProjectPropertiesEvent( this, name );
+ event.setOldValue( getBuildPath() );
+
+ projectInfo.setBuildPath( binPath );
+
+ event.setNewValue( getBuildPath() );
+ HaskellProjectManager.broadcast( event );
+ }
+
+ public void addTarget( final IBuildTarget target ) {
+ String name = IHaskellProject.PROPERTY_TARGET;
ProjectPropertiesEvent event = new ProjectPropertiesEvent( this, name );
- event.setOldValue( getTargetNames() );
+ event.setOldValue( getTargets() );
- targetNames.add( targetName );
+ projectInfo.addTarget( target );
- event.setNewValue( getTargetNames() );
+ event.setNewValue( getTargets() );
+ HaskellProjectManager.broadcast( event );
+ }
+
+ public void removeTarget( final IBuildTarget target ) {
+ String name = IHaskellProject.PROPERTY_TARGET;
+ ProjectPropertiesEvent event = new ProjectPropertiesEvent( this, name );
+ event.setOldValue( getTargets() );
+
+ projectInfo.removeTarget( target );
+
+ event.setNewValue( getTargets() );
HaskellProjectManager.broadcast( event );
}
@@ -143,10 +175,25 @@ public void compile( final IFile file ) {
getCompiler().compile( file );
}
+ public void saveDescriptor() {
+ try {
+ DescriptorFile descriptor = new DescriptorFile( this );
+ byte[] contents = descriptor.toXMLString().getBytes();
+ InputStream is = new ByteArrayInputStream( contents );
+ getResource().getFile( HaskellProjectManager.HASKELL_PROJECT_DESCRIPTOR ).create( is, true, null );
+ } catch( CoreException ex ) {
+ HaskellCorePlugin.log( ex );
+ }
+ }
+
// helping methods
///////////////////
- private IPath getProjectRelativePath( final String whichPath ) {
+ /**
+ * Returns an {@link IPath} that represents the given path,
+ * relative to the project root.
+ */
+ public IPath getProjectRelativePath( final String whichPath ) {
IPath result;
if( "".equals( whichPath ) ) { //$NON-NLS-1$
result = project.getProjectRelativePath();
@@ -156,9 +203,4 @@ private IPath getProjectRelativePath( final String whichPath ) {
return result;
}
- private void check( final String candidate ) {
- if( candidate == null ) {
- throw new IllegalArgumentException();
- }
- }
}
View
18 ...sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/IExecutableBuildTarget.java
@@ -0,0 +1,18 @@
+package net.sf.eclipsefp.haskell.core.internal.project;
+
+import net.sf.eclipsefp.haskell.core.project.IBuildTarget;
+
+/**
+ * A build target that is an executable file.
+ *
+ * @author Thomas ten Cate
+ */
+public interface IExecutableBuildTarget extends IBuildTarget {
+
+ /**
+ * Returns the fully qualified name of the main function,
+ * for example "Main.main".
+ */
+ public String getMain();
+
+}
View
25 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/IXMLNames.java
@@ -8,22 +8,25 @@
*/
interface IXMLNames {
- public static final String COMPILER_ELEMENT = "compiler"; //$NON-NLS-1$
+ String COMPILER_ELEMENT = "compiler"; //$NON-NLS-1$
/** <p>the single root element of the XML hierarchy in
* <code>.hsproject</code> files.</p> */
String DOCUMENT_ELEMENT = "haskellProject"; //$NON-NLS-1$
+ /** <p>the element in the <code>.hsproject</code> file that names the
+ * simple project information node.</p> */
+ String SIMPLE_PROJECT_ELEMENT = "simpleProject"; //$NON-NLS-1$
+ String CABAL_PROJECT_ELEMENT = "cabalProject"; //$NON-NLS-1$
/** <p>the element in the <code>.hsproject</code> file that names the source
- * path of the project.</p> */
- String SOURCE_PATH_ELEMENT = "sourcePath"; //$NON-NLS-1$
+ * paths of the project.</p> */
+ String SOURCE_PATHS_ELEMENT = "sourcePaths"; //$NON-NLS-1$
/** <p>the element in the <code>.hsproject</code> file that names the output
* path of the project.</p> */
String OUTPUT_PATH_ELEMENT = "outputPath"; //$NON-NLS-1$
- /** <p>the element in the <code>.hsproject</code> file that names the target
- * binary name of the project.</p> */
- String TARGET_NAME_ELEMENT = "targetBinary"; //$NON-NLS-1$
-
- /** <p>The 'name' attribute.</p> */
- String NAME_ATT = "name"; //$NON-NLS-1$
- /** <p>The 'path' attribute.</p> */
- String PATH_ATT = "path"; //$NON-NLS-1$
+ /** <p>the element in the <code>.hsproject</code> file that names the targets
+ * of the project.</p> */
+ String BIN_PATH_ELEMENT = "binPath"; //$NON-NLS-1$
+ String TARGETS_ELEMENT = "targets"; //$NON-NLS-1$
+ String PATH_ELEMENT = "path"; //$NON-NLS-1$
+ String EXECUTABLE_TARGET_ELEMENT = "executableTarget"; //$NON-NLS-1$
+ String MAIN_ELEMENT = "main"; //$NON-NLS-1$
}
View
150 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/Parser.java
@@ -7,9 +7,9 @@
import javax.xml.parsers.DocumentBuilderFactory;
import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
@@ -24,8 +24,15 @@
*/
public class Parser implements IXMLNames {
- public static void readIn(final IFile projectDescriptor,
- final HaskellProject project)
+ private final IFile projectDescriptor;
+ private final HaskellProject project;
+
+ public Parser(final IFile projectDescriptor, final HaskellProject project) {
+ this.projectDescriptor = projectDescriptor;
+ this.project = project;
+ }
+
+ public void read()
{
try {
Reader reader = new InputStreamReader(projectDescriptor
@@ -42,8 +49,11 @@ public static void readIn(final IFile projectDescriptor,
} finally {
reader.close();
}
- applyPaths(project, rootElement);
- setupCompiler(project, rootElement);
+ if (rootElement != null && rootElement.getNodeName().equals(DOCUMENT_ELEMENT)) {
+ applyProjectInfo(rootElement);
+ // TODO TtC replace by BuildConfigurations
+ // setupCompiler(rootElement);
+ }
} catch( Exception ex ) {
String msg = "Problem when reading .hsproject file.\n"; //$NON-NLS-1$
HaskellCorePlugin.log( msg, ex );
@@ -53,43 +63,99 @@ public static void readIn(final IFile projectDescriptor,
// helping methods
// ////////////////
- private static void setupCompiler(final HaskellProject project,
- final Element rootElement)
- {
- final NodeList list = rootElement.getElementsByTagName(COMPILER_ELEMENT);
- if (list.getLength() > 0) {
- if ("null".equals(list.item(0).getTextContent())) { //$NON-NLS-1$
- project.setCompiler(null);
- }
- }
- }
+ private void setupCompiler(final Element rootElement)
+ {
+ final NodeList list = rootElement.getElementsByTagName(COMPILER_ELEMENT);
+ if (list.getLength() > 0) {
+ if ("null".equals(list.item(0).getTextContent())) { //$NON-NLS-1$
+ project.setCompiler(null);
+ }
+ }
+ }
- private static String getValue(final Element rootElement,
- final String tagName,
- final String attributeName)
- {
- String result = ""; //$NON-NLS-1$
- NodeList list = rootElement.getElementsByTagName(tagName);
- if (list.getLength() > 0) {
- // we use only the first entry for each path type
- NamedNodeMap attributes = list.item(0).getAttributes();
- Node pathNode = attributes.getNamedItem(attributeName);
- result = pathNode.getNodeValue();
- }
- return result;
- }
+ private void applyProjectInfo(final Element rootElement)
+ {
+ NodeList list = rootElement.getElementsByTagName( CABAL_PROJECT_ELEMENT );
+ if (list.getLength() > 0) {
+ Node projectInfo = list.item( 0 );
+ applyCabalProjectInfo((Element)projectInfo);
+ }
+ list = rootElement.getElementsByTagName( SIMPLE_PROJECT_ELEMENT );
+ if (list.getLength() > 0) {
+ // we use only the first item
+ Node projectInfo = list.item( 0 );
+ applySimpleProjectInfo((Element)projectInfo);
+ return;
+ }
+ }
+
+ private void applyCabalProjectInfo(final Element cabalProjectElement) {
+ IPath path = Path.fromPortableString( cabalProjectElement.getTextContent() );
+ project.setCabalFile( project.getResource().getFile( path ) );
+ }
+
+ private void applySimpleProjectInfo(final Element projectInfoElement) {
+ NodeList children = projectInfoElement.getChildNodes();
+ for (int i = 0; i < children.getLength(); ++i) {
+ if (children.item( i ).getNodeType() == Node.ELEMENT_NODE) {
+ Element el = (Element)children.item( i );
+ String name = el.getNodeName();
+ if (name.equals( SOURCE_PATHS_ELEMENT )) {
+ applySourcePaths(el);
+ } else if (name.equals( OUTPUT_PATH_ELEMENT )) {
+ applyOutputPath(el);
+ } else if (name.equals( BIN_PATH_ELEMENT )) {
+ applyBinPath(el);
+ } else if (name.equals( TARGETS_ELEMENT )) {
+ applyTargets(el);
+ }
+ }
+ }
+ }
+
+ private void applySourcePaths(final Element sourcePathsElement) {
+ NodeList paths = sourcePathsElement.getElementsByTagName( PATH_ELEMENT );
+ for (int i = 0; i < paths.getLength(); ++i) {
+ Element path = (Element) paths.item( i );
+ project.addSourcePath( Path.fromPortableString( path.getTextContent() ) );
+ }
+ }
+
+ private void applyOutputPath(final Element outputPathElement) {
+ project.setOutputPath( Path.fromPortableString( outputPathElement.getTextContent() ) );
+ }
+
+ private void applyBinPath(final Element binPathElement) {
+ project.setBuildPath( Path.fromPortableString( binPathElement.getTextContent() ) );
+ }
+
+ private void applyTargets(final Element targetsElement) {
+ NodeList targets = targetsElement.getChildNodes();
+ for (int i = 0; i < targets.getLength(); ++i) {
+ if (targets.item(i).getNodeType() == Node.ELEMENT_NODE) {
+ Element target = (Element) targets.item( i );
+ String name = target.getNodeName();
+ if (name.equals(EXECUTABLE_TARGET_ELEMENT)) {
+ applyExecutableTarget(target);
+ }
+ }
+ }
+ }
+
+ private void applyExecutableTarget(final Element executableTargetElement) {
+ String path = getValue(executableTargetElement, PATH_ELEMENT);
+ String main = getValue(executableTargetElement, MAIN_ELEMENT);
+ ExecutableBuildTarget target = new ExecutableBuildTarget( Path.fromPortableString( path ), main );
+ project.addTarget( target );
+ }
+
+ private String getValue(final Element element, final String subElementName) {
+ NodeList list = element.getElementsByTagName(subElementName);
+ if (list.getLength() > 0) {
+ Element subElement = (Element) list.item( 0 );
+ return subElement.getTextContent();
+ }
+ return ""; //$NON-NLS-1$
+ }
- private static void applyPaths(final HaskellProject project,
- final Element rootElement)
- {
- if (rootElement != null
- && rootElement.getNodeName().equalsIgnoreCase(DOCUMENT_ELEMENT)) {
- project.addSourcePath(getValue(rootElement, SOURCE_PATH_ELEMENT,
- PATH_ATT));
- project.setOutputPath(getValue(rootElement, OUTPUT_PATH_ELEMENT,
- PATH_ATT));
- project.addTargetName( new Path( getValue(rootElement, TARGET_NAME_ELEMENT,
- NAME_ATT)));
- }
- }
}
View
31 ....eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/ProjectCreationOperation.java
@@ -3,11 +3,9 @@
// version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
package net.sf.eclipsefp.haskell.core.internal.project;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
import net.sf.eclipsefp.haskell.core.internal.util.CoreTexts;
-import org.eclipse.core.resources.IFile;
+import net.sf.eclipsefp.haskell.core.project.IHaskellProject;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
@@ -55,7 +53,7 @@ public void run( final IProgressMonitor monitor ) throws CoreException {
createDirectories( monitor, project );
monitor.subTask( CoreTexts.projectCreationOperation_settings );
- createDescriptionFile( monitor, project );
+ createNatureProject( monitor, project );
executeExtraOperation( monitor, project );
}
};
@@ -145,15 +143,6 @@ private void addNatures( final IProgressMonitor mon, final IProject project )
return new String[0];
}
- /**
- * Returns an object describing the project descriptor file
- *
- * This method should be overriden by clients.
- */
- protected DescriptorFileInfo getDescFileInfo() {
- return null;
- }
-
private void createDirectories(final IProgressMonitor mon,
final IProject proj) throws CoreException {
String[] directories = getDirectories();
@@ -165,15 +154,13 @@ private void createDirectories(final IProgressMonitor mon,
}
}
- private void createDescriptionFile(final IProgressMonitor monitor,
- final IProject project) throws CoreException {
- DescriptorFileInfo descFileInfo = getDescFileInfo();
- if (descFileInfo != null && !"".equals(descFileInfo.getName())) { //$NON-NLS-1$
- IFile file = project.getFile(descFileInfo.getName());
- String content = descFileInfo.getContent();
- InputStream is = new ByteArrayInputStream(content.getBytes());
- file.create(is, true, new SubProgressMonitor(monitor, 1));
- }
+ /**
+ * Creates the nature-specific project descriptor, e.g. an {@link IHaskellProject}.
+ * @param monitor the progress monitor
+ * @param project the project
+ */
+ protected void createNatureProject(final IProgressMonitor monitor, final IProject project) {
+ // subclasses can implement
}
protected void executeExtraOperation(
View
70 ....eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/internal/project/SimpleHaskellProjectInfo.java
@@ -0,0 +1,70 @@
+package net.sf.eclipsefp.haskell.core.internal.project;
+
+import java.util.HashSet;
+import java.util.Set;
+import net.sf.eclipsefp.haskell.core.project.IBuildTarget;
+import net.sf.eclipsefp.haskell.core.project.IHaskellProjectInfo;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * A {@link IHaskellProjectInfo} without a Cabal file.
+ * Writes the information to the .hsproject file.
+ *
+ * @author Thomas ten Cate
+ */
+public class SimpleHaskellProjectInfo implements IHaskellProjectInfo {
+
+ // TODO TtC read from settings
+ private final Set<IPath> sourcePaths = new HashSet<IPath>();
+ private final Set<IBuildTarget> targets = new HashSet<IBuildTarget>();
+ private IPath outputPath = Path.fromPortableString( "out" ); //$NON-NLS-1$
+ private IPath binPath = Path.fromPortableString( "bin" ); //$NON-NLS-1$
+
+ public void addSourcePath( final IPath path ) {
+ check( path );
+ sourcePaths.add( path );
+ }
+
+ public void addTarget( final IBuildTarget target ) {
+ check( target );
+ targets.add( target );
+ }
+
+ public void removeTarget( final IBuildTarget target ) {
+ check( target );
+ targets.remove( target );
+ }
+
+ public IPath getBuildPath() {
+ return binPath;
+ }
+
+ public IPath getOutputPath() {
+ return outputPath;
+ }
+
+ public Set<IPath> getSourcePaths() {
+ return new HashSet<IPath>( sourcePaths );
+ }
+
+ public Set<IBuildTarget> getTargets() {
+ return new HashSet<IBuildTarget>( targets );
+ }
+
+ public void setBuildPath( final IPath path ) {
+ check( path );
+ binPath = path;
+ }
+
+ public void setOutputPath( final IPath path ) {
+ check( path );
+ outputPath = path;
+ }
+
+ private void check( final Object candidate ) {
+ if( candidate == null ) {
+ throw new IllegalArgumentException();
+ }
+ }
+}
View
3  net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/CorePreferenceInitializer.java
@@ -25,7 +25,8 @@ public void initializeDefaultPreferences() {
coreNode.put( SELECTED_COMPILER, "ghcCompiler" ); //$NON-NLS-1$
coreNode.put( FOLDERS_SRC, "src" ); //$NON-NLS-1$
coreNode.put( FOLDERS_OUT, "out" ); //$NON-NLS-1$
- coreNode.put( TARGET_BINARY, "bin/theResult" ); //$NON-NLS-1$
+ coreNode.put( FOLDERS_BUILD, "build" ); //$NON-NLS-1$
+ coreNode.put( TARGET_BINARY, "theResult" ); //$NON-NLS-1$
coreNode.putBoolean( FOLDERS_IN_NEW_PROJECT, true );
}
View
1  net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/preferences/ICorePreferenceNames.java
@@ -16,6 +16,7 @@
// new Haskell project
String TARGET_BINARY = "TARGET_BINARY"; //$NON-NLS-1$
String FOLDERS_SRC = "FOLDERS_SRC"; //$NON-NLS-1$
+ String FOLDERS_BUILD = "FOLDERS_BUILD"; //$NON-NLS-1$
String FOLDERS_OUT = "FOLDERS_OUT"; //$NON-NLS-1$
String FOLDERS_IN_NEW_PROJECT = "FOLDERS_IN_NEW_PROJECT"; //$NON-NLS-1$
View
52 ...sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/HaskellProjectCreationOperation.java
@@ -1,11 +1,13 @@
package net.sf.eclipsefp.haskell.core.project;
import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
-import net.sf.eclipsefp.haskell.core.internal.project.DescriptorFileInfo;
+import net.sf.eclipsefp.haskell.core.internal.project.ExecutableBuildTarget;
import net.sf.eclipsefp.haskell.core.internal.project.ProjectCreationOperation;
import net.sf.eclipsefp.haskell.core.preferences.ICorePreferenceNames;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.preferences.IPreferencesService;
public class HaskellProjectCreationOperation extends ProjectCreationOperation {
@@ -23,33 +25,37 @@ public HaskellProjectCreationOperation() {
if (! createFolders() ) {
return new String[0];
}
- IPreferencesService service = Platform.getPreferencesService();
- String sourcePath = service.getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.FOLDERS_SRC, null, null );
- String outputPath = service.getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.FOLDERS_OUT, null, null );
- return new String[] { sourcePath, outputPath };
+ return new String[] { getDefaultSourcePath(), getDefaultBuildPath(), getDefaultOutputPath() };
}
- @Override
- protected DescriptorFileInfo getDescFileInfo() {
- return new DescriptorFileInfo(
- HaskellProjectManager.HASKELL_PROJECT_DESCRIPTOR,
- createDescriptorContent());
+ private boolean createFolders() {
+ return Platform.getPreferencesService().getBoolean( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.FOLDERS_IN_NEW_PROJECT, false, null );
}
- private String createDescriptorContent() {
- if (! createFolders() ) {
- return ""; //$NON-NLS-1$
- }
- IPreferencesService service = Platform.getPreferencesService();
- return HaskellProjectManager.createDescriptorContent(
- service.getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.FOLDERS_SRC, null, null ),
- service.getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.FOLDERS_OUT, null, null ),
- service.getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.TARGET_BINARY, null, null ),
- service.getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.SELECTED_COMPILER, null, null ));
+ private String getDefaultSourcePath() {
+ return Platform.getPreferencesService().getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.FOLDERS_SRC, null, null );
}
- private boolean createFolders() {
- return Platform.getPreferencesService().getBoolean( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.FOLDERS_IN_NEW_PROJECT, false, null );
+ private String getDefaultOutputPath() {
+ return Platform.getPreferencesService().getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.FOLDERS_OUT, null, null );
}
+ private String getDefaultBuildPath() {
+ return Platform.getPreferencesService().getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.FOLDERS_BUILD, null, null );
+ }
+
+ private String getDefaultTarget() {
+ return Platform.getPreferencesService().getString( HaskellCorePlugin.getPluginId(), ICorePreferenceNames.TARGET_BINARY, null, null );
+ }
+
+ @Override
+ protected void createNatureProject( final IProgressMonitor monitor, final IProject project ) {
+ IHaskellProject hsProject = HaskellProjectManager.get( project );
+ hsProject.addSourcePath( Path.fromPortableString( getDefaultSourcePath() ) );
+ hsProject.setOutputPath( Path.fromPortableString( getDefaultOutputPath() ) );
+ hsProject.setBuildPath( Path.fromPortableString( getDefaultBuildPath() ) );
+ hsProject.addTarget( new ExecutableBuildTarget( Path.fromPortableString( getDefaultTarget() ), "Main.main" ) ); //$NON-NLS-1$
+ hsProject.saveDescriptor();
+ }
+
}
View
48 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/HaskellProjectManager.java
@@ -1,27 +1,19 @@
// Copyright (c) 2003-2005 by Leif Frenzel - see http://leiffrenzel.de
package net.sf.eclipsefp.haskell.core.project;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
-import net.sf.eclipsefp.haskell.core.internal.project.DescriptorFile;
import net.sf.eclipsefp.haskell.core.internal.project.HaskellProject;
import net.sf.eclipsefp.haskell.core.internal.project.Parser;
import net.sf.eclipsefp.haskell.core.internal.util.Assert;
-import net.sf.eclipsefp.haskell.core.internal.util.CoreTexts;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
/** <p>The HaskellProjectManager manages Haskell project specific information
@@ -90,24 +82,6 @@ public static IHaskellProject get( final IProject project ) {
return getInstance().getInternal( project );
}
- /** <p>creates the contents of a project descriptor file with the
- * specified path settings for the project.</p> */
- public static String createDescriptorContent( final String sourcePath,
- final String outputPath,
- final String targetName,
- final String compiler) {
- return DescriptorFile.createDescriptorContent( sourcePath,
- outputPath,
- targetName,
- compiler);
- }
-
- /** <p>creates the content of a project descriptor file with empty path
- * settings.</p> */
- public static String createEmptyDescriptorContent() {
- return DescriptorFile.createEmptyDescriptorContent();
- }
-
/** <p>registers the specified listener for project property changes.</p> */
public static void addProjectPropertiesListener(
final IProjectPropertiesListener listener ) {
@@ -181,28 +155,14 @@ private IHaskellProject getInternal( final IProject project ) {
}
private IHaskellProject createNew( final IFile descFile ) {
- Job job = new Job( CoreTexts.haskellProjectManager_jobName ) {
- @Override
- protected IStatus run( final IProgressMonitor monitor ) {
- IStatus result = Status.OK_STATUS;
- try {
- byte[] contents = createEmptyDescriptorContent().getBytes();
- InputStream is = new ByteArrayInputStream( contents );
- descFile.create( is, true, null );
- } catch( CoreException cex ) {
- result = cex.getStatus();
- }
- return result;
- }
- };
- job.setRule( descFile.getProject() );
- job.schedule();
- return new HaskellProject( descFile.getProject() );
+ IHaskellProject hsProject = new HaskellProject( descFile.getProject() );
+ hsProject.saveDescriptor();
+ return hsProject;
}
private IHaskellProject readFromDescriptor( final IFile descFile ) {
HaskellProject result = new HaskellProject( descFile.getProject() );
- Parser.readIn( descFile, result );
+ new Parser( descFile, result ).read();
return result;
}
View
25 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/IBuildTarget.java
@@ -0,0 +1,25 @@
+package net.sf.eclipsefp.haskell.core.project;
+
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * A build target: either an executable or a library.
+ * Instances must be immutable.
+ *
+ * @author Thomas ten Cate
+ */
+public interface IBuildTarget {
+
+ /**
+ * Returns the path and name of the resulting file,
+ * without extension, relative to the output directory.
+ */
+ public IPath getPath();
+
+ /**
+ * Returns the same as {@link #getPath()}, but with an added
+ * extension on operating systems that require it.
+ */
+ public IPath getPlatformPath();
+
+}
View
31 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/IHaskellProject.java
@@ -1,13 +1,10 @@
// Copyright (c) 2003-2005 by Leif Frenzel - see http://leiffrenzel.de
package net.sf.eclipsefp.haskell.core.project;
-import java.util.Set;
import net.sf.eclipsefp.haskell.core.compiler.IHaskellCompiler;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IPath;
/**
* <p>
@@ -18,11 +15,12 @@
*
* @author Leif Frenzel
*/
-public interface IHaskellProject extends IAdaptable {
+public interface IHaskellProject extends IHaskellProjectInfo {
String PROPERTY_SOURCE_PATH = "sourcePath"; //$NON-NLS-1$
+ String PROPERTY_BIN_PATH = "binPath"; //$NON-NLS-1$
String PROPERTY_OUTPUT_PATH = "outputPath"; //$NON-NLS-1$
- String PROPERTY_TARGET_NAME = "targetName"; //$NON-NLS-1$
+ String PROPERTY_TARGET = "targetName"; //$NON-NLS-1$
String PROPERTY_IMPORT_LIBRARIES = "importLibraries"; //$NON-NLS-1$
/**
@@ -33,22 +31,16 @@
IProject getResource();
/**
- * <p>
- * returns the paths to the source folders of this IHaskellProject.
- * </p>
+ * Returns the Cabal file that this project is based upon,
+ * or <code>null</code> if it is not based on a Cabal file.
*/
- Set<IPath> getSourcePaths();
-
- /** <p>returns the paths to the targets (executables or libs) of this
- * IHaskellProject.</p> */
- Set<IPath> getTargetNames();
+ IFile getCabalFile();
/**
- * <p>
- * returns the path to the output folder of this IHaskellProject.
- * </p>
+ * Sets the Cabal file that this project is based upon.
+ * If set to <code>null</code>, the project turns back into a "simple" project.
*/
- IPath getOutputPath();
+ void setCabalFile(IFile file);
/**
* <p>
@@ -62,4 +54,9 @@
IHaskellCompiler getCompiler();
void compile( IFile file );
+
+ /**
+ * Saves the project to the .hsproject file.
+ */
+ void saveDescriptor();
}
View
67 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/project/IHaskellProjectInfo.java
@@ -0,0 +1,67 @@
+package net.sf.eclipsefp.haskell.core.project;
+
+import java.util.Set;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Represents information about a Haskell project:
+ * source paths, output paths, target binaries, etcetera.
+ * This information is either stored in a Cabal file,
+ * or in the .hsproject file.
+ *
+ * @author Thomas ten Cate
+ *
+ * TODO removal of source paths and targets
+ */
+public interface IHaskellProjectInfo {
+
+ /**
+ * Returns the set of source folders, relative to the project root.
+ */
+ public Set<IPath> getSourcePaths();
+
+ /**
+ * Add a source folder, relative to the project root, to the set of source folders.
+ */
+ public void addSourcePath(IPath path);
+
+ /**
+ * Returns the set of build targets.
+ */
+ public Set<IBuildTarget> getTargets();
+
+ /**
+ * Adds a build target.
+ */
+ public void addTarget(IBuildTarget target);
+
+ /**
+ * Removes a build target.
+ */
+ public void removeTarget(IBuildTarget target);
+
+ /**
+ * Returns the path to which build target binaries should be written,
+ * relative to the project root.
+ */
+ public IPath getOutputPath();
+
+ /**
+ * Sets the path to which intermediate build files should be written,
+ * relative to the project root.
+ */
+ public void setOutputPath(IPath path);
+
+ /**
+ * Returns the path to which intermediate build files should be written,
+ * relative to the project root.
+ */
+ public IPath getBuildPath();
+
+ /**
+ * Sets the path to which intermediate build files should be written,
+ * relative to the project root.
+ */
+ public void setBuildPath(IPath path);
+
+}
View
15 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/util/GHCSyntax.java
@@ -3,7 +3,6 @@
// version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
package net.sf.eclipsefp.haskell.core.util;
-import org.eclipse.core.runtime.Platform;
/** <p>provides public constants for the command line syntax of ghc and ghc-pkg,
* GHCs package management tool.</p>
@@ -20,19 +19,19 @@
* <p>Value is <code>ghc</code>, with the <code>.exe</code> extension
* appended on Windows systems.</p>
*/
- public static final String GHC = makeExe( "ghc" ); //$NON-NLS-1$
+ public static final String GHC = ResourceUtil.executableName( "ghc" ); //$NON-NLS-1$
/** <p>The name of the <code>ghc-pkg</code> executable.</p>
*
* <p>Value is <code>ghc-pkg</code>, with the <code>.exe</code> extension
* appended on Windows systems.</p>
*/
- public static final String GHC_PKG = makeExe( "ghc-pkg" ); //$NON-NLS-1$
+ public static final String GHC_PKG = ResourceUtil.executableName( "ghc-pkg" ); //$NON-NLS-1$
/** <p>The name of the <code>runghc</code> executable.</p>
*
* <p>Value is <code>runghc</code>, with the <code>.exe</code> extension
* appended on Windows systems.</p>
*/
- public static final String RUN_GHC = makeExe( "runghc" ); //$NON-NLS-1$
+ public static final String RUN_GHC = ResourceUtil.executableName( "runghc" ); //$NON-NLS-1$
/** <p>The name of the <code>package.conf</code> file.</p> */
public static final String FILE_PACKAGE_CONF = "package.conf"; //$NON-NLS-1$
@@ -58,12 +57,4 @@
/** <p>The <code>--RTS</code> option.</p> */
public static final String OPT_NO_RTS = "--RTS"; //$NON-NLS-1$
-
- // helping functions
- ////////////////////
-
- private static String makeExe( final String command ) {
- boolean windows = Platform.OS_WIN32.equals( Platform.getOS() );
- return windows ? command + ".exe" : command; //$NON-NLS-1$
- }
}
View
2  net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/util/QueryUtil.java
@@ -13,7 +13,7 @@
* <p>A typical use would be to call a command line tool and ask for its
* version number, like 'java -version'.</p>
*
- * TODO: refactor this to use ProcessRunner (and probably refactor ProcessRunner as well)
+ * TODO TtC refactor this to use ProcessRunner (and probably refactor ProcessRunner as well)
*
* @author Leif Frenzel
*/
View
38 net.sf.eclipsefp.haskell.core/src/net/sf/eclipsefp/haskell/core/util/ResourceUtil.java
@@ -11,9 +11,11 @@
import java.util.List;
import java.util.Set;
import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
+import net.sf.eclipsefp.haskell.core.internal.project.IExecutableBuildTarget;
import net.sf.eclipsefp.haskell.core.internal.util.Assert;
import net.sf.eclipsefp.haskell.core.project.HaskellNature;
import net.sf.eclipsefp.haskell.core.project.HaskellProjectManager;
+import net.sf.eclipsefp.haskell.core.project.IBuildTarget;
import net.sf.eclipsefp.haskell.core.project.IHaskellProject;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -24,6 +26,7 @@
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
/**
* <p>
@@ -61,7 +64,7 @@ public static boolean hasLiterateExtension(final IResource resource) {
/**
* <p>
- * returns the target executable for the passed project as resource. The
+ * returns the target executables for the passed project as resource. The
* project must have the Haskell nature.
* </p>
*/
@@ -71,11 +74,14 @@ public static boolean hasLiterateExtension(final IResource resource) {
List<IFile> result = new ArrayList<IFile>();
IHaskellProject hsProject = HaskellProjectManager.get( project );
- Set<IPath> targetNames = hsProject.getTargetNames();
- for( IPath path: targetNames ) {
- IFile file = project.getFile( path );
- if( file.exists() ) {
- result.add( file );
+ IPath binPath = hsProject.getOutputPath();
+ Set<IBuildTarget> targets = hsProject.getTargets();
+ for( IBuildTarget target: targets ) {
+ if ( target instanceof IExecutableBuildTarget ) {
+ IFile file = project.getFile( binPath.append( target.getPlatformPath() ) );
+ if( file.exists() ) {
+ result.add( file );
+ }
}
}
return result.toArray( new IFile[ result.size() ] );
@@ -263,4 +269,24 @@ private static IHaskellProject getHsProject( final IProject project ) {
public static String getModuleName( final String fileName ) {
return fileName.substring( 0, fileName.lastIndexOf( '.' ) );
}
+
+ /**
+ * Returns the name of an executable corresponding to the given filename.
+ * On Unix, returns the given path without modification.
+ * On Windows, appends the ".exe" extension.
+ * TODO TtC we have the same thing in a FileUtil class somewhere...
+ */
+ public static IPath executableName( final IPath path ) {
+ if ( Platform.OS_WIN32.equals( Platform.getOS() ) ) {
+ return path.addFileExtension( "exe" ); //$NON-NLS-1$
+ }
+ return path;
+ }
+
+ public static String executableName( final String path ) {
+ if ( Platform.OS_WIN32.equals( Platform.getOS() ) ) {
+ return path + ".exe"; //$NON-NLS-1$
+ }
+ return path;
+ }
}
View
8 ...ava/test/net/sf/eclipsefp/haskell/debug/ui/internal/launch/ghci/GhciLaunchOperationDelegate_PDETest.java
@@ -31,7 +31,7 @@ public void testAddSourceFolders_single() throws Exception {
// source folders added by default
HaskellProject hp = new HaskellProject( project );
- hp.addSourcePath( "src" );
+ hp.addSourcePath( new Path( "src" ) );
IFile[] files = new IFile[] { project.getFile( new Path( "src/Bla.hs" ) ) };
GhciLaunchOperationDelegate del = new GhciLaunchOperationDelegate();
@@ -53,8 +53,8 @@ public void testAddSourceFolders_multi() throws Exception {
= putInQuotes( project.getLocation().append( new Path( "bla/src2" ) ) );
HaskellProject hp = new HaskellProject( project );
- hp.addSourcePath( "src" );
- hp.addSourcePath( "bla/src2" );
+ hp.addSourcePath( new Path( "src" ) );
+ hp.addSourcePath( new Path( "bla/src2" ) );
IFile[] files = new IFile[] { project.getFile( new Path( "src/Bla.hs" ) ) };
GhciLaunchOperationDelegate del = new GhciLaunchOperationDelegate();
@@ -67,7 +67,7 @@ public void testAddLinkedSourceFolder() throws Exception {
folder.createLink( new Path( "/bla/lsrc/" ), IResource.ALLOW_MISSING_LOCAL, null );
HaskellProject hp = new HaskellProject( project );
- hp.addSourcePath( "lsrc" );
+ hp.addSourcePath( new Path( "lsrc" ) );
IFile[] files = new IFile[] { project.getFile( new Path( "src/Bla.hs" ) ) };
GhciLaunchOperationDelegate del = new GhciLaunchOperationDelegate();
assertContains( "-i\"/bla/lsrc\"", del.createArguments( hp, files ) );
View
17 net.sf.eclipsefp.haskell.ghccompiler/src/net/sf/eclipsefp/haskell/ghccompiler/core/GhcCompiler.java
@@ -13,6 +13,7 @@
import net.sf.eclipsefp.haskell.core.compiler.DefaultHaskellCompiler;
import net.sf.eclipsefp.haskell.core.internal.util.MultiplexedWriter;
import net.sf.eclipsefp.haskell.core.project.HaskellProjectManager;
+import net.sf.eclipsefp.haskell.core.project.IBuildTarget;
import net.sf.eclipsefp.haskell.core.project.IHaskellProject;
import net.sf.eclipsefp.haskell.core.util.IProcessRunner;
import net.sf.eclipsefp.haskell.core.util.ProcessRunner;
@@ -102,7 +103,7 @@ public void compile( final IFile file, final Writer outputWriter ) {
}
IProject project = haskellProject.getResource();
- String outDir = getAbsPath( project, haskellProject.getOutputPath() );
+ String buildDir = getAbsPath( project, haskellProject.getBuildPath() );
List<String> cmdLine = new ArrayList<String>();
// command and special options
@@ -113,9 +114,9 @@ public void compile( final IFile file, final Writer outputWriter ) {
}
cmdLine.add( "--make" ); //$NON-NLS-1$
cmdLine.add( "-odir" ); //$NON-NLS-1$
- cmdLine.add( outDir );
+ cmdLine.add( buildDir );
cmdLine.add( "-hidir" ); //$NON-NLS-1$
- cmdLine.add( outDir );
+ cmdLine.add( buildDir );
cmdLine.add( "-ferror-spans" ); //$NON-NLS-1$
cmdLine.add( "-o" ); //$NON-NLS-1$
@@ -146,11 +147,13 @@ private String getAbsPath( final IProject project, final IPath path ) {
}
private IPath getTargetName( final IHaskellProject haskellProject ) {
- String result = "theResult"; //$NON-NLS-1$
- Set<IPath> targetNames = haskellProject.getTargetNames();
+ IPath targetPath;
+ Set<IBuildTarget> targetNames = haskellProject.getTargets();
if( targetNames.size() > 0 ) {
- result = targetNames.iterator().next().toOSString();
+ targetPath = targetNames.iterator().next().getPath();
+ } else {
+ targetPath = Path.fromPortableString( "theResult" ); //$NON-NLS-1$
}
- return new Path( result );
+ return haskellProject.getOutputPath().append( targetPath );
}
}
View
2  net.sf.eclipsefp.haskell.ghccompiler/src/net/sf/eclipsefp/haskell/ghccompiler/core/GhcOutputParser.java
@@ -15,7 +15,7 @@
*
* For parsing, the Parsec "grammar" from GHCOutputParser.hs is used.
*
- * TODO this should be an {@link ICompilerListener}, I think.
+ * TODO TtC this should be an {@link ICompilerListener}, I think.
*
* @author Thomas ten Cate
*/
View
2  net.sf.eclipsefp.haskell.scion.client/src/net/sf/eclipsefp/haskell/scion/client/ScionInstance.java
@@ -141,7 +141,7 @@ public void reloadFile(String fileName) {
}
public void unloadFile(String fileName) {
- // TODO Scion has no command for unloading yet!
+ // TODO TtC Scion has no command for unloading yet!
loadedFiles.remove(fileName);
}
View
1  net.sf.eclipsefp.haskell.scion.client/src/net/sf/eclipsefp/haskell/scion/client/ScionPlugin.java
@@ -70,7 +70,6 @@ public static String getStringResource(String key) {
/**
* Returns whether tracing is enabled for the specified option.
- * TODO this is executed for every trace call, even when tracing is off... optimize?
*/
public static boolean isTracing(String optionId) {
String option = getPluginId() + "/" + optionId;
View
2  ...psefp.haskell.scion.client/src/net/sf/eclipsefp/haskell/scion/internal/commands/DefinedNamesCommand.java
@@ -18,7 +18,7 @@ protected String getMethod() {
@Override
protected void doProcessResult(Object result) throws JSONException {
- // TODO
+ // TODO TtC
}
}
View
2  net.sf.eclipsefp.haskell.scion.client/src/net/sf/eclipsefp/haskell/scion/types/Location.java
@@ -20,7 +20,7 @@
private int startLine, startColumn, endLine, endColumn;
public Location(JSONObject json) throws JSONException {
- // TODO this is not the complete syntax
+ // TODO TtC this is not the complete syntax
this.fileName = json.getString("file");
JSONArray region = json.getJSONArray("region");
startLine = region.getInt(0) - 1;
View
BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/executable_obj.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/executablestanza.gif
Deleted file not rendered
View
BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/lambda.gif
Deleted file not rendered
View
BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/library.gif
Deleted file not rendered
View
BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/library_obj.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/librarystanza.gif
Deleted file not rendered
View
BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/projexe.gif
Deleted file not rendered
View
BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/target_obj.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/targets_obj.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
3  net.sf.eclipsefp.haskell.ui/plugin.properties
@@ -60,6 +60,9 @@ openDefinitionCommand_desc = Opens an editor on the definition of the selected e
viewCategory_name = Haskell
projectExecutableFilter_name = Haskell project executables
projectExecutableFilter_desc = Hides the project executable in Haskell projects
+buildTargets_menu_label = Build &Targets
+buildTargets_add_name = &Add...
+buildTargets_add_label = &Add Build Target...
# [Views] particular views
navigatorContent_name = Haskell content
View
63 net.sf.eclipsefp.haskell.ui/plugin.xml
@@ -413,6 +413,69 @@
</viewerContribution>
</extension>
+ <!-- Build Target menu contributions -->
+
+ <extension point="org.eclipse.ui.menus">
+ <menuContribution
+ locationURI="menu:project">
+ <menu
+ label="%buildTargets_menu_label"
+ id="net.sf.eclipsefp.haskell.ui.menu.buildtargets">
+ <command
+ commandId="net.sf.eclipsefp.haskell.ui.buildtargets.add"
+ style="push">
+ </command>
+ </menu>
+ </menuContribution>
+ <menuContribution
+ locationURI="popup:org.eclipse.ui.popup.any">
+ <command
+ commandId="net.sf.eclipsefp.haskell.ui.buildtargets.add"
+ label="%buildTargets_add_label"
+ style="push">
+ <visibleWhen checkEnabled="false">
+ <with variable="selection">
+ <count value="1"/>
+ <iterate ifEmpty="false">
+ <instanceof value="net.sf.eclipsefp.haskell.ui.internal.views.projectexplorer.model.BuildTargets"/>
+ </iterate>
+ </with>
+ </visibleWhen>
+ </command>
+ </menuContribution>
+ </extension>
+
+ <extension point="org.eclipse.ui.commands">
+ <command
+ id="net.sf.eclipsefp.haskell.ui.buildtargets.add"
+ name="%buildTargets_add_name">
+ </command>
+ </extension>
+
+ <extension point="org.eclipse.ui.handlers">
+ <handler
+ commandId="net.sf.eclipsefp.haskell.ui.buildtargets.add"
+ class="net.sf.eclipsefp.haskell.ui.internal.handlers.AddBuildTargetHandler">
+ <enabledWhen>
+ <!-- enabled when exactly one project is selected and it is of Haskell nature,
+ or the Build Targets node or one of its children is selected -->
+ <with variable="selection">
+ <count value="1"/>
+ <iterate ifEmpty="false">
+ <or>
+ <adapt type="org.eclipse.core.resources.IProject">
+ <test property="org.eclipse.core.resources.projectNature"
+ value="net.sf.eclipsefp.haskell.core.project.HaskellNature"/>
+ </adapt>
+ <instanceof value="net.sf.eclipsefp.haskell.ui.internal.views.projectexplorer.model.BuildTargets"/>
+ <instanceof value="net.sf.eclipsefp.haskell.core.project.IBuildTarget"/>
+ </or>
+ </iterate>
+ </with>
+ </enabledWhen>
+ </handler>
+ </extension>
+
<!-- [Views] Project Explorer -->
<extension point="org.eclipse.ui.navigator.viewer">
View
30 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/Validator.java
@@ -2,8 +2,17 @@
import java.util.Observable;
import java.util.Observer;
-
-public abstract class Validator implements Observer {
+import net.sf.eclipsefp.haskell.ui.dialog.dialogfields.DialogField;
+import net.sf.eclipsefp.haskell.ui.dialog.dialogfields.IDialogFieldListener;
+
+/**
+ * Validates input in a wizard.
+ * This can be hooked up as a listener to dialog fields or observables.
+ * Subclasses can then implement validation logic and call the appropriate
+ * methods to set the validation state. The {@link ValidatorManager} will
+ * then take care of setting the wizard page's state.
+ */
+public abstract class Validator implements Observer, IDialogFieldListener {
private ValidatorManager fManager;
@@ -19,6 +28,10 @@ public Validator( final ValidatorManager manager ) {
setManager( manager );
}
+ public ValidatorManager getManager() {
+ return fManager;
+ }
+
public void setManager( final ValidatorManager manager ) {
if( fManager == null ) {
fManager = manager;
@@ -80,14 +93,23 @@ public void setIncomplete( final String message, final boolean error ) {
public void update() {
setComplete();
doUpdate();
- fManager.updatePage();
+ if (fManager != null) {
+ fManager.updatePage();
+ }
}
- // //////////////////////////
+ // /////////////////////////
// methods from Observable
public void update( final Observable o, final Object arg ) {
update();
}
+ // ///////////////////////////////////
+ // methods from IDialogFieldListener
+
+ public void dialogFieldChanged( final DialogField field ) {
+ update();
+ }
+
}
View
15 net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/ValidatorManager.java
@@ -3,6 +3,16 @@
import java.util.ArrayList;
import org.eclipse.jface.wizard.WizardPage;
+/**
+ * Manages multiple {@link Validator}s for a wizard page.
+ * This aggregates the states from all validators, sets the page's
+ * completion state, and displays the appropriate message on the page.
+ *
+ * The page is complete if all validators indicate completion.
+ * If some validator indicates an error message, this message is shown.
+ * If not, but some validator indicates a (non-error) message, this message is shown.
+ * Otherwise, no message is shown.
+ */
public final class ValidatorManager {
private final WizardPage fWizardPage;
@@ -14,7 +24,10 @@ public ValidatorManager(final WizardPage wizardPage) {
}
public void addValidator(final Validator validator) {
- validators.add( validator );
+ if (!validators.contains( validator )) {
+ validators.add( validator );
+ validator.setManager( this );
+ }
}
public void updatePage() {
View
2  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/dialog/dialogfields/DialogField.java
@@ -146,7 +146,7 @@ public Label getLabelControl(final Composite parent) {
if (fLabelText != null && !"".equals(fLabelText)) { //$NON-NLS-1$
fLabel.setText(fLabelText);
} else {
- // XXX: to avoid a 16 pixel wide empty label - revisit
+ // TODO to avoid a 16 pixel wide empty label - revisit
fLabel.setText("."); //$NON-NLS-1$
fLabel.setVisible(false);
}
View
13 </