diff options
author | Eike Ziller <git@eikeziller.de> | 2017-09-25 11:57:51 +0200 |
---|---|---|
committer | Eike Ziller <git@eikeziller.de> | 2017-10-01 20:11:08 +0200 |
commit | ce0bd485ee6ff54099b564730f82ac7667b0fa08 (patch) | |
tree | 22657699d7231cfbe2e3a96c1fc3a5cedcc6b2b4 | |
parent | 3f1f50c44847a0e76a95507c9566a35dfe809a78 (diff) |
Initial Haskell project support
Shows all files from the file system tree around the .cabal file.
Provides a simple build configuration with "stack build" step.
Provides a simple run configuration with "stack exec" for each
"executable" entry.
-rw-r--r-- | plugins/haskell/Haskell.json.in | 13 | ||||
-rw-r--r-- | plugins/haskell/haskell.pro | 13 | ||||
-rw-r--r-- | plugins/haskell/haskellbuildconfiguration.cpp | 200 | ||||
-rw-r--r-- | plugins/haskell/haskellbuildconfiguration.h | 85 | ||||
-rw-r--r-- | plugins/haskell/haskellconstants.h | 2 | ||||
-rw-r--r-- | plugins/haskell/haskellplugin.cpp | 11 | ||||
-rw-r--r-- | plugins/haskell/haskellproject.cpp | 122 | ||||
-rw-r--r-- | plugins/haskell/haskellproject.h | 57 | ||||
-rw-r--r-- | plugins/haskell/haskellrunconfiguration.cpp | 156 | ||||
-rw-r--r-- | plugins/haskell/haskellrunconfiguration.h | 73 | ||||
-rw-r--r-- | plugins/haskell/stackbuildstep.cpp | 105 | ||||
-rw-r--r-- | plugins/haskell/stackbuildstep.h | 59 |
12 files changed, 892 insertions, 4 deletions
diff --git a/plugins/haskell/Haskell.json.in b/plugins/haskell/Haskell.json.in index daecf89..fe8767b 100644 --- a/plugins/haskell/Haskell.json.in +++ b/plugins/haskell/Haskell.json.in @@ -7,5 +7,16 @@ \"License\" : \"MIT\", \"Description\" : \"Haskell support\", \"Url\" : \"https://haskell.org\", - $$dependencyList + $$dependencyList, + + \"Mimetypes\" : [ + \"<?xml version=\'1.0\'?>\", + \"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\", + \" <mime-type type=\'text/x-haskell-project\'>\", + \" <sub-class-of type=\'text/plain\'/>\", + \" <comment>Haskell Cabal project file</comment>\", + \" <glob pattern=\'*.cabal\'/>\", + \" </mime-type>\", + \"</mime-info>\" + ] } diff --git a/plugins/haskell/haskell.pro b/plugins/haskell/haskell.pro index 2c9739a..92d0307 100644 --- a/plugins/haskell/haskell.pro +++ b/plugins/haskell/haskell.pro @@ -15,7 +15,11 @@ SOURCES += \ optionspage.cpp \ filecache.cpp \ haskelleditorwidget.cpp \ - followsymbol.cpp + followsymbol.cpp \ + haskellproject.cpp \ + haskellbuildconfiguration.cpp \ + stackbuildstep.cpp \ + haskellrunconfiguration.cpp HEADERS += \ haskell_global.h \ @@ -32,7 +36,11 @@ HEADERS += \ optionspage.h \ filecache.h \ haskelleditorwidget.h \ - followsymbol.h + followsymbol.h \ + haskellproject.h \ + haskellbuildconfiguration.h \ + stackbuildstep.h \ + haskellrunconfiguration.h ## uncomment to build plugin into user config directory ## <localappdata>/plugins/<ideversion> @@ -52,6 +60,7 @@ QTC_LIB_DEPENDS += \ QTC_PLUGIN_DEPENDS += \ coreplugin \ + projectexplorer \ texteditor QTC_PLUGIN_RECOMMENDS += \ diff --git a/plugins/haskell/haskellbuildconfiguration.cpp b/plugins/haskell/haskellbuildconfiguration.cpp new file mode 100644 index 0000000..0412340 --- /dev/null +++ b/plugins/haskell/haskellbuildconfiguration.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "haskellbuildconfiguration.h" + +#include "haskellconstants.h" +#include "haskellproject.h" +#include "stackbuildstep.h" + +#include <projectexplorer/buildinfo.h> +#include <projectexplorer/buildsteplist.h> +#include <projectexplorer/project.h> +#include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/target.h> +#include <utils/algorithm.h> +#include <utils/detailswidget.h> +#include <utils/mimetypes/mimedatabase.h> +#include <utils/pathchooser.h> +#include <utils/qtcassert.h> + +#include <QHBoxLayout> +#include <QLabel> +#include <QVBoxLayout> + +using namespace ProjectExplorer; + +const char C_HASKELL_BUILDCONFIGURATION_ID[] = "Haskell.BuildConfiguration"; + +namespace Haskell { +namespace Internal { + +HaskellBuildConfigurationFactory::HaskellBuildConfigurationFactory() {} + +int HaskellBuildConfigurationFactory::priority(const Target *parent) const +{ + return HaskellProject::isHaskellProject(parent->project()) ? 0 : -1; +} + +static QList<BuildInfo *> createInfos(const HaskellBuildConfigurationFactory *factory, + const Kit *k, + const Utils::FileName &projectFilePath) +{ + auto info = new BuildInfo(factory); + info->typeName = HaskellBuildConfigurationFactory::tr("Release"); + info->displayName = info->typeName; + info->buildDirectory = projectFilePath.parentDir().appendPath(".stack-work"); + info->kitId = k->id(); + info->buildType = BuildConfiguration::BuildType::Release; + return {info}; +} + +QList<BuildInfo *> HaskellBuildConfigurationFactory::availableBuilds(const Target *parent) const +{ + // Entries that are available in add build configuration dropdown + QTC_ASSERT(priority(parent) > -1, return {}); + return Utils::transform(createInfos(this, parent->kit(), parent->project()->projectFilePath()), + [](BuildInfo *info) { + info->displayName.clear(); + return info; + }); +} + +int HaskellBuildConfigurationFactory::priority(const Kit *k, const QString &projectPath) const +{ + if (k && Utils::mimeTypeForFile(projectPath).matchesName(Constants::C_HASKELL_PROJECT_MIMETYPE)) + return 0; + return -1; +} + +QList<BuildInfo *> HaskellBuildConfigurationFactory::availableSetups( + const Kit *k, const QString &projectPath) const +{ + QTC_ASSERT(priority(k, projectPath) > -1, return {}); + return createInfos(this, k, Utils::FileName::fromString(projectPath)); +} + +BuildConfiguration *HaskellBuildConfigurationFactory::create(Target *parent, + const BuildInfo *info) const +{ + QTC_ASSERT(HaskellProject::isHaskellProject(parent->project()), return nullptr); + auto config = new HaskellBuildConfiguration(parent); + config->setBuildDirectory(info->buildDirectory); + config->setBuildType(info->buildType); + config->setDisplayName(info->displayName); + + BuildStepList *buildSteps = config->stepList(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD)); + auto stackBuildStep = new StackBuildStep(buildSteps); + buildSteps->appendStep(stackBuildStep); + + return config; +} + +bool HaskellBuildConfigurationFactory::canRestore(const Target *parent, const QVariantMap &map) const +{ + Q_UNUSED(map) + return HaskellProject::isHaskellProject(parent->project()); +} + +BuildConfiguration *HaskellBuildConfigurationFactory::restore(Target *parent, const QVariantMap &map) +{ + QTC_ASSERT(canRestore(parent, map), return nullptr); + auto config = new HaskellBuildConfiguration(parent); + config->fromMap(map); + return config; +} + +bool HaskellBuildConfigurationFactory::canClone(const Target *parent, + BuildConfiguration *product) const +{ + Q_UNUSED(parent) + return product->id() == C_HASKELL_BUILDCONFIGURATION_ID; +} + +BuildConfiguration *HaskellBuildConfigurationFactory::clone(Target *parent, + BuildConfiguration *product) +{ + QTC_ASSERT(canClone(parent, product), return nullptr); + auto config = new HaskellBuildConfiguration(parent); + config->fromMap(product->toMap()); + return config; +} + +HaskellBuildConfiguration::HaskellBuildConfiguration(Target *target) + : BuildConfiguration(target, C_HASKELL_BUILDCONFIGURATION_ID) +{} + +NamedWidget *HaskellBuildConfiguration::createConfigWidget() +{ + return new HaskellBuildConfigurationWidget(this); +} + +BuildConfiguration::BuildType HaskellBuildConfiguration::buildType() const +{ + return m_buildType; +} + +void HaskellBuildConfiguration::setBuildType(BuildConfiguration::BuildType type) +{ + m_buildType = type; +} + +HaskellBuildConfigurationWidget::HaskellBuildConfigurationWidget(HaskellBuildConfiguration *bc) + : NamedWidget() + , m_buildConfiguration(bc) +{ + setDisplayName(tr("General")); + setLayout(new QVBoxLayout); + layout()->setMargin(0); + auto box = new Utils::DetailsWidget; + box->setState(Utils::DetailsWidget::NoSummary); + layout()->addWidget(box); + auto details = new QWidget; + box->setWidget(details); + details->setLayout(new QHBoxLayout); + details->layout()->setMargin(0); + details->layout()->addWidget(new QLabel(tr("Build directory:"))); + + auto buildDirectoryInput = new Utils::PathChooser; + buildDirectoryInput->setExpectedKind(Utils::PathChooser::Directory); + buildDirectoryInput->setFileName(m_buildConfiguration->buildDirectory()); + details->layout()->addWidget(buildDirectoryInput); + + connect(m_buildConfiguration, + &BuildConfiguration::buildDirectoryChanged, + buildDirectoryInput, + [this, buildDirectoryInput] { + buildDirectoryInput->setFileName(m_buildConfiguration->buildDirectory()); + }); + connect(buildDirectoryInput, + &Utils::PathChooser::pathChanged, + m_buildConfiguration, + [this, buildDirectoryInput](const QString &) { + m_buildConfiguration->setBuildDirectory(buildDirectoryInput->rawFileName()); + }); +} + +} // namespace Internal +} // namespace Haskell diff --git a/plugins/haskell/haskellbuildconfiguration.h b/plugins/haskell/haskellbuildconfiguration.h new file mode 100644 index 0000000..56ec088 --- /dev/null +++ b/plugins/haskell/haskellbuildconfiguration.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/namedwidget.h> + +namespace Haskell { +namespace Internal { + +class HaskellBuildConfigurationFactory : public ProjectExplorer::IBuildConfigurationFactory +{ + Q_OBJECT + +public: + HaskellBuildConfigurationFactory(); + + int priority(const ProjectExplorer::Target *parent) const override; + QList<ProjectExplorer::BuildInfo *> availableBuilds( + const ProjectExplorer::Target *parent) const override; + int priority(const ProjectExplorer::Kit *k, const QString &projectPath) const override; + QList<ProjectExplorer::BuildInfo *> availableSetups(const ProjectExplorer::Kit *k, + const QString &projectPath) const override; + ProjectExplorer::BuildConfiguration *create( + ProjectExplorer::Target *parent, const ProjectExplorer::BuildInfo *info) const override; + bool canRestore(const ProjectExplorer::Target *parent, const QVariantMap &map) const override; + ProjectExplorer::BuildConfiguration *restore(ProjectExplorer::Target *parent, + const QVariantMap &map) override; + bool canClone(const ProjectExplorer::Target *parent, + ProjectExplorer::BuildConfiguration *product) const override; + ProjectExplorer::BuildConfiguration *clone( + ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) override; +}; + +class HaskellBuildConfiguration : public ProjectExplorer::BuildConfiguration +{ + Q_OBJECT + +public: + explicit HaskellBuildConfiguration(ProjectExplorer::Target *target); + + ProjectExplorer::NamedWidget *createConfigWidget() override; + BuildType buildType() const override; + void setBuildType(BuildType type); + +private: + BuildType m_buildType = BuildType::Release; +}; + +class HaskellBuildConfigurationWidget : public ProjectExplorer::NamedWidget +{ + Q_OBJECT + +public: + HaskellBuildConfigurationWidget(HaskellBuildConfiguration *bc); + +private: + HaskellBuildConfiguration *m_buildConfiguration; +}; + +} // namespace Internal +} // namespace Haskell diff --git a/plugins/haskell/haskellconstants.h b/plugins/haskell/haskellconstants.h index 55be670..1ff285c 100644 --- a/plugins/haskell/haskellconstants.h +++ b/plugins/haskell/haskellconstants.h @@ -30,6 +30,8 @@ namespace Constants { const char C_HASKELLEDITOR_ID[] = "Haskell.HaskellEditor"; const char C_HASKELLSNIPPETSGROUP_ID[] = "Haskell"; +const char C_HASKELL_PROJECT_MIMETYPE[] = "text/x-haskell-project"; +const char C_HASKELL_RUNCONFIG_ID_PREFIX[] = "Haskell.Run."; } // namespace Haskell } // namespace Constants diff --git a/plugins/haskell/haskellplugin.cpp b/plugins/haskell/haskellplugin.cpp index 362e00f..c5386a4 100644 --- a/plugins/haskell/haskellplugin.cpp +++ b/plugins/haskell/haskellplugin.cpp @@ -26,12 +26,17 @@ #include "haskellplugin.h" #include "ghcmod.h" +#include "haskellbuildconfiguration.h" #include "haskellconstants.h" #include "haskelleditorfactory.h" #include "haskellmanager.h" +#include "haskellproject.h" +#include "haskellrunconfiguration.h" #include "optionspage.h" +#include "stackbuildstep.h" #include <coreplugin/icore.h> +#include <projectexplorer/projectmanager.h> #include <texteditor/snippets/snippetprovider.h> namespace Haskell { @@ -62,7 +67,11 @@ bool HaskellPlugin::initialize(const QStringList &arguments, QString *errorStrin addAutoReleasedObject(new HaskellEditorFactory); addAutoReleasedObject(new OptionsPage); - + addAutoReleasedObject(new HaskellBuildConfigurationFactory); + addAutoReleasedObject(new StackBuildStepFactory); + addAutoReleasedObject(new HaskellRunConfigurationFactory); + ProjectExplorer::ProjectManager::registerProjectType<HaskellProject>( + Constants::C_HASKELL_PROJECT_MIMETYPE); TextEditor::SnippetProvider::registerGroup(Constants::C_HASKELLSNIPPETSGROUP_ID, tr("Haskell", "SnippetProvider")); diff --git a/plugins/haskell/haskellproject.cpp b/plugins/haskell/haskellproject.cpp new file mode 100644 index 0000000..96855ee --- /dev/null +++ b/plugins/haskell/haskellproject.cpp @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "haskellproject.h" + +#include "haskellconstants.h" + +#include <coreplugin/iversioncontrol.h> +#include <coreplugin/vcsmanager.h> +#include <utils/algorithm.h> +#include <utils/fileutils.h> +#include <utils/runextensions.h> + +#include <QFile> +#include <QTextStream> + +using namespace ProjectExplorer; +using namespace Utils; + +const char C_HASKELL_PROJECT_ID[] = "Haskell.Project"; + +namespace Haskell { +namespace Internal { + +static QVector<QString> parseExecutableNames(const FileName &projectFilePath) +{ + static const QString EXECUTABLE = "executable"; + static const int EXECUTABLE_LEN = EXECUTABLE.length(); + QVector<QString> result; + QFile file(projectFilePath.toString()); + if (file.open(QFile::ReadOnly)) { + QTextStream stream(&file); + while (!stream.atEnd()) { + const QString line = stream.readLine().trimmed(); + if (line.length() > EXECUTABLE_LEN && line.startsWith(EXECUTABLE) + && line.at(EXECUTABLE_LEN).isSpace()) + result.append(line.mid(EXECUTABLE_LEN + 1).trimmed()); + } + } + return result; +} + +HaskellProjectNode::HaskellProjectNode(const FileName &projectFilePath, Core::Id id) + : ProjectNode(projectFilePath, id.toString().toLatin1()) +{} + +HaskellProject::HaskellProject(const Utils::FileName &fileName) + : Project(Constants::C_HASKELL_PROJECT_MIMETYPE, fileName) +{ + setId(C_HASKELL_PROJECT_ID); + setDisplayName(fileName.toFileInfo().completeBaseName()); + updateFiles(); +} + +bool HaskellProject::isHaskellProject(Project *project) +{ + return project && project->id() == C_HASKELL_PROJECT_ID; +} + +HaskellProject *HaskellProject::toHaskellProject(Project *project) +{ + if (project && project->id() == C_HASKELL_PROJECT_ID) + return static_cast<HaskellProject *>(project); + return nullptr; +} + +QList<Core::Id> HaskellProject::availableRunConfigurationIds() const +{ + return Utils::transform<QList>(parseExecutableNames(projectFilePath()), [](const QString &exe) { + return Core::Id(Constants::C_HASKELL_RUNCONFIG_ID_PREFIX).withSuffix(exe); + }); +} + +void HaskellProject::updateFiles() +{ + emitParsingStarted(); + FileName projectDir = projectDirectory(); + const QList<Core::IVersionControl *> versionControls = Core::VcsManager::versionControls(); + QFuture<QList<FileNode *>> future = Utils::runAsync([this, projectDir, versionControls] { + return FileNode::scanForFilesWithVersionControls( + projectDir, + [this](const FileName &fn) -> FileNode * { + if (fn != FileName::fromString(projectFilePath().toString() + ".user")) + return new FileNode(fn, FileType::Source, false); + else + return nullptr; + }, + versionControls); + }); + Utils::onResultReady(future, this, [this](const QList<FileNode *> &nodes) { + auto root = new HaskellProjectNode(projectDirectory(), id()); + root->setDisplayName(displayName()); + root->addNestedNodes(nodes); + setRootProjectNode(root); + emitParsingFinished(true); + }); +} + +} // namespace Internal +} // namespace Haskell diff --git a/plugins/haskell/haskellproject.h b/plugins/haskell/haskellproject.h new file mode 100644 index 0000000..cc6e308 --- /dev/null +++ b/plugins/haskell/haskellproject.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <projectexplorer/project.h> +#include <projectexplorer/projectnodes.h> + +namespace Haskell { +namespace Internal { + +class HaskellProjectNode : public ProjectExplorer::ProjectNode +{ +public: + HaskellProjectNode(const Utils::FileName &projectFilePath, Core::Id id); +}; + +class HaskellProject : public ProjectExplorer::Project +{ + Q_OBJECT + +public: + explicit HaskellProject(const Utils::FileName &fileName); + + static bool isHaskellProject(Project *project); + static HaskellProject *toHaskellProject(Project *project); + + QList<Core::Id> availableRunConfigurationIds() const; + +private: + void updateFiles(); +}; + +} // namespace Internal +} // namespace Haskell diff --git a/plugins/haskell/haskellrunconfiguration.cpp b/plugins/haskell/haskellrunconfiguration.cpp new file mode 100644 index 0000000..dfeee7e --- /dev/null +++ b/plugins/haskell/haskellrunconfiguration.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "haskellrunconfiguration.h" + +#include "haskellconstants.h" +#include "haskellmanager.h" +#include "haskellproject.h" + +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/localenvironmentaspect.h> +#include <projectexplorer/runconfigurationaspects.h> +#include <projectexplorer/runnables.h> +#include <projectexplorer/target.h> +#include <utils/detailswidget.h> + +#include <QFormLayout> + +using namespace ProjectExplorer; + +namespace Haskell { +namespace Internal { + +HaskellRunConfigurationFactory::HaskellRunConfigurationFactory() {} + +QList<Core::Id> HaskellRunConfigurationFactory::availableCreationIds( + Target *parent, + IRunConfigurationFactory::CreationMode mode) const +{ + Q_UNUSED(mode) + const auto project = HaskellProject::toHaskellProject(parent->project()); + if (project) + return project->availableRunConfigurationIds(); + return {}; +} + +QString HaskellRunConfigurationFactory::displayNameForId(Core::Id id) const +{ + return id.suffixAfter(Constants::C_HASKELL_RUNCONFIG_ID_PREFIX); +} + +bool HaskellRunConfigurationFactory::canCreate(Target *parent, Core::Id id) const +{ + return id.name().startsWith(Constants::C_HASKELL_RUNCONFIG_ID_PREFIX) + && HaskellProject::isHaskellProject(parent->project()); +} + +bool HaskellRunConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const +{ + return canCreate(parent, idFromMap(map)); +} + +bool HaskellRunConfigurationFactory::canClone(Target *parent, RunConfiguration *product) const +{ + return canCreate(parent, product->id()); +} + +RunConfiguration *HaskellRunConfigurationFactory::clone(Target *parent, RunConfiguration *product) +{ + return cloneHelper<HaskellRunConfiguration>(parent, product); +} + +RunConfiguration *HaskellRunConfigurationFactory::doCreate(Target *parent, Core::Id id) +{ + QTC_ASSERT(canCreate(parent, id), return nullptr); + return createHelper<HaskellRunConfiguration>(parent, id); +} + +RunConfiguration *HaskellRunConfigurationFactory::doRestore(Target *parent, const QVariantMap &map) +{ + QTC_ASSERT(canRestore(parent, map), return nullptr); + auto config = doCreate(parent, idFromMap(map)); + config->fromMap(map); + return config; +} + +HaskellRunConfiguration::HaskellRunConfiguration(Target *parent) + : RunConfiguration(parent) +{ + auto argumentAspect = new ArgumentsAspect(this, "Haskell.RunAspect.Arguments"); + auto workingDirAspect = new WorkingDirectoryAspect(this, "Haskell.RunAspect.WorkingDirectory"); + workingDirAspect->setDefaultWorkingDirectory(parent->project()->projectDirectory()); + auto terminalAspect = new TerminalAspect(this, "Haskell.RunAspect.Terminal"); + auto environmentAspect + = new LocalEnvironmentAspect(this, LocalEnvironmentAspect::BaseEnvironmentModifier()); + addExtraAspect(argumentAspect); + addExtraAspect(terminalAspect); + addExtraAspect(environmentAspect); +} + +QWidget *HaskellRunConfiguration::createConfigurationWidget() +{ + auto details = new Utils::DetailsWidget; + details->setState(Utils::DetailsWidget::NoSummary); + auto widget = new QWidget; + details->setWidget(widget); + auto layout = new QFormLayout(widget); + layout->setMargin(0); + layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); + extraAspect<ArgumentsAspect>()->addToMainConfigurationWidget(widget, layout); + extraAspect<TerminalAspect>()->addToMainConfigurationWidget(widget, layout); + return details; +} + +Runnable HaskellRunConfiguration::runnable() const +{ + const QString projectDirectory = target()->project()->projectDirectory().toString(); + StandardRunnable r; + if (BuildConfiguration *buildConfiguration = target()->activeBuildConfiguration()) + r.commandLineArguments += "--work-dir \"" + + QDir(projectDirectory) + .relativeFilePath( + buildConfiguration->buildDirectory().toString()) + + "\" "; + r.commandLineArguments += "exec \"" + m_executable + "\""; + auto argumentsAspect = extraAspect<ArgumentsAspect>(); + if (!argumentsAspect->arguments().isEmpty()) + r.commandLineArguments += " -- " + argumentsAspect->arguments(); + r.workingDirectory = projectDirectory; + r.runMode = extraAspect<TerminalAspect>()->runMode(); + r.environment = extraAspect<LocalEnvironmentAspect>()->environment(); + r.executable = r.environment.searchInPath(HaskellManager::stackExecutable().toString()).toString(); + return r; +} + +void HaskellRunConfiguration::initialize(Core::Id id) +{ + RunConfiguration::initialize(id); + m_executable = id.suffixAfter(Constants::C_HASKELL_RUNCONFIG_ID_PREFIX); + setDefaultDisplayName(m_executable); +} + +} // namespace Internal +} // namespace Haskell diff --git a/plugins/haskell/haskellrunconfiguration.h b/plugins/haskell/haskellrunconfiguration.h new file mode 100644 index 0000000..44edfe6 --- /dev/null +++ b/plugins/haskell/haskellrunconfiguration.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <projectexplorer/runconfiguration.h> + +namespace Haskell { +namespace Internal { + +class HaskellRunConfigurationFactory : public ProjectExplorer::IRunConfigurationFactory +{ + Q_OBJECT + +public: + HaskellRunConfigurationFactory(); + + QList<Core::Id> availableCreationIds(ProjectExplorer::Target *parent, + CreationMode mode) const override; + QString displayNameForId(Core::Id id) const override; + bool canCreate(ProjectExplorer::Target *parent, Core::Id id) const override; + bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const override; + bool canClone(ProjectExplorer::Target *parent, + ProjectExplorer::RunConfiguration *product) const override; + ProjectExplorer::RunConfiguration *clone(ProjectExplorer::Target *parent, + ProjectExplorer::RunConfiguration *product) override; + +private: + ProjectExplorer::RunConfiguration *doCreate(ProjectExplorer::Target *parent, + Core::Id id) override; + ProjectExplorer::RunConfiguration *doRestore(ProjectExplorer::Target *parent, + const QVariantMap &map) override; +}; + +class HaskellRunConfiguration : public ProjectExplorer::RunConfiguration +{ + Q_OBJECT + +public: + HaskellRunConfiguration(ProjectExplorer::Target *parent); + + QWidget *createConfigurationWidget() override; + ProjectExplorer::Runnable runnable() const override; + void initialize(Core::Id id); + +private: + QString m_executable; +}; + +} // namespace Internal +} // namespace Haskell diff --git a/plugins/haskell/stackbuildstep.cpp b/plugins/haskell/stackbuildstep.cpp new file mode 100644 index 0000000..f4b1cfb --- /dev/null +++ b/plugins/haskell/stackbuildstep.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "stackbuildstep.h" + +#include "haskellmanager.h" + +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/project.h> + +using namespace ProjectExplorer; + +const char C_STACK_BUILD_STEP_ID[] = "Haskell.Stack.Build"; + +namespace Haskell { +namespace Internal { + +StackBuildStep::StackBuildStep(ProjectExplorer::BuildStepList *bsl) + : AbstractProcessStep(bsl, C_STACK_BUILD_STEP_ID) +{ + setDefaultDisplayName(trDisplayName()); + + const auto updateArguments = [this] { + const auto projectDir = QDir(project()->projectDirectory().toString()); + processParameters()->setArguments( + "build --work-dir \"" + + projectDir.relativeFilePath(buildConfiguration()->buildDirectory().toString()) + "\""); + }; + const auto updateEnvironment = [this] { + processParameters()->setEnvironment(buildConfiguration()->environment()); + }; + processParameters()->setCommand(HaskellManager::stackExecutable().toString()); + updateArguments(); + processParameters()->setWorkingDirectory(project()->projectDirectory().toString()); + updateEnvironment(); + connect(HaskellManager::instance(), + &HaskellManager::stackExecutableChanged, + this, + [this](const Utils::FileName &stackExe) { + processParameters()->setCommand(stackExe.toString()); + }); + connect(buildConfiguration(), &BuildConfiguration::buildDirectoryChanged, this, updateArguments); + connect(buildConfiguration(), &BuildConfiguration::environmentChanged, this, updateEnvironment); +} + +BuildStepConfigWidget *StackBuildStep::createConfigWidget() +{ + return new SimpleBuildStepConfigWidget(this); +} + +QString StackBuildStep::trDisplayName() +{ + return tr("Stack Build"); +} + +QList<BuildStepInfo> StackBuildStepFactory::availableSteps(BuildStepList *parent) const +{ + Q_UNUSED(parent) + return {BuildStepInfo(C_STACK_BUILD_STEP_ID, StackBuildStep::trDisplayName())}; +} + +BuildStep *StackBuildStepFactory::create(BuildStepList *parent, Core::Id id) +{ + Q_UNUSED(id) + return new StackBuildStep(parent); +} + +BuildStep *StackBuildStepFactory::restore(BuildStepList *parent, const QVariantMap &map) +{ + auto step = new StackBuildStep(parent); + step->fromMap(map); + return step; +} + +BuildStep *StackBuildStepFactory::clone(BuildStepList *parent, BuildStep *product) +{ + auto step = new StackBuildStep(parent); + step->fromMap(product->toMap()); + return step; +} + +} // namespace Internal +} // namespace Haskell diff --git a/plugins/haskell/stackbuildstep.h b/plugins/haskell/stackbuildstep.h new file mode 100644 index 0000000..e786d18 --- /dev/null +++ b/plugins/haskell/stackbuildstep.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <projectexplorer/abstractprocessstep.h> + +namespace Haskell { +namespace Internal { + +class StackBuildStep : public ProjectExplorer::AbstractProcessStep +{ + Q_OBJECT + +public: + StackBuildStep(ProjectExplorer::BuildStepList *bsl); + + ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; + + static QString trDisplayName(); +}; + +class StackBuildStepFactory : public ProjectExplorer::IBuildStepFactory +{ + // IBuildStepFactory interface +public: + QList<ProjectExplorer::BuildStepInfo> availableSteps( + ProjectExplorer::BuildStepList *parent) const override; + ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id) override; + ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, + const QVariantMap &map) override; + ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent, + ProjectExplorer::BuildStep *product) override; +}; + +} // namespace Internal +} // namespace Haskell |