Nim: Add support for the nimble build system

Change-Id: Id3bd977f14bc9d2ec3fa92e162238bbff0513de1
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Filippo Cucchetto
2019-09-16 22:43:27 +02:00
parent 04f0123c43
commit c75c4b2d0e
41 changed files with 2194 additions and 25 deletions

View File

@@ -0,0 +1,14 @@
# Package
backend = "%{ProjectBackend}"
version = "%{ProjectVersion}"
author = "%{ProjectAuthor}"
description = "%{ProjectDescription}"
license = "%{ProjectLicense}"
srcDir = "src"
bin = @["%{ProjectName}"]
# Dependencies
requires "nim >= %{ProjectNimVersion}"

View File

@@ -0,0 +1,5 @@
# This is just an example to get you started. A typical binary package
# uses this file as the main entry point of the application.
when isMainModule:
echo("Hello, World!")

View File

@@ -0,0 +1,15 @@
# Package
backend = "%{ProjectBackend}"
version = "%{ProjectVersion}"
author = "%{ProjectAuthor}"
description = "%{ProjectDescription}"
license = "%{ProjectLicense}"
srcDir = "src"
installExt = @["nim"]
bin = @["%{ProjectName}"]
# Dependencies
requires "nim >= %{ProjectNimVersion}"

View File

@@ -0,0 +1,7 @@
# This is just an example to get you started. A typical hybrid package
# uses this file as the main entry point of the application.
import %{ProjectName}pkg/submodule
when isMainModule:
echo(getWelcomeMessage())

View File

@@ -0,0 +1,6 @@
# This is just an example to get you started. Users of your hybrid library will
# import this file by writing ``import %{ProjectName}pkg/submodule``. Feel free to rename or
# remove this file altogether. You may create additional modules alongside
# this file as required.
proc getWelcomeMessage*(): string = "Hello, World!"

View File

@@ -0,0 +1 @@
switch("path", "$projectDir/../src")

View File

@@ -0,0 +1,12 @@
# This is just an example to get you started. You may wish to put all of your
# tests into a single file, or separate them into multiple `test1`, `test2`
# etc. files (better names are recommended, just make sure the name starts with
# the letter 't').
#
# To run these tests, simply execute `nimble test`.
import unittest
import %{ProjectName}pkg/submodule
test "correct welcome":
check getWelcomeMessage() == "Hello, World!"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,13 @@
# Package
backend = "%{ProjectBackend}"
version = "%{ProjectVersion}"
author = "%{ProjectAuthor}"
description = "%{ProjectDescription}"
license = "%{ProjectLicense}"
srcDir = "src"
# Dependencies
requires "nim >= %{ProjectNimVersion}"

View File

@@ -0,0 +1,7 @@
# This is just an example to get you started. A typical library package
# exports the main API in this file. Note that you cannot rename this file
# but you can remove it if you wish.
proc add*(x, y: int): int =
## Adds two files together.
return x + y

View File

@@ -0,0 +1,12 @@
# This is just an example to get you started. Users of your library will
# import this file by writing ``import %{ProjectName}/submodule``. Feel free to rename or
# remove this file altogether. You may create additional modules alongside
# this file as required.
type
Submodule* = object
name*: string
proc initSubmodule*(): Submodule =
## Initialises a new ``Submodule`` object.
Submodule(name: "Anonymous")

View File

@@ -0,0 +1 @@
switch("path", "$projectDir/../src")

View File

@@ -0,0 +1,12 @@
# This is just an example to get you started. You may wish to put all of your
# tests into a single file, or separate them into multiple `test1`, `test2`
# etc. files (better names are recommended, just make sure the name starts with
# the letter 't').
#
# To run these tests, simply execute `nimble test`.
import unittest
import %{ProjectName}
test "can add":
check add(5, 5) == 10

View File

@@ -0,0 +1,268 @@
{
"version":1,
"kind":"project",
"id":"Z.NimbleProject",
"category":"I.Projects",
"trDescription":"Creates a Nim application with Nimble.",
"trDisplayName":"Nimble Application",
"trDisplayCategory":"Non-Qt Project",
"featuresRequired":[
"ToolChain.Nim.NimToolChain"
],
"icon":"icon.png",
"enabled":"%{JS: value('Plugins').indexOf('Nim') >= 0 }",
"options":[
{
"key":"ProjectFile",
"value":"%{NimProjectFile}"
},
{
"key":"NimProjectFile",
"value":"%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'nimble')}"
},
{
"key":"NimFileName",
"value":"main.nim"
}
],
"pages":[
{
"trDisplayName":"Project Location",
"trShortTitle":"Location",
"typeId":"Project"
},
{
"trDisplayName":"Define Project Configuration",
"trShortTitle":"Configuration",
"typeId":"Fields",
"data":[
{
"name":"ProjectType",
"trDisplayName":"Type:",
"type":"ComboBox",
"persistenceKey":"ProjectType",
"data":{
"items":[
{
"trKey":"Binary",
"value":"Binary"
},
{
"trKey":"Library",
"value":"Library"
},
{
"trKey":"Hybrid",
"value":"Hybrid"
}
]
}
},
{
"name":"ProjectAuthor",
"trDisplayName":"Author:",
"type":"LineEdit",
"mandatory":true
},
{
"name":"ProjectDescription",
"trDisplayName":"Description:",
"type":"LineEdit",
"mandatory":true
},
{
"name":"ProjectVersion",
"trDisplayName":"Version:",
"type":"LineEdit",
"mandatory":true,
"data":{
"trText":"0.1.0"
}
},
{
"name":"ProjectLicense",
"trDisplayName":"License:",
"type":"ComboBox",
"persistenceKey":"LicenseType",
"data":{
"index":0,
"items":[
{
"trKey":"MIT",
"value":"MIT"
},
{
"trKey":"GPL-2.0",
"value":"GPL-2.0"
},
{
"trKey":"Apache-2.0",
"value":"Apache-2.0"
},
{
"trKey":"ISC",
"value":"ISC"
},
{
"trKey":"GPL-3.0",
"value":"GPL-3.0"
},
{
"trKey":"BSD-3-Clause",
"value":"BSD-3-Clause"
},
{
"trKey":"LGPL-2.1",
"value":"LGPL-2.1"
},
{
"trKey":"LGPL-3.0",
"value":"LGPL-3.0"
},
{
"trKey":"EPL-2.0",
"value":"EPL-2.0"
},
{
"trKey":"Proprietary",
"value":"Proprietary"
},
{
"trKey":"Other",
"value":"Other"
}
]
}
},
{
"name":"ProjectBackend",
"trDisplayName":"Backend:",
"type":"ComboBox",
"persistenceKey":"BackendType",
"data":{
"index":0,
"items":[
{
"trKey":"C",
"value":"c"
},
{
"trKey":"Cpp",
"value":"cpp"
},
{
"trKey":"Objective C",
"value":"objc"
},
{
"trKey":"Javascript",
"value":"js"
}
]
}
},
{
"name":"ProjectNimVersion",
"trDisplayName":"Min Nim Version:",
"type":"LineEdit",
"mandatory":true,
"data":{
"trText":"1.0.0"
}
}
]
},
{
"trDisplayName":"Kit Selection",
"trShortTitle":"Kits",
"typeId":"Kits",
"enabled":"%{JS: !value('IsSubproject')}",
"data":{
"projectFilePath":"%{ProjectFile}"
}
},
{
"trDisplayName":"Project Management",
"trShortTitle":"Summary",
"typeId":"Summary"
}
],
"generators":[
{
"typeId":"File",
"data":[
{
"source":"binary/binary.nimble",
"target":"%{ProjectFile}",
"openAsProject":true,
"condition":"%{JS: value('ProjectType') === 'Binary'}"
},
{
"source":"binary/src/binary.nim",
"target":"%{ProjectDirectory}/src/%{ProjectName}.nim",
"condition":"%{JS: value('ProjectType') === 'Binary'}",
"openInEditor": true
},
{
"source":"hybrid/hybrid.nimble",
"target":"%{ProjectFile}",
"openAsProject":true,
"condition":"%{JS: value('ProjectType') === 'Hybrid'}"
},
{
"source":"hybrid/src/hybrid.nim",
"target":"%{ProjectDirectory}/src/%{ProjectName}.nim",
"condition":"%{JS: value('ProjectType') === 'Hybrid'}",
"openInEditor": true
},
{
"source":"hybrid/src/hybridpkg/submodule.nim",
"target":"%{ProjectDirectory}/src/%{ProjectName}pkg/submodule.nim",
"condition":"%{JS: value('ProjectType') === 'Hybrid'}"
},
{
"source":"hybrid/tests/config.nims",
"target":"%{ProjectDirectory}/tests/config.nims",
"condition":"%{JS: value('ProjectType') === 'Hybrid'}"
},
{
"source":"hybrid/tests/test1.nim",
"target":"%{ProjectDirectory}/tests/test1.nim",
"condition":"%{JS: value('ProjectType') === 'Hybrid'}"
},
{
"source":"library/library.nimble",
"target":"%{ProjectFile}",
"openAsProject":true,
"condition":"%{JS: value('ProjectType') === 'Library'}"
},
{
"source":"library/src/library.nim",
"target":"%{ProjectDirectory}/src/%{ProjectName}.nim",
"condition":"%{JS: value('ProjectType') === 'Library'}",
"openInEditor": true
},
{
"source":"library/src/library/submodule.nim",
"target":"%{ProjectDirectory}/src/%{ProjectName}/submodule.nim",
"condition":"%{JS: value('ProjectType') === 'Library'}"
},
{
"source":"library/tests/config.nims",
"target":"%{ProjectDirectory}/tests/config.nims",
"condition":"%{JS: value('ProjectType') === 'Library'}"
},
{
"source":"library/tests/test1.nim",
"target":"%{ProjectDirectory}/tests/test1.nim",
"condition":"%{JS: value('ProjectType') === 'Library'}"
},
{
"source":"../git.ignore",
"target":"%{ProjectDirectory}/.gitignore",
"condition":"%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}"
}
]
}
]
}

View File

@@ -8,6 +8,14 @@ add_qtc_plugin(Nim
nim.qrc nim.qrc
nimconstants.h nimconstants.h
nimplugin.cpp nimplugin.h nimplugin.cpp nimplugin.h
project/nimblebuildstep.h project/nimblebuildstep.cpp
project/nimblebuildstepwidget.h project/nimblebuildstepwidget.cpp project/nimblebuildstepwidget.ui
project/nimbleproject.h project/nimbleproject.cpp
project/nimblerunconfiguration.h project/nimblerunconfiguration.cpp
project/nimbletaskstep.h project/nimbletaskstep.cpp
project/nimbletaskstepwidget.h project/nimbletaskstepwidget.cpp project/nimbletaskstepwidget.ui
project/nimblebuildsystem.h project/nimblebuildsystem.cpp
project/nimblebuildconfiguration.h project/nimblebuildconfiguration.cpp
project/nimbuildsystem.cpp project/nimbuildsystem.h project/nimbuildsystem.cpp project/nimbuildsystem.h
project/nimbuildconfiguration.cpp project/nimbuildconfiguration.h project/nimbuildconfiguration.cpp project/nimbuildconfiguration.h
project/nimcompilerbuildstep.cpp project/nimcompilerbuildstep.h project/nimcompilerbuildstep.cpp project/nimcompilerbuildstep.h

View File

@@ -34,6 +34,12 @@
\" <glob pattern=\'*.nim\'/>\", \" <glob pattern=\'*.nim\'/>\",
\" </mime-type>\", \" </mime-type>\",
\" <mime-type type=\'text/x-nimble\'>\",
\" <sub-class-of type=\'text/plain\'/>\",
\" <comment>Nimble project file</comment>\",
\" <glob pattern=\'*.nimble\'/>\",
\" </mime-type>\",
\" <mime-type type=\'text/x-nim-script\'>\", \" <mime-type type=\'text/x-nim-script\'>\",
\" <sub-class-of type=\'text/plain\'/>\", \" <sub-class-of type=\'text/plain\'/>\",
\" <comment>Nim script file</comment>\", \" <comment>Nim script file</comment>\",

View File

@@ -14,9 +14,17 @@ HEADERS += \
editor/nimcompletionassistprovider.h \ editor/nimcompletionassistprovider.h \
editor/nimhighlighter.h \ editor/nimhighlighter.h \
editor/nimindenter.h \ editor/nimindenter.h \
project/nimblebuildconfiguration.h \
project/nimblebuildstep.h \
project/nimblebuildstepwidget.h \
project/nimbleproject.h \
project/nimblerunconfiguration.h \
project/nimbletaskstep.h \
project/nimbletaskstepwidget.h \
tools/nimlexer.h \ tools/nimlexer.h \
tools/sourcecodestream.h \ tools/sourcecodestream.h \
project/nimbuildsystem.h \ project/nimbuildsystem.h \
project/nimblebuildsystem.h \
project/nimproject.h \ project/nimproject.h \
project/nimprojectnode.h \ project/nimprojectnode.h \
project/nimbuildconfiguration.h \ project/nimbuildconfiguration.h \
@@ -45,8 +53,16 @@ SOURCES += \
editor/nimcompletionassistprovider.cpp \ editor/nimcompletionassistprovider.cpp \
editor/nimhighlighter.cpp \ editor/nimhighlighter.cpp \
editor/nimindenter.cpp \ editor/nimindenter.cpp \
project/nimblebuildconfiguration.cpp \
project/nimblebuildstep.cpp \
project/nimbletaskstep.cpp \
project/nimblebuildstepwidget.cpp \
project/nimbleproject.cpp \
project/nimblerunconfiguration.cpp \
project/nimbletaskstepwidget.cpp \
tools/nimlexer.cpp \ tools/nimlexer.cpp \
project/nimbuildsystem.cpp \ project/nimbuildsystem.cpp \
project/nimblebuildsystem.cpp \
project/nimproject.cpp \ project/nimproject.cpp \
project/nimprojectnode.cpp \ project/nimprojectnode.cpp \
project/nimbuildconfiguration.cpp \ project/nimbuildconfiguration.cpp \
@@ -69,6 +85,8 @@ SOURCES += \
suggest/server.cpp suggest/server.cpp
FORMS += \ FORMS += \
project/nimblebuildstepwidget.ui \
project/nimbletaskstepwidget.ui \
project/nimcompilerbuildstepconfigwidget.ui \ project/nimcompilerbuildstepconfigwidget.ui \
settings/nimcodestylepreferenceswidget.ui \ settings/nimcodestylepreferenceswidget.ui \
settings/nimtoolssettingswidget.ui settings/nimtoolssettingswidget.ui

View File

@@ -46,6 +46,14 @@ QtcPlugin {
"nimrunconfiguration.h", "nimrunconfiguration.cpp", "nimrunconfiguration.h", "nimrunconfiguration.cpp",
"nimtoolchain.h", "nimtoolchain.cpp", "nimtoolchain.h", "nimtoolchain.cpp",
"nimtoolchainfactory.h", "nimtoolchainfactory.cpp", "nimtoolchainfactory.h", "nimtoolchainfactory.cpp",
"nimblebuildstep.h", "nimblebuildstep.cpp",
"nimblebuildstepwidget.h", "nimblebuildstepwidget.cpp", "nimblebuildstepwidget.ui",
"nimbleproject.h", "nimbleproject.cpp",
"nimblerunconfiguration.h", "nimblerunconfiguration.cpp",
"nimbletaskstep.h", "nimbletaskstep.cpp",
"nimbletaskstepwidget.h", "nimbletaskstepwidget.cpp", "nimbletaskstepwidget.ui",
"nimblebuildsystem.h", "nimblebuildsystem.cpp",
"nimblebuildconfiguration.h", "nimblebuildconfiguration.cpp",
] ]
} }

View File

@@ -32,6 +32,7 @@ namespace Nim {
namespace Constants { namespace Constants {
const char C_NIMPROJECT_ID[] = "Nim.NimProject"; const char C_NIMPROJECT_ID[] = "Nim.NimProject";
const char C_NIMBLEPROJECT_ID[] = "Nim.NimbleProject";
const char C_NIMEDITOR_ID[] = "Nim.NimEditor"; const char C_NIMEDITOR_ID[] = "Nim.NimEditor";
const char C_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "Nim Editor"); const char C_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "Nim Editor");
@@ -39,11 +40,28 @@ const char C_EDITOR_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("OpenWith::Editors", "Nim
const char C_NIMTOOLCHAIN_TYPEID[] = "Nim.NimToolChain"; const char C_NIMTOOLCHAIN_TYPEID[] = "Nim.NimToolChain";
const char C_NIMTOOLCHAIN_COMPILER_COMMAND_KEY[] = "Nim.NimToolChain.CompilerCommand"; const char C_NIMTOOLCHAIN_COMPILER_COMMAND_KEY[] = "Nim.NimToolChain.CompilerCommand";
// NimbleProject
const char C_NIMBLEPROJECT_TASKS[] = "Nim.NimbleProject.Tasks";
const char C_NIMBLEPROJECT_METADATA[] = "Nim.NimbleProject.Metadata";
// NimProject // NimProject
const char C_NIMPROJECT_EXCLUDEDFILES[] = "Nim.NimProjectExcludedFiles"; const char C_NIMPROJECT_EXCLUDEDFILES[] = "Nim.NimProjectExcludedFiles";
// NimBuildConfiguration // NimBuildConfiguration
const char C_NIMBUILDCONFIGURATION_ID[] = "Nim.NimBuildConfiguration"; const char C_NIMBUILDCONFIGURATION_ID[] = "Nim.NimBuildConfiguration";
const char C_NIMBLEBUILDCONFIGURATION_ID[] = "Nim.NimbleBuildConfiguration";
const char C_NIMBLEBUILDCONFIGURATION_BUILDTYPE[] = "Nim.NimbleBuildConfiguration.BuildType";
// NimbleBuildStep
const char C_NIMBLEBUILDSTEP_ID[] = "Nim.NimbleBuildStep";
const char C_NIMBLEBUILDSTEP_DISPLAY[] = QT_TRANSLATE_NOOP("NimbleBuildStep", "Nimble Build");
const char C_NIMBLEBUILDSTEP_ARGUMENTS[] = "Nim.NimbleBuildStep.Arguments";
// NimbleTaskStep
const char C_NIMBLETASKSTEP_ID[] = "Nim.NimbleTaskStep";
const char C_NIMBLETASKSTEP_DISPLAY[] = QT_TRANSLATE_NOOP("NimbleTaskStep", "Nimble Task");
const QString C_NIMBLETASKSTEP_TASKNAME = QStringLiteral("Nim.NimbleTaskStep.TaskName");
const QString C_NIMBLETASKSTEP_TASKARGS = QStringLiteral("Nim.NimbleTaskStep.TaskArgs");
// NimCompilerBuildStep // NimCompilerBuildStep
const char C_NIMCOMPILERBUILDSTEP_ID[] = "Nim.NimCompilerBuildStep"; const char C_NIMCOMPILERBUILDSTEP_ID[] = "Nim.NimCompilerBuildStep";
@@ -92,6 +110,7 @@ const char C_NIMCODESTYLEPREVIEWSNIPPET[] =
* MIME type * MIME type
******************************************************************************/ ******************************************************************************/
const char C_NIM_MIMETYPE[] = "text/x-nim"; const char C_NIM_MIMETYPE[] = "text/x-nim";
const char C_NIMBLE_MIMETYPE[] = "text/x-nimble";
const char C_NIM_SCRIPT_MIMETYPE[] = "text/x-nim-script"; const char C_NIM_SCRIPT_MIMETYPE[] = "text/x-nim-script";
const char C_NIM_MIME_ICON[] = "text-x-nim"; const char C_NIM_MIME_ICON[] = "text-x-nim";
const char C_NIM_PROJECT_MIMETYPE[] = "text/x-nim-project"; const char C_NIM_PROJECT_MIMETYPE[] = "text/x-nim-project";

View File

@@ -28,12 +28,17 @@
#include "nimconstants.h" #include "nimconstants.h"
#include "editor/nimeditorfactory.h" #include "editor/nimeditorfactory.h"
#include "editor/nimhighlighter.h" #include "editor/nimhighlighter.h"
#include "project/nimblerunconfiguration.h"
#include "project/nimblebuildconfiguration.h"
#include "project/nimbuildconfiguration.h" #include "project/nimbuildconfiguration.h"
#include "project/nimcompilerbuildstep.h" #include "project/nimcompilerbuildstep.h"
#include "project/nimcompilercleanstep.h" #include "project/nimcompilercleanstep.h"
#include "project/nimproject.h" #include "project/nimproject.h"
#include "project/nimbleproject.h"
#include "project/nimrunconfiguration.h" #include "project/nimrunconfiguration.h"
#include "project/nimtoolchainfactory.h" #include "project/nimtoolchainfactory.h"
#include "project/nimblebuildstep.h"
#include "project/nimbletaskstep.h"
#include "settings/nimcodestylepreferencesfactory.h" #include "settings/nimcodestylepreferencesfactory.h"
#include "settings/nimcodestylesettingspage.h" #include "settings/nimcodestylesettingspage.h"
#include "settings/nimtoolssettingspage.h" #include "settings/nimtoolssettingspage.h"
@@ -66,12 +71,21 @@ public:
NimSettings settings; NimSettings settings;
NimEditorFactory editorFactory; NimEditorFactory editorFactory;
NimBuildConfigurationFactory buildConfigFactory; NimBuildConfigurationFactory buildConfigFactory;
NimRunConfigurationFactory runConfigFactory; NimbleBuildConfigurationFactory nimbleBuildConfigFactory;
RunWorkerFactory runWorkerFactory{ NimRunConfigurationFactory nimRunConfigFactory;
NimbleRunConfigurationFactory nimbleRunConfigFactory;
RunWorkerFactory nimRunWorkerFactory {
RunWorkerFactory::make<SimpleTargetRunner>(), RunWorkerFactory::make<SimpleTargetRunner>(),
{ProjectExplorer::Constants::NORMAL_RUN_MODE}, {ProjectExplorer::Constants::NORMAL_RUN_MODE},
{runConfigFactory.id()} {nimRunConfigFactory.id()}
}; };
RunWorkerFactory nimbleRunWorkerFactory {
RunWorkerFactory::make<SimpleTargetRunner>(),
{ProjectExplorer::Constants::NORMAL_RUN_MODE},
{nimbleRunConfigFactory.id()}
};
NimbleBuildStepFactory nimbleBuildStepFactory;
NimbleTaskStepFactory nimbleTaskStepFactory;
NimCompilerBuildStepFactory buildStepFactory; NimCompilerBuildStepFactory buildStepFactory;
NimCompilerCleanStepFactory cleanStepFactory; NimCompilerCleanStepFactory cleanStepFactory;
NimCodeStyleSettingsPage codeStyleSettingsPage; NimCodeStyleSettingsPage codeStyleSettingsPage;
@@ -99,6 +113,7 @@ bool NimPlugin::initialize(const QStringList &arguments, QString *errorMessage)
&NimEditorFactory::decorateEditor); &NimEditorFactory::decorateEditor);
ProjectManager::registerProjectType<NimProject>(Constants::C_NIM_PROJECT_MIMETYPE); ProjectManager::registerProjectType<NimProject>(Constants::C_NIM_PROJECT_MIMETYPE);
ProjectManager::registerProjectType<NimbleProject>(Constants::C_NIMBLE_MIMETYPE);
return true; return true;
} }
@@ -112,6 +127,7 @@ void NimPlugin::extensionsInitialized()
if (!icon.isNull()) { if (!icon.isNull()) {
Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_MIMETYPE); Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_MIMETYPE);
Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_SCRIPT_MIMETYPE); Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_SCRIPT_MIMETYPE);
Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIMBLE_MIMETYPE);
} }
} }

View File

@@ -0,0 +1,144 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 "nimblebuildconfiguration.h"
#include "nimconstants.h"
#include "nimblebuildstep.h"
#include "nimbleproject.h"
#include <projectexplorer/buildinfo.h>
#include <projectexplorer/buildstep.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectmacroexpander.h>
#include <utils/fileutils.h>
#include <utils/osspecificaspects.h>
#include <QFileInfo>
#include <QDir>
using namespace Nim;
using namespace ProjectExplorer;
using namespace Utils;
NimbleBuildConfiguration::NimbleBuildConfiguration(Target *target, Core::Id id)
: BuildConfiguration(target, id)
{
setConfigWidgetDisplayName(tr("General"));
setConfigWidgetHasFrame(true);
setBuildDirectorySettingsKey("Nim.NimbleBuildConfiguration.BuildDirectory");
m_nimbleProject = dynamic_cast<NimbleProject*>(project());
QTC_ASSERT(m_nimbleProject, return);
QObject::connect(m_nimbleProject, &NimbleProject::metadataChanged, this, &NimbleBuildConfiguration::updateApplicationTargets);
updateApplicationTargets();
}
BuildConfiguration::BuildType NimbleBuildConfiguration::buildType() const
{
return m_buildType;
}
void NimbleBuildConfiguration::initialize()
{
BuildConfiguration::initialize();
m_buildType = initialBuildType();
setBuildDirectory(project()->projectDirectory());
// Don't add a nimble build step when the package has no binaries (i.e a library package)
if (!m_nimbleProject->metadata().bin.empty())
{
BuildStepList *buildSteps = stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
buildSteps->appendStep(new NimbleBuildStep(buildSteps));
}
}
void NimbleBuildConfiguration::updateApplicationTargets()
{
QTC_ASSERT(m_nimbleProject, return);
const NimbleMetadata &metaData = m_nimbleProject->metadata();
const FilePath &projectDir = project()->projectDirectory();
const FilePath binDir = projectDir.pathAppended(metaData.binDir);
const FilePath srcDir = projectDir.pathAppended("src");
QList<BuildTargetInfo> targets = Utils::transform(metaData.bin, [&](const QString &bin){
BuildTargetInfo info = {};
info.displayName = bin;
info.targetFilePath = binDir.pathAppended(HostOsInfo::withExecutableSuffix(bin));
info.projectFilePath = srcDir.pathAppended(bin).stringAppended(".nim");
info.workingDirectory = binDir;
info.buildKey = bin;
return info;
});
target()->setApplicationTargets(std::move(targets));
}
bool NimbleBuildConfiguration::fromMap(const QVariantMap &map)
{
m_buildType = static_cast<BuildType>(map[Constants::C_NIMBLEBUILDCONFIGURATION_BUILDTYPE].toInt());
return BuildConfiguration::fromMap(map);
}
QVariantMap NimbleBuildConfiguration::toMap() const
{
auto map = BuildConfiguration::toMap();
map[Constants::C_NIMBLEBUILDCONFIGURATION_BUILDTYPE] = buildType();
return map;
}
NimbleBuildConfigurationFactory::NimbleBuildConfigurationFactory()
{
registerBuildConfiguration<NimbleBuildConfiguration>(Constants::C_NIMBLEBUILDCONFIGURATION_ID);
setSupportedProjectType(Constants::C_NIMBLEPROJECT_ID);
setSupportedProjectMimeTypeName(Constants::C_NIMBLE_MIMETYPE);
}
QList<BuildInfo> NimbleBuildConfigurationFactory::availableBuilds(const Kit *k, const Utils::FilePath &projectPath, bool forSetup) const
{
static const QList<BuildConfiguration::BuildType> configurations = {BuildConfiguration::Debug, BuildConfiguration::Release};
return Utils::transform(configurations, [&](BuildConfiguration::BuildType buildType){
BuildInfo info(this);
info.buildType = buildType;
info.kitId = k->id();
if (buildType == BuildConfiguration::Debug)
info.typeName = tr("Debug");
else if (buildType == BuildConfiguration::Release)
info.typeName = tr("Release");
if (forSetup) {
info.displayName = info.typeName;
info.buildDirectory = projectPath.parentDir();
}
return info;
});
}

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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/target.h>
namespace Nim {
class NimbleProject;
class NimbleBuildConfiguration : public ProjectExplorer::BuildConfiguration
{
Q_OBJECT
friend class ProjectExplorer::BuildConfigurationFactory;
NimbleBuildConfiguration(ProjectExplorer::Target *target, Core::Id id);
BuildType buildType() const override;
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
protected:
void initialize() override;
void updateApplicationTargets();
private:
NimbleProject *m_nimbleProject = nullptr;
BuildType m_buildType;
};
class NimbleBuildConfigurationFactory : public ProjectExplorer::BuildConfigurationFactory
{
Q_OBJECT
public:
NimbleBuildConfigurationFactory();
private:
QList<ProjectExplorer::BuildInfo> availableBuilds(const ProjectExplorer::Kit *k,
const Utils::FilePath &projectPath,
bool forSetup) const override;
};
}

View File

@@ -0,0 +1,189 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 "nimblebuildstep.h"
#include "nimblebuildstepwidget.h"
#include "nimbletaskstepwidget.h"
#include "nimconstants.h"
#include "nimbleproject.h"
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/ioutputparser.h>
#include <projectexplorer/processparameters.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <QRegularExpression>
#include <QStandardPaths>
using namespace Nim;
using namespace ProjectExplorer;
using namespace Utils;
namespace {
class NimParser : public IOutputParser
{
public:
void stdOutput(const QString &line) final
{
parseLine(line.trimmed());
IOutputParser::stdOutput(line);
}
void stdError(const QString &line) final
{
parseLine(line.trimmed());
IOutputParser::stdError(line);
}
private:
void parseLine(const QString &line)
{
static QRegularExpression regex("(.+.nim)\\((\\d+), (\\d+)\\) (.+)",
QRegularExpression::OptimizeOnFirstUsageOption);
static QRegularExpression warning("(Warning):(.*)",
QRegularExpression::OptimizeOnFirstUsageOption);
static QRegularExpression error("(Error):(.*)",
QRegularExpression::OptimizeOnFirstUsageOption);
QRegularExpressionMatch match = regex.match(line);
if (!match.hasMatch())
return;
const QString filename = match.captured(1);
bool lineOk = false;
const int lineNumber = match.captured(2).toInt(&lineOk);
const QString message = match.captured(4);
if (!lineOk)
return;
Task::TaskType type = Task::Unknown;
if (warning.match(message).hasMatch())
type = Task::Warning;
else if (error.match(message).hasMatch())
type = Task::Error;
else
return;
Task task(type,
message,
Utils::FilePath::fromUserInput(filename),
lineNumber,
ProjectExplorer::Constants::TASK_CATEGORY_COMPILE);
emit addTask(task);
}
};
}
NimbleBuildStep::NimbleBuildStep(BuildStepList *parentList)
: AbstractProcessStep(parentList, Constants::C_NIMBLEBUILDSTEP_ID)
{
setDefaultDisplayName(tr(Constants::C_NIMBLEBUILDSTEP_DISPLAY));
setDisplayName(tr(Constants::C_NIMBLEBUILDSTEP_DISPLAY));
QTC_ASSERT(buildConfiguration(), return);
QObject::connect(buildConfiguration(), &BuildConfiguration::buildTypeChanged, this, &NimbleBuildStep::resetArguments);
QObject::connect(this, &NimbleBuildStep::argumentsChanged, this, &NimbleBuildStep::onArgumentsChanged);
resetArguments();
}
bool NimbleBuildStep::init()
{
auto parser = new NimParser();
parser->setWorkingDirectory(project()->projectDirectory());
setOutputParser(parser);
ProcessParameters* params = processParameters();
params->setEnvironment(buildConfiguration()->environment());
params->setMacroExpander(buildConfiguration()->macroExpander());
params->setWorkingDirectory(project()->projectDirectory());
params->setCommandLine({QStandardPaths::findExecutable("nimble"), {"build", m_arguments}});
return AbstractProcessStep::init();
}
BuildStepConfigWidget *NimbleBuildStep::createConfigWidget()
{
return new NimbleBuildStepWidget(this);
}
QString NimbleBuildStep::arguments() const
{
return m_arguments;
}
void NimbleBuildStep::setArguments(const QString &args)
{
if (m_arguments == args)
return;
m_arguments = args;
emit argumentsChanged(args);
}
void NimbleBuildStep::resetArguments()
{
setArguments(defaultArguments());
}
bool NimbleBuildStep::fromMap(const QVariantMap &map)
{
m_arguments = map.value(Constants::C_NIMBLEBUILDSTEP_ARGUMENTS, defaultArguments()).toString();
return AbstractProcessStep::fromMap(map);
}
QVariantMap NimbleBuildStep::toMap() const
{
auto map = AbstractProcessStep::toMap();
map[Constants::C_NIMBLEBUILDSTEP_ARGUMENTS] = m_arguments;
return map;
}
QString NimbleBuildStep::defaultArguments() const
{
QTC_ASSERT(buildConfiguration(), return {}; );
switch (buildConfiguration()->buildType()) {
case ProjectExplorer::BuildConfiguration::Debug:
return "--debugger:native";
case ProjectExplorer::BuildConfiguration::Unknown:
case ProjectExplorer::BuildConfiguration::Profile:
case ProjectExplorer::BuildConfiguration::Release:
default:
return "";
}
}
void NimbleBuildStep::onArgumentsChanged()
{
ProcessParameters* params = processParameters();
params->setCommandLine({QStandardPaths::findExecutable("nimble"), {"build", m_arguments}});
}
NimbleBuildStepFactory::NimbleBuildStepFactory()
{
registerStep<NimbleBuildStep>(Constants::C_NIMBLEBUILDSTEP_ID);
setDisplayName(NimbleBuildStep::tr("Nimble Build"));
setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
setSupportedConfiguration(Constants::C_NIMBLEBUILDCONFIGURATION_ID);
setRepeatable(true);
}

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 Nim {
class NimbleBuildStep : public ProjectExplorer::AbstractProcessStep
{
Q_OBJECT
public:
NimbleBuildStep(ProjectExplorer::BuildStepList *parentList);
bool init() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
QString arguments() const;
void setArguments(const QString &args);
void resetArguments();
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
signals:
void argumentsChanged(const QString &args);
private:
QString defaultArguments() const;
void onArgumentsChanged();
QString m_arguments;
};
class NimbleBuildStepFactory : public ProjectExplorer::BuildStepFactory
{
public:
NimbleBuildStepFactory();
};
}

View File

@@ -0,0 +1,58 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 "nimblebuildstepwidget.h"
#include "ui_nimblebuildstepwidget.h"
#include "nimblebuildstep.h"
#include "nimbleproject.h"
#include <QAction>
#include <projectexplorer/buildconfiguration.h>
#include <utils/utilsicons.h>
using namespace Nim;
using namespace ProjectExplorer;
NimbleBuildStepWidget::NimbleBuildStepWidget(NimbleBuildStep *bs)
: BuildStepConfigWidget(bs)
, ui(new Ui::NimbleBuildStepWidget)
{
ui->setupUi(this);
ui->argumentsLineEdit->setText(bs->arguments());
QObject::connect(bs, &NimbleBuildStep::argumentsChanged, ui->argumentsLineEdit, &QLineEdit::setText);
QObject::connect(ui->argumentsLineEdit, &QLineEdit::textEdited, bs, &NimbleBuildStep::setArguments);
ui->resetButton->setIcon(Utils::Icons::RESET.icon());
QObject::connect(ui->resetButton, &QToolButton::triggered, bs, &NimbleBuildStep::resetArguments);
}
NimbleBuildStepWidget::~NimbleBuildStepWidget()
{
delete ui;
}

View File

@@ -0,0 +1,50 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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/buildstep.h>
#include <projectexplorer/buildconfiguration.h>
namespace Nim {
class NimbleBuildStep;
namespace Ui { class NimbleBuildStepWidget; }
class NimbleBuildStepWidget : public ProjectExplorer::BuildStepConfigWidget
{
Q_OBJECT
public:
explicit NimbleBuildStepWidget(NimbleBuildStep *bs);
~NimbleBuildStepWidget();
private:
Ui::NimbleBuildStepWidget *ui;
};
}

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Nim::NimbleBuildStepWidget</class>
<widget class="QWidget" name="Nim::NimbleBuildStepWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>50</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="argumentsLabel">
<property name="text">
<string>Arguments:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="argumentsLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="resetButton">
<property name="toolTip">
<string>Reset to Default</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,149 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 "nimblebuildsystem.h"
#include "nimbleproject.h"
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QProcess>
#include <QStandardPaths>
using namespace Nim;
using namespace ProjectExplorer;
using namespace Utils;
namespace {
std::vector<NimbleTask> parseTasks(const QString &nimblePath, const QString &workingDirectory)
{
QProcess process;
process.setWorkingDirectory(workingDirectory);
process.start(QStandardPaths::findExecutable(nimblePath), {"tasks"});
process.waitForFinished();
std::vector<NimbleTask> result;
QList<QByteArray> lines = process.readAllStandardOutput().split('\n');
lines = Utils::transform(lines, [](const QByteArray &line){ return line.trimmed(); });
Utils::erase(lines, [](const QByteArray &line) { return line.isEmpty(); });
for (const QByteArray &line : lines) {
QList<QByteArray> tokens = line.trimmed().split(' ');
QTC_ASSERT(!tokens.empty(), continue);
QString taskName = QString::fromUtf8(tokens.takeFirst());
QString taskDesc = QString::fromUtf8(tokens.join(' '));
result.push_back({std::move(taskName), std::move(taskDesc)});
}
return result;
}
NimbleMetadata parseMetadata(const QString &nimblePath, const QString &workingDirectory) {
QProcess process;
process.setWorkingDirectory(workingDirectory);
process.start(QStandardPaths::findExecutable(nimblePath), {"dump"});
process.waitForFinished();
NimbleMetadata result = {};
QList<QByteArray> lines = process.readAllStandardOutput().split('\n');
lines = Utils::transform(lines, [](const QByteArray &line){ return line.trimmed(); });
Utils::erase(lines, [](const QByteArray &line) { return line.isEmpty(); });
for (const QByteArray &line : lines) {
QList<QByteArray> tokens = line.trimmed().split(':');
QTC_ASSERT(tokens.size() == 2, continue);
QString name = QString::fromUtf8(tokens.takeFirst()).trimmed();
QString value = QString::fromUtf8(tokens.takeFirst()).trimmed();
QTC_ASSERT(value.size() >= 2, continue);
QTC_ASSERT(value.front() == QChar('"'), continue);
QTC_ASSERT(value.back() == QChar('"'), continue);
value.remove(0, 1);
value.remove(value.size() - 1, 1);
if (name == "binDir")
result.binDir = value;
else if (name == "srcDir")
result.srcDir = value;
else if (name == "bin") {
QStringList bin = value.split(',');
bin = Utils::transform(bin, [](const QString &x){ return x.trimmed(); });
Utils::erase(bin, [](const QString &x) { return x.isEmpty(); });
result.bin = std::move(bin);
}
}
return result;
}
}
NimbleBuildSystem::NimbleBuildSystem(Project *project)
: NimBuildSystem(project)
{
}
void NimbleBuildSystem::parseProject(BuildSystem::ParsingContext &&ctx)
{
NimBuildSystem::parseProject(std::move(ctx));
}
void NimbleBuildSystem::updateProject()
{
updateProjectMetaData();
updateProjectTasks();
}
void NimbleBuildSystem::init()
{
// Not called in parseProject due to nimble behavior to create temporary
// files in project directory. This creation in turn stimulate the fs watcher
// that in turn causes project parsing (thus a loop if invoke in parseProject).
// For this reason we call this function manually during project creation
// See https://github.com/nim-lang/nimble/issues/720
m_directoryWatcher.addFile(project()->projectFilePath().toString(), FileSystemWatcher::WatchModifiedDate);
connect(&m_directoryWatcher, &FileSystemWatcher::fileChanged, this, [this](const QString &path) {
if (path == project()->projectFilePath().toString()) {
updateProject();
}
});
updateProject();
}
void NimbleBuildSystem::updateProjectTasks()
{
auto prj = dynamic_cast<NimbleProject*>(project());
QTC_ASSERT(prj, return);
prj->setTasks(parseTasks(QStandardPaths::findExecutable("nimble"), project()->projectDirectory().toString()));
}
void NimbleBuildSystem::updateProjectMetaData()
{
auto prj = dynamic_cast<NimbleProject*>(project());
QTC_ASSERT(prj, return);
prj->setMetadata(parseMetadata(QStandardPaths::findExecutable("nimble"), project()->projectDirectory().toString()));
}

View File

@@ -0,0 +1,49 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 <nim/project/nimbuildsystem.h>
namespace Nim {
class NimbleBuildSystem : public NimBuildSystem
{
Q_OBJECT
public:
NimbleBuildSystem(ProjectExplorer::Project *project);
void init();
protected:
void parseProject(ParsingContext &&ctx) override;
void updateProject();
void updateProjectTasks();
void updateProjectMetaData();
};
}

View File

@@ -0,0 +1,112 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 "nimbleproject.h"
#include "nimconstants.h"
#include "nimblebuildsystem.h"
#include <coreplugin/icontext.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>
using namespace Nim;
using namespace ProjectExplorer;
NimbleProject::NimbleProject(const Utils::FilePath &fileName)
: ProjectExplorer::Project(Constants::C_NIMBLE_MIMETYPE, fileName)
{
setId(Constants::C_NIMBLEPROJECT_ID);
setDisplayName(fileName.toFileInfo().completeBaseName());
// ensure debugging is enabled (Nim plugin translates nim code to C code)
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
auto bs = std::make_unique<NimbleBuildSystem>(this);
bs->init();
setBuildSystem(std::move(bs));
}
std::vector<NimbleTask> NimbleProject::tasks() const
{
return m_tasks;
}
NimbleMetadata NimbleProject::metadata() const
{
return m_metadata;
}
void NimbleProject::setTasks(std::vector<NimbleTask> tasks)
{
if (tasks == m_tasks)
return;
m_tasks = std::move(tasks);
emit tasksChanged(m_tasks);
}
void NimbleProject::setMetadata(NimbleMetadata metadata)
{
if (m_metadata == metadata)
return;
m_metadata = std::move(metadata);
emit metadataChanged(m_metadata);
}
QVariantMap NimbleProject::toMap() const
{
QVariantMap result = Project::toMap();
result[Constants::C_NIMPROJECT_EXCLUDEDFILES] = static_cast<NimBuildSystem *>(buildSystem())
->excludedFiles();
result[Constants::C_NIMBLEPROJECT_TASKS] = toStringList(m_tasks);
return result;
}
Project::RestoreResult NimbleProject::fromMap(const QVariantMap &map, QString *errorMessage)
{
static_cast<NimBuildSystem *>(buildSystem())
->setExcludedFiles(map.value(Constants::C_NIMPROJECT_EXCLUDEDFILES).toStringList());
Project::RestoreResult result = Project::RestoreResult::Error;
std::tie(result, m_tasks) = fromStringList(map.value(Constants::C_NIMBLEPROJECT_TASKS).toStringList());
return result == Project::RestoreResult::Ok ? Project::fromMap(map, errorMessage) : result;
}
QStringList NimbleProject::toStringList(const std::vector<NimbleTask> &tasks)
{
QStringList result;
for (const NimbleTask &task : tasks) {
result.push_back(task.name);
result.push_back(task.description);
}
return result;
}
std::tuple<Project::RestoreResult, std::vector<NimbleTask>> NimbleProject::fromStringList(const QStringList &list)
{
if (list.size() % 2 != 0)
return {Project::RestoreResult::Error, {}};
std::vector<NimbleTask> result;
for (int i = 0; i < list.size(); i += 2)
result.push_back({list[i], list[i + 1]});
return {Project::RestoreResult::Ok, std::move(result)};
}

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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>
namespace Nim {
struct NimbleTask
{
QString name;
QString description;
bool operator==(const NimbleTask &o) const {
return name == o.name && description == o.description;
}
};
struct NimbleMetadata
{
QStringList bin;
QString binDir;
QString srcDir;
bool operator==(const NimbleMetadata &o) const {
return bin == o.bin && binDir == o.binDir && srcDir == o.srcDir;
}
};
class NimbleProject : public ProjectExplorer::Project
{
Q_OBJECT
public:
NimbleProject(const Utils::FilePath &filename);
std::vector<NimbleTask> tasks() const;
NimbleMetadata metadata() const;
void setTasks(std::vector<NimbleTask> tasks);
void setMetadata(NimbleMetadata metadata);
// Keep for compatibility with Qt Creator 4.10
QVariantMap toMap() const final;
signals:
void tasksChanged(std::vector<NimbleTask>);
void metadataChanged(NimbleMetadata);
protected:
// Keep for compatibility with Qt Creator 4.10
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) final;
private:
static QStringList toStringList(const std::vector<NimbleTask> &tasks);
static std::tuple<RestoreResult, std::vector<NimbleTask>> fromStringList(const QStringList &list);
NimbleMetadata m_metadata;
std::vector<NimbleTask> m_tasks;
};
}

View File

@@ -0,0 +1,110 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 "nimblerunconfiguration.h"
#include "nimconstants.h"
#include "nimbleproject.h"
#include <projectexplorer/localenvironmentaspect.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <utils/algorithm.h>
#include <utils/environment.h>
using namespace Nim;
using namespace ProjectExplorer;
NimbleRunConfiguration::NimbleRunConfiguration(ProjectExplorer::Target *target, Core::Id id)
: RunConfiguration(target, id)
{
auto project = dynamic_cast<NimbleProject*>(target->project());
QTC_ASSERT(project, return);
addAspect<LocalEnvironmentAspect>(target);
addAspect<ExecutableAspect>();
addAspect<ArgumentsAspect>();
addAspect<WorkingDirectoryAspect>();
addAspect<TerminalAspect>();
connect(project, &Project::parsingFinished,
this, &NimbleRunConfiguration::updateTargetInformation);
connect(project, &NimbleProject::metadataChanged,
this, &NimbleRunConfiguration::updateTargetInformation);
connect(project, &NimbleProject::tasksChanged,
this, &NimbleRunConfiguration::updateTargetInformation);
updateTargetInformation();
}
NimbleRunConfiguration::~NimbleRunConfiguration()
{
}
void NimbleRunConfiguration::updateTargetInformation()
{
BuildTargetInfo bti = buildTargetInfo();
setDisplayName(bti.displayName);
setDefaultDisplayName(bti.displayName);
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
}
bool NimbleRunConfiguration::isBuildTargetValid() const
{
return Utils::anyOf(target()->applicationTargets(), [this](const BuildTargetInfo &bti) {
return bti.buildKey == buildKey();
});
}
QString NimbleRunConfiguration::disabledReason() const
{
if (!isBuildTargetValid())
return tr("The project no longer builds the target associated with this run configuration.");
return RunConfiguration::disabledReason();
}
void NimbleRunConfiguration::updateEnabledState()
{
if (!isBuildTargetValid())
setEnabled(false);
else
RunConfiguration::updateEnabledState();
}
NimbleRunConfigurationFactory::NimbleRunConfigurationFactory()
: RunConfigurationFactory()
{
registerRunConfiguration<NimbleRunConfiguration>("Nim.NimbleRunConfiguration");
addSupportedProjectType(Constants::C_NIMBLEPROJECT_ID);
addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
}
QList<RunConfigurationCreationInfo> NimbleRunConfigurationFactory::availableCreators(Target *parent) const
{
return RunConfigurationFactory::availableCreators(parent);
}

View File

@@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2016 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 Nim {
class NimbleRunConfiguration : public ProjectExplorer::RunConfiguration
{
Q_OBJECT
public:
NimbleRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
~NimbleRunConfiguration();
QString disabledReason() const override;
protected:
void updateEnabledState() override;
private:
void updateTargetInformation();
bool isBuildTargetValid() const;
};
class NimbleRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory
{
public:
NimbleRunConfigurationFactory();
protected:
QList<ProjectExplorer::RunConfigurationCreationInfo> availableCreators(ProjectExplorer::Target *parent) const override;
};
}

View File

@@ -0,0 +1,132 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 "nimbletaskstep.h"
#include "nimbletaskstepwidget.h"
#include "nimconstants.h"
#include "nimbleproject.h"
#include <projectexplorer/buildstep.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/processparameters.h>
#include <utils/fileutils.h>
#include <QStandardPaths>
using namespace Nim;
using namespace ProjectExplorer;
NimbleTaskStep::NimbleTaskStep(BuildStepList *parentList)
: AbstractProcessStep(parentList, Constants::C_NIMBLETASKSTEP_ID)
{
setDefaultDisplayName(tr(Constants::C_NIMBLETASKSTEP_DISPLAY));
setDisplayName(tr(Constants::C_NIMBLETASKSTEP_DISPLAY));
}
bool NimbleTaskStep::init()
{
processParameters()->setEnvironment(buildConfiguration()->environment());
processParameters()->setWorkingDirectory(project()->projectDirectory());
return validate() && AbstractProcessStep::init();
}
BuildStepConfigWidget *NimbleTaskStep::createConfigWidget()
{
return new NimbleTaskStepWidget(this);
}
bool NimbleTaskStep::fromMap(const QVariantMap &map)
{
setTaskName(map.value(Constants::C_NIMBLETASKSTEP_TASKNAME, QString()).toString());
setTaskArgs(map.value(Constants::C_NIMBLETASKSTEP_TASKARGS, QString()).toString());
return validate() ? AbstractProcessStep::fromMap(map) : false;
}
QVariantMap NimbleTaskStep::toMap() const
{
QVariantMap result = AbstractProcessStep::toMap();
result[Constants::C_NIMBLETASKSTEP_TASKNAME] = taskName();
result[Constants::C_NIMBLETASKSTEP_TASKARGS] = taskArgs();
return result;
}
void NimbleTaskStep::setTaskName(const QString &name)
{
if (m_taskName == name)
return;
m_taskName = name;
emit taskNameChanged(name);
updateCommandLine();
}
void NimbleTaskStep::setTaskArgs(const QString &args)
{
if (m_taskArgs == args)
return;
m_taskArgs = args;
emit taskArgsChanged(args);
updateCommandLine();
}
void NimbleTaskStep::updateCommandLine()
{
QString args = m_taskName + " " + m_taskArgs;
Utils::CommandLine commandLine(Utils::FilePath::fromString(QStandardPaths::findExecutable("nimble")),
args, Utils::CommandLine::Raw);
processParameters()->setCommandLine(commandLine);
}
bool NimbleTaskStep::validate()
{
if (m_taskName.isEmpty())
return true;
auto nimbleProject = dynamic_cast<NimbleProject*>(project());
QTC_ASSERT(nimbleProject, return false);
if (!Utils::contains(nimbleProject->tasks(), [this](const NimbleTask &task){ return task.name == m_taskName; })) {
emit addTask(Task(Task::Error,
tr("Nimble task %1 not found").arg(m_taskName),
Utils::FilePath(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
emitFaultyConfigurationMessage();
return false;
}
return true;
}
NimbleTaskStepFactory::NimbleTaskStepFactory()
{
registerStep<NimbleTaskStep>(Constants::C_NIMBLETASKSTEP_ID);
setDisplayName(NimbleTaskStep::tr("Nimble Task"));
setSupportedStepLists({ProjectExplorer::Constants::BUILDSTEPS_BUILD,
ProjectExplorer::Constants::BUILDSTEPS_CLEAN,
ProjectExplorer::Constants::BUILDSTEPS_DEPLOY});
setSupportedConfiguration(Constants::C_NIMBLEBUILDCONFIGURATION_ID);
setRepeatable(true);
}

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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/processstep.h>
namespace Nim {
class NimbleTaskStep : public ProjectExplorer::AbstractProcessStep
{
Q_OBJECT
public:
NimbleTaskStep(ProjectExplorer::BuildStepList *parentList);
bool init() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
QString taskName() const { return m_taskName; }
void setTaskName(const QString &name);
QString taskArgs() const { return m_taskArgs; }
void setTaskArgs(const QString &args);
signals:
void taskNameChanged(const QString &name);
void taskArgsChanged(const QString &args);
private:
void updateCommandLine();
bool validate();
QString m_taskName;
QString m_taskArgs;
};
class NimbleTaskStepFactory : public ProjectExplorer::BuildStepFactory
{
public:
NimbleTaskStepFactory();
};
}

View File

@@ -0,0 +1,157 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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 "nimbletaskstepwidget.h"
#include "ui_nimbletaskstepwidget.h"
#include "nimbleproject.h"
#include "nimbletaskstep.h"
#include <utils/algorithm.h>
using namespace Nim;
using namespace ProjectExplorer;
NimbleTaskStepWidget::NimbleTaskStepWidget(NimbleTaskStep *bs)
: BuildStepConfigWidget(bs)
, ui(new Ui::NimbleTaskStepWidget)
{
ui->setupUi(this);
auto project = dynamic_cast<NimbleProject*>(bs->project());
QTC_ASSERT(project, return);
ui->taskList->setModel(&m_tasks);
QObject::connect(&m_tasks, &QAbstractItemModel::dataChanged, this, &NimbleTaskStepWidget::onDataChanged);
updateTaskList(project->tasks());
QObject::connect(project, &NimbleProject::tasksChanged, this, &NimbleTaskStepWidget::updateTaskList);
selectTask(bs->taskName());
QObject::connect(bs, &NimbleTaskStep::taskNameChanged, this, &NimbleTaskStepWidget::selectTask);
QObject::connect(bs, &NimbleTaskStep::taskNameChanged, this, &NimbleTaskStepWidget::recreateSummary);
QObject::connect(this, &NimbleTaskStepWidget::selectedTaskChanged, bs, &NimbleTaskStep::setTaskName);
ui->taskArgumentsLineEdit->setText(bs->taskArgs());
QObject::connect(bs, &NimbleTaskStep::taskArgsChanged, ui->taskArgumentsLineEdit, &QLineEdit::setText);
QObject::connect(bs, &NimbleTaskStep::taskArgsChanged, this, &NimbleTaskStepWidget::recreateSummary);
QObject::connect(ui->taskArgumentsLineEdit, &QLineEdit::textChanged, bs ,&NimbleTaskStep::setTaskArgs);
setSummaryUpdater([this, bs] {
return QString("<b>%1:</b> nimble %2 %3")
.arg(displayName())
.arg(bs->taskName())
.arg(bs->taskArgs());
});
}
NimbleTaskStepWidget::~NimbleTaskStepWidget()
{
delete ui;
}
void NimbleTaskStepWidget::updateTaskList(const std::vector<NimbleTask> &tasks)
{
QSet<QString> newTasks;
for (const NimbleTask &t : tasks)
newTasks.insert(t.name);
QSet<QString> currentTasks;
for (int i = 0; i < m_tasks.rowCount(); ++i)
currentTasks.insert(m_tasks.item(i)->text());
const QSet<QString> added = newTasks - currentTasks;
const QSet<QString> removed = currentTasks - newTasks;
for (const QString &name : added) {
auto item = new QStandardItem();
item->setText(name);
item->setCheckable(true);
item->setCheckState(Qt::Unchecked);
item->setEditable(false);
item->setSelectable(false);
m_tasks.appendRow(item);
}
for (int i = m_tasks.rowCount() - 1; i >= 0; i--)
if (removed.contains(m_tasks.item(i)->text()))
m_tasks.removeRow(i);
m_tasks.sort(0);
}
void NimbleTaskStepWidget::selectTask(const QString &name)
{
if (m_selecting)
return;
m_selecting = true;
QList<QStandardItem*> items = m_tasks.findItems(name);
QStandardItem* item = items.empty() ? nullptr : items.front();
uncheckedAllDifferentFrom(item);
if (item)
item->setCheckState(Qt::Checked);
emit selectedTaskChanged(name);
m_selecting = false;
}
void NimbleTaskStepWidget::onDataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight,
const QVector<int> &roles)
{
QTC_ASSERT(topLeft == bottomRight, return );
if (!roles.contains(Qt::CheckStateRole))
return;
auto item = m_tasks.itemFromIndex(topLeft);
if (!item)
return;
if (m_selecting)
return;
m_selecting = true;
if (item->checkState() == Qt::Checked) {
uncheckedAllDifferentFrom(item);
emit selectedTaskChanged(item->text());
} else if (item->checkState() == Qt::Unchecked) {
emit selectedTaskChanged(QString());
}
m_selecting = false;
}
void NimbleTaskStepWidget::uncheckedAllDifferentFrom(QStandardItem *toSkip)
{
for (int i = 0; i < m_tasks.rowCount(); ++i) {
auto item = m_tasks.item(i);
if (!item || item == toSkip)
continue;
item->setCheckState(Qt::Unchecked);
}
}

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) Filippo Cucchetto <filippocucchetto@gmail.com>
** Contact: http://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/buildstep.h>
#include <nim/project/nimbleproject.h>
#include <QStandardItemModel>
namespace Nim {
class NimbleTaskStep;
namespace Ui { class NimbleTaskStepWidget; }
class NimbleTaskStepWidget : public ProjectExplorer::BuildStepConfigWidget
{
Q_OBJECT
public:
explicit NimbleTaskStepWidget(NimbleTaskStep *buildStep);
~NimbleTaskStepWidget();
signals:
void selectedTaskChanged(const QString &name);
private:
void updateTaskList(const std::vector<NimbleTask> &tasks);
void selectTask(const QString &name);
void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
void uncheckedAllDifferentFrom(QStandardItem *item);
Ui::NimbleTaskStepWidget *ui;
QStandardItemModel m_tasks;
bool m_selecting = false;
};
}

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Nim::NimbleTaskStepWidget</class>
<widget class="QWidget" name="Nim::NimbleTaskStepWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>252</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="taskArgumentsLabel">
<property name="text">
<string>Task arguments:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="taskArgumentsLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="tasksLabel">
<property name="text">
<string>Tasks:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QFrame" name="tasksFrame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListView" name="taskList">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -25,7 +25,7 @@
#include "nimbuildsystem.h" #include "nimbuildsystem.h"
#include "nimproject.h" #include "nimbleproject.h"
#include "nimprojectnode.h" #include "nimprojectnode.h"
#include <utils/algorithm.h> #include <utils/algorithm.h>
@@ -51,12 +51,14 @@ NimBuildSystem::NimBuildSystem(Project *project)
connect(&m_scanner, &TreeScanner::finished, this, &NimBuildSystem::updateProject); connect(&m_scanner, &TreeScanner::finished, this, &NimBuildSystem::updateProject);
m_scanner.setFilter([this](const Utils::MimeType &, const Utils::FilePath &fp) { m_scanner.setFilter([this](const Utils::MimeType &, const Utils::FilePath &fp) {
const QString path = fp.toString(); const QString path = fp.toString();
return excludedFiles().contains(path) || path.endsWith(".nimproject") return excludedFiles().contains(path)
|| path.endsWith(".nimproject")
|| path.contains(".nimproject.user"); || path.contains(".nimproject.user");
}); });
connect(&m_directoryWatcher, &FileSystemWatcher::directoryChanged, this, [this]() { connect(&m_directoryWatcher, &FileSystemWatcher::directoryChanged, this, [this] {
requestParse(); if (!isWaitingForParse())
requestDelayedParse();
}); });
} }
@@ -100,14 +102,14 @@ void NimBuildSystem::parseProject(BuildSystem::ParsingContext &&ctx)
QTC_ASSERT(!m_currentContext.project, return ); QTC_ASSERT(!m_currentContext.project, return );
m_currentContext = std::move(ctx); m_currentContext = std::move(ctx);
QTC_CHECK(m_currentContext.project); QTC_CHECK(m_currentContext.project);
m_scanner.asyncScanForFiles(m_currentContext.project->projectDirectory()); m_scanner.asyncScanForFiles(m_currentContext.project->projectDirectory());
} }
const FilePathList NimBuildSystem::nimFiles() const const FilePathList NimBuildSystem::nimFiles() const
{ {
return project()->files( return project()->files([](const Node *n) {
[](const Node *n) { return Project::AllFiles(n) && n->path().endsWith(".nim"); }); return Project::AllFiles(n) && n->path().endsWith(".nim");
});
} }
void NimBuildSystem::loadSettings() void NimBuildSystem::loadSettings()
@@ -128,23 +130,33 @@ void NimBuildSystem::saveSettings()
void NimBuildSystem::updateProject() void NimBuildSystem::updateProject()
{ {
auto newRoot = std::make_unique<NimProjectNode>(project()->projectDirectory()); // Collect scanned nodes
std::vector<std::unique_ptr<FileNode>> nodes;
QSet<QString> directories;
for (FileNode *node : m_scanner.release()) { for (FileNode *node : m_scanner.release()) {
if (!node->path().endsWith(".nim")) if (!node->path().endsWith(".nim") && !node->path().endsWith(".nimble"))
node->setEnabled(false); // Disable files that do not end in .nim node->setEnabled(false); // Disable files that do not end in .nim
directories.insert(node->directory()); nodes.emplace_back(node);
newRoot->addNestedNode(std::unique_ptr<FileNode>(node));
} }
newRoot->setDisplayName(project()->displayName()); // Sync watched dirs
project()->setRootProjectNode(std::move(newRoot)); const QSet<QString> fsDirs = Utils::transform<QSet>(nodes, &FileNode::directory);
const QSet<QString> projectDirs = m_directoryWatcher.directories().toSet();
m_directoryWatcher.addDirectories(Utils::toList(fsDirs - projectDirs), FileSystemWatcher::WatchAllChanges);
m_directoryWatcher.removeDirectories(Utils::toList(projectDirs - fsDirs));
m_directoryWatcher.addDirectories(Utils::toList(directories), FileSystemWatcher::WatchAllChanges); // Sync project files
const QSet<FilePath> fsFiles = Utils::transform<QSet>(nodes, &FileNode::filePath);
const QSet<FilePath> projectFiles = project()->files([](const Node *n) { return Project::AllFiles(n); }).toSet();
if (fsFiles != projectFiles) {
auto projectNode = std::make_unique<ProjectNode>(project()->projectDirectory());
projectNode->setDisplayName(project()->displayName());
projectNode->addNestedNodes(std::move(nodes));
project()->setRootProjectNode(std::move(projectNode));
}
// Complete scan
m_currentContext.guard.markAsSuccess(); m_currentContext.guard.markAsSuccess();
m_currentContext = {}; m_currentContext = {};
} }

View File

@@ -58,11 +58,11 @@ public:
void setExcludedFiles(const QStringList &list); // Keep for compatibility with Qt Creator 4.10 void setExcludedFiles(const QStringList &list); // Keep for compatibility with Qt Creator 4.10
QStringList excludedFiles(); // Make private when no longer supporting Qt Creator 4.10 QStringList excludedFiles(); // Make private when no longer supporting Qt Creator 4.10
void parseProject(ParsingContext &&ctx) final; void parseProject(ParsingContext &&ctx) override;
const Utils::FilePathList nimFiles() const; const Utils::FilePathList nimFiles() const;
private: protected:
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();