// Copyright (c) 2003-2008 by Leif Frenzel. All rights reserved.
// This code is made available under the terms of the Eclipse Public License,
// version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
package net.sf.eclipsefp.haskell.debug.ui.internal.launch.ghci;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import net.sf.eclipsefp.haskell.buildwrapper.BWFacade;
import net.sf.eclipsefp.haskell.buildwrapper.BuildWrapperPlugin;
import net.sf.eclipsefp.haskell.buildwrapper.types.BuildFlags;
import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
import net.sf.eclipsefp.haskell.core.compiler.CompilerManager;
import net.sf.eclipsefp.haskell.debug.core.internal.launch.IInteractiveLaunchOperationDelegate;
import net.sf.eclipsefp.haskell.ghccompiler.GhcCompilerPlugin;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
/** <p>implements a delegate for launching GHCi.</p>
*
* @author Leif Frenzel
*/
public class GhciLaunchOperationDelegate
implements IInteractiveLaunchOperationDelegate {
//private final CompilerParams compilerParams = new CompilerParams();
// interface methods of IInteractiveLaunchOperationDelegate
///////////////////////////////////////////////////////////
@Override
public String[] createArguments( final IProject hsProject,
final IFile[] selectedFiles,final String mode ) {
List<String> cmdLine = new ArrayList<>();
cmdLine.add( "--interactive" ); //$NON-NLS-1$
BWFacade bf=BuildWrapperPlugin.getFacade( hsProject );
if (bf!=null){
BuildFlags flags=bf.getBuildFlags( selectedFiles[0] );
if (flags!=null){
boolean debug="debug".equals(mode); //$NON-NLS-1$
boolean isDir=false;
for (String s:flags.getGhcFlags()){
boolean include=true;
if (debug){
// here we exclude dir folders pointing to built object code, so that we interpret everything
// it's better to get all flags and exclude what we don't want than adding stuff from the cabal file ourselves
boolean removeFromDebug=(s.startsWith( "-I" ) || s.startsWith( "-i" )) //$NON-NLS-1$ //$NON-NLS-2$
&& s.contains( BWFacade.DIST_FOLDER );
if (isDir){
removeFromDebug=true;
isDir=false;
} else {
isDir=s.startsWith( "-" ) && s.contains( "dir" ); //$NON-NLS-1$//$NON-NLS-2$
removeFromDebug |= isDir;
}
include=!removeFromDebug;
}
String sl=s.toLowerCase(Locale.ENGLISH);
// ignore verbosity settings, since -v0 will cause us to not show anything
if (sl.startsWith( "-v" ) && sl.length()==3){ //$NON-NLS-1$
include=false;
}
// ignore optimisation settings
if (sl.startsWith( "-o" ) && sl.length()==3){ //$NON-NLS-1$
include=false;
}
if (include){
cmdLine.add(s);
}
}
}
}
// cmdLine.addAll(Util.constructLibPath( selectedFiles ));
//
// /*if( isPrefSet( IGhcPreferenceNames.GHCI_USES_GHC_OPTIONS ) ) {
// cmdLine.addAll( compilerParams.construct() );
// }*/
// for (String s:ResourceUtil.getApplicableListProperty( selectedFiles, CabalSyntax.FIELD_EXTENSIONS )){
// if (s.length()>0){
// cmdLine.add("-X"+s); //$NON-NLS-1$
// }
// }
//
// cmdLine.addAll(ResourceUtil.getApplicableListProperty( selectedFiles, CabalSyntax.FIELD_GHC_OPTIONS ));
//
// cmdLine.addAll(ResourceUtil.getApplicableListProperty( selectedFiles, CabalSyntax.FIELD_GHC_PROF_OPTIONS ));
//
//
// collectImportDirs( hsProject, cmdLine ,selectedFiles );
addAll( cmdLine, selectedFiles );
String[] result = new String[ cmdLine.size() ];
cmdLine.toArray( result );
if( GhcCompilerPlugin.isTracing() ) {
System.out.println( "Launching interactive session with arguments:" ); //$NON-NLS-1$
HaskellCorePlugin.dump( cmdLine );
}
return result;
}
@Override
public String getExecutable() {
return CompilerManager.getCompilerExecutable();
}
// helping methods
//////////////////
// private void collectImportDirs( final IProject hsProject,
// final List<String> cmdLine, final IFile[] selectedFiles) {
// //if( isPrefSet( IGhcPreferenceNames.GHCI_SOURCE_FOLDERS ) ) {
// try {
// Set<IProject> visited = new HashSet<IProject>();
// visited.add( hsProject );
// collectImportDirsRec( hsProject, cmdLine, visited,selectedFiles );
// } catch( final CoreException cex ) {
// HaskellCorePlugin.log( cex );
// }
// //}
// }
//
// private void collectImportDirsRec(
// final IProject hsProject,
// final List<String> cmdLine,
// final Set<IProject> visited,final IFile[] selectedFiles ) throws CoreException {
// /*Set<IPath> sourcePaths = hsProject.getSourcePaths();*/
// Collection<String> srcs=new ArrayList<String>();
//
// srcs.addAll( ResourceUtil.getSourceFolders( selectedFiles ));
//
// // if we reference our own library, we need to include the sources
// // also if we don't belong to a source folder
// if( hsProject.hasNature( HaskellNature.NATURE_ID ) ) {
//
// IFile f=BuildWrapperPlugin.getCabalFile( hsProject );
// PackageDescription pd=PackageDescriptionLoader.load(f);
// if (srcs.isEmpty() || ResourceUtil.getImportPackages(selectedFiles).contains( pd.getPackageStanza().getName())){
//
// for (PackageDescriptionStanza sts:pd.getStanzas()){
// if (CabalSyntax.SECTION_LIBRARY.equals(sts.getType())){
// srcs.addAll(sts.getSourceDirs());
// }
// }
// }
// }
//
// for( String sourcePath: srcs ) {
// IResource r=hsProject;
// if (!sourcePath.equals( "." )){ //$NON-NLS-1$
// r=hsProject.getFolder( sourcePath );
// }
// // getRawLocation gives us the real FS path even if the resource is linked
// IPath loc = new Path( r.getLocationURI().getPath() );
// // AbstractHaskellLaunchDelegate uses ProcessBuilder, which will do the proper escaping if needed, so no need to wrap in quotes here
// cmdLine.add( "-i" + loc.toOSString() ); //$NON-NLS-1$
// }
// IProject[] refs = hsProject.getReferencedProjects();
// for( IProject ref: refs ) {
// if( ref.hasNature( HaskellNature.NATURE_ID ) ) {
// if( !visited.contains( ref ) ) {
// collectImportDirsRec( ref, cmdLine, visited,selectedFiles );
// visited.add( ref );
// }
// }
// }
// }
/*private boolean isPrefSet( final String key ) {
return Platform.getPreferencesService().getBoolean( GhcCompilerPlugin.getPluginId(), key, false, null );
}*/
private void addAll( final List<String> cmdLine, final IFile[] selectedFiles ) {
for( int i = 0; i < selectedFiles.length; i++ ) {
if (selectedFiles[ i ]!=null){
IPath p=selectedFiles[ i ].getLocation();
if (p!=null){ // file could be non existent
String path = p.toOSString();
// AbstractHaskellLaunchDelegate uses ProcessBuilder, which will do the proper escaping, so no need to wrap in quotes here
cmdLine.add( path );
}
}
}
}
@Override
public String getReloadCommand() {
return ":r"; //$NON-NLS-1$
}
}