<commit_before>package org.jetbrains.haskell.run.haskell

import com.intellij.execution.CantRunException
import com.intellij.execution.ExecutionException
import com.intellij.execution.configurations.CommandLineState
import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.execution.process.ProcessHandler
import com.intellij.execution.runners.ExecutionEnvironment
import java.io.File
import org.jetbrains.haskell.util.joinPath
import org.jetbrains.haskell.util.OS
import com.intellij.execution.Executor
import com.intellij.execution.runners.ProgramRunner
import com.intellij.execution.ExecutionResult
import com.intellij.execution.DefaultExecutionResult
import com.intellij.execution.configurations.RunnerSettings
import org.jetbrains.haskell.util.GHCUtil
import com.intellij.openapi.roots.ModuleRootManager
import org.jetbrains.haskell.debugger.GHCiProcessHandler
import org.jetbrains.haskell.debugger.HaskellDebugProcessHandler
import org.jetbrains.haskell.debugger.RemoteDebugStreamHandler
import org.jetbrains.haskell.debugger.RemoteProcessHandler
import org.jetbrains.cabal.CabalInterface
import com.intellij.openapi.module.Module
import org.jetbrains.cabal.CabalFile
import org.jetbrains.cabal.psi.Executable
import com.intellij.openapi.vfs.LocalFileSystem
import org.jetbrains.haskell.debugger.config.HaskellDebugSettings
import com.intellij.execution.process.ProcessTerminatedListener
import com.intellij.execution.process.OSProcessHandler
import com.pty4j.PtyProcess
import org.jetbrains.haskell.config.HaskellSettings
import org.jetbrains.cabal.psi.FullVersionConstraint
import java.util.ArrayList

public class HaskellCommandLineState(environment: ExecutionEnvironment, val configuration: CabalRunConfiguration) : CommandLineState(environment) {


    protected override fun startProcess(): ProcessHandler {
        val generalCommandLine = createCommandLine()
        val processHandler: ProcessHandler =
                if (HaskellSettings.getInstance().getState().usePty!!) {
                    OSProcessHandler(getPtyProcess(generalCommandLine)!!)
                } else {
                    OSProcessHandler(generalCommandLine)
                }
        ProcessTerminatedListener.attach(processHandler)
        return processHandler
    }

    private fun getPtyProcess(generalCommandLine: GeneralCommandLine): PtyProcess? {
        val exePath = generalCommandLine.getExePath()!!
        val params = generalCommandLine.getParametersList()?.getList()
        val env = generalCommandLine.getEnvironment()
        val dir = generalCommandLine.getWorkDirectory()
        val command = Array(1 + (params?.size ?: 0), {
            (i: Int) ->
            if (i == 0) exePath else params!!.get(i - 1)
        })
        return PtyProcess.exec(command, env, dir?.getAbsolutePath(), true)
    }

    private fun getDependencies(): List<FullVersionConstraint> {
        val module = configuration.getModule()
        if (module == null) {
            throw ExecutionException("Error while starting debug process: module not specified")
        }
        val exec = getExecutable(module)
        return exec.getBuildDepends() ?: listOf()
    }

    /**
     * Returns pair of main file path and path to the sources directory
     */
    private fun getPaths(): Pair<String, String> {
        val module = configuration.getModule()
        if (module == null) {
            throw ExecutionException("Error while starting debug process: module not specified")
        }
        val exec = getExecutable(module)
        val mainFileName: String? = exec.getMainFile()?.getText()
        if (mainFileName == null) {
            throw ExecutionException("Error while starting debug process: no main file specified in executable section")
        }
        val srcDirPath = tryGetSrcDirFullPath(mainFileName, module, exec)
        if (srcDirPath == null) {
            throw ExecutionException("Error while starting debug process: main file $mainFileName not found in source directories")
        }
        val filePath = joinPath(srcDirPath, mainFileName)
        return Pair(filePath, srcDirPath)
    }

    private fun getExecutable(module: Module): Executable {

        val cabalFile = tryGetCabalFile(module)
        if (cabalFile == null) {
            throw ExecutionException("Error while starting debug process: cabal file not found")
        }
        val exec = tryGetExecWithNameFromConfig(cabalFile)
        if (exec == null) {
            throw ExecutionException("Error while starting debug process: cabal file does not contain executable ${configuration.getMyExecutableName()}")
        }
        return exec
    }

    private fun startGHCiDebugProcess(): HaskellDebugProcessHandler {
        val module = configuration.getModule()
        if (module == null) {
            throw ExecutionException("Error while starting debug process: module not specified")
        }
        val paths = getPaths()
        val filePath = paths.first
        val srcDirPath = paths.second
        val ghciPath = GHCUtil.getCommandPath(ModuleRootManager.getInstance(module)!!.getSdk()!!.getHomeDirectory(), "ghci")
        if (ghciPath == null) {
            throw ExecutionException("Error while starting debug process: ghci path not specified")
        }

        val command: ArrayList<String> = arrayListOf(ghciPath, filePath, "-i$srcDirPath")
        val depends = getDependencies()
        command.add("-package")
        command.add("network")
        for (dep in depends) {
            command.add("-package")
            command.add(dep.getBaseName())
        }
        val process = Runtime.getRuntime().exec(command.copyToArray())
        return GHCiProcessHandler(process)
    }

    private fun startRemoteDebugProcess(): HaskellDebugProcessHandler {
        val module = configuration.getModule()
        if (module == null) {
            throw ExecutionException("Error while starting debug process: module not specified")
        }
        val paths = getPaths()
        val filePath = paths.first
        val srcDirPath = paths.second

        val streamHandler = RemoteDebugStreamHandler()
        streamHandler.start()

        val baseDir = module.getModuleFile()!!.getParent()!!.getCanonicalPath()!!
        val debuggerPath = HaskellDebugSettings.getInstance().getState().remoteDebuggerPath
        if (debuggerPath == null) {
            throw ExecutionException("Cannot run remote debugger: path not specified")
        }

        val builder = ProcessBuilder(debuggerPath, "-m${filePath}", "-p${streamHandler.getPort()}", "-i${srcDirPath}")
                .directory(File(baseDir))

        try {
            return RemoteProcessHandler(builder.start(), streamHandler)
        } catch (ex: Exception) {
            throw ExecutionException("Cannot run remote debugger in path " + debuggerPath)
        }
    }
<commit_msg>build-depends is used in remote debugger<commit_after>package org.jetbrains.haskell.run.haskell

import com.intellij.execution.CantRunException
import com.intellij.execution.ExecutionException
import com.intellij.execution.configurations.CommandLineState
import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.execution.process.ProcessHandler
import com.intellij.execution.runners.ExecutionEnvironment
import java.io.File
import org.jetbrains.haskell.util.joinPath
import org.jetbrains.haskell.util.OS
import com.intellij.execution.Executor
import com.intellij.execution.runners.ProgramRunner
import com.intellij.execution.ExecutionResult
import com.intellij.execution.DefaultExecutionResult
import com.intellij.execution.configurations.RunnerSettings
import org.jetbrains.haskell.util.GHCUtil
import com.intellij.openapi.roots.ModuleRootManager
import org.jetbrains.haskell.debugger.GHCiProcessHandler
import org.jetbrains.haskell.debugger.HaskellDebugProcessHandler
import org.jetbrains.haskell.debugger.RemoteDebugStreamHandler
import org.jetbrains.haskell.debugger.RemoteProcessHandler
import org.jetbrains.cabal.CabalInterface
import com.intellij.openapi.module.Module
import org.jetbrains.cabal.CabalFile
import org.jetbrains.cabal.psi.Executable
import com.intellij.openapi.vfs.LocalFileSystem
import org.jetbrains.haskell.debugger.config.HaskellDebugSettings
import com.intellij.execution.process.ProcessTerminatedListener
import com.intellij.execution.process.OSProcessHandler
import com.pty4j.PtyProcess
import org.jetbrains.haskell.config.HaskellSettings
import org.jetbrains.cabal.psi.FullVersionConstraint
import java.util.ArrayList

public class HaskellCommandLineState(environment: ExecutionEnvironment, val configuration: CabalRunConfiguration) : CommandLineState(environment) {


    protected override fun startProcess(): ProcessHandler {
        val generalCommandLine = createCommandLine()
        val processHandler: ProcessHandler =
                if (HaskellSettings.getInstance().getState().usePty!!) {
                    OSProcessHandler(getPtyProcess(generalCommandLine)!!)
                } else {
                    OSProcessHandler(generalCommandLine)
                }
        ProcessTerminatedListener.attach(processHandler)
        return processHandler
    }

    private fun getPtyProcess(generalCommandLine: GeneralCommandLine): PtyProcess? {
        val exePath = generalCommandLine.getExePath()!!
        val params = generalCommandLine.getParametersList()?.getList()
        val env = generalCommandLine.getEnvironment()
        val dir = generalCommandLine.getWorkDirectory()
        val command = Array(1 + (params?.size ?: 0), {
            (i: Int) ->
            if (i == 0) exePath else params!!.get(i - 1)
        })
        return PtyProcess.exec(command, env, dir?.getAbsolutePath(), true)
    }

    private fun getDependencies(): List<FullVersionConstraint> {
        val module = configuration.getModule()
        if (module == null) {
            throw ExecutionException("Error while starting debug process: module not specified")
        }
        val exec = getExecutable(module)
        return exec.getBuildDepends() ?: listOf()
    }

    /**
     * Returns pair of main file path and path to the sources directory
     */
    private fun getPaths(): Pair<String, String> {
        val module = configuration.getModule()
        if (module == null) {
            throw ExecutionException("Error while starting debug process: module not specified")
        }
        val exec = getExecutable(module)
        val mainFileName: String? = exec.getMainFile()?.getText()
        if (mainFileName == null) {
            throw ExecutionException("Error while starting debug process: no main file specified in executable section")
        }
        val srcDirPath = tryGetSrcDirFullPath(mainFileName, module, exec)
        if (srcDirPath == null) {
            throw ExecutionException("Error while starting debug process: main file $mainFileName not found in source directories")
        }
        val filePath = joinPath(srcDirPath, mainFileName)
        return Pair(filePath, srcDirPath)
    }

    private fun getExecutable(module: Module): Executable {

        val cabalFile = tryGetCabalFile(module)
        if (cabalFile == null) {
            throw ExecutionException("Error while starting debug process: cabal file not found")
        }
        val exec = tryGetExecWithNameFromConfig(cabalFile)
        if (exec == null) {
            throw ExecutionException("Error while starting debug process: cabal file does not contain executable ${configuration.getMyExecutableName()}")
        }
        return exec
    }

    private fun startGHCiDebugProcess(): HaskellDebugProcessHandler {
        val module = configuration.getModule()
        if (module == null) {
            throw ExecutionException("Error while starting debug process: module not specified")
        }
        val paths = getPaths()
        val filePath = paths.first
        val srcDirPath = paths.second
        val ghciPath = GHCUtil.getCommandPath(ModuleRootManager.getInstance(module)!!.getSdk()!!.getHomeDirectory(), "ghci")
        if (ghciPath == null) {
            throw ExecutionException("Error while starting debug process: ghci path not specified")
        }

        val command: ArrayList<String> = arrayListOf(ghciPath, filePath, "-i$srcDirPath")
        val depends = getDependencies()
        command.add("-package")
        command.add("network")
        for (dep in depends) {
            command.add("-package")
            command.add(dep.getBaseName())
        }
        val process = Runtime.getRuntime().exec(command.copyToArray())
        return GHCiProcessHandler(process)
    }

    private fun startRemoteDebugProcess(): HaskellDebugProcessHandler {
        val module = configuration.getModule()
        if (module == null) {
            throw ExecutionException("Error while starting debug process: module not specified")
        }
        val paths = getPaths()
        val filePath = paths.first
        val srcDirPath = paths.second

        val streamHandler = RemoteDebugStreamHandler()
        streamHandler.start()

        val baseDir = module.getModuleFile()!!.getParent()!!.getCanonicalPath()!!
        val debuggerPath = HaskellDebugSettings.getInstance().getState().remoteDebuggerPath
        if (debuggerPath == null) {
            throw ExecutionException("Cannot run remote debugger: path not specified")
        }

        val command: ArrayList<String> = arrayListOf(debuggerPath, "-m${filePath}", "-p${streamHandler.getPort()}", "-i${srcDirPath}")
        val depends = getDependencies()
        for (dep in depends) {
            command.add("-pkg${dep.getBaseName()}")
        }
        val builder = ProcessBuilder(command) .directory(File(baseDir))

        try {
            return RemoteProcessHandler(builder.start(), streamHandler)
        } catch (ex: Exception) {
            throw ExecutionException("Cannot run remote debugger in path " + debuggerPath)
        }
    }

{'fraction_non_alphanumeric': 0.0897766323024055, 'fraction_numerical': 0.0007159221076746849, 'mean_word_length': 3.2355973317161917, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5528930', 'n_tokens_mistral': 3739, 'n_tokens_neox': 3590, 'n_words': 853}