summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo Cucchetto <filippocucchetto@gmail.com>2019-09-16 22:43:27 +0200
committerFilippo Cucchetto <filippocucchetto@gmail.com>2019-11-04 16:35:13 +0000
commitc75c4b2d0ea37e2902ffcc4742c329d679633974 (patch)
tree1db2bcf527f9e9b761bf28cfc83b1402c4419862
parent04f0123c43ab602880da3fd41c9f650882ac39b6 (diff)
downloadqt-creator-c75c4b2d0ea37e2902ffcc4742c329d679633974.tar.gz
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>
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/binary/binary.nimble14
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/binary/src/binary.nim5
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/hybrid/hybrid.nimble15
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/hybrid/src/hybrid.nim7
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/hybrid/src/hybridpkg/submodule.nim6
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/hybrid/tests/config.nims1
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/hybrid/tests/test1.nim12
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/icon.pngbin0 -> 1448 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/icon@2x.pngbin0 -> 2255 bytes
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/library/library.nimble13
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/library/src/library.nim7
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/library/src/library/submodule.nim12
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/library/tests/config.nims1
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/library/tests/test1.nim12
-rw-r--r--share/qtcreator/templates/wizards/projects/nimble/wizard.json268
-rw-r--r--src/plugins/nim/CMakeLists.txt8
-rw-r--r--src/plugins/nim/Nim.json.in10
-rw-r--r--src/plugins/nim/nim.pro18
-rw-r--r--src/plugins/nim/nim.qbs8
-rw-r--r--src/plugins/nim/nimconstants.h19
-rw-r--r--src/plugins/nim/nimplugin.cpp22
-rw-r--r--src/plugins/nim/project/nimblebuildconfiguration.cpp144
-rw-r--r--src/plugins/nim/project/nimblebuildconfiguration.h72
-rw-r--r--src/plugins/nim/project/nimblebuildstep.cpp189
-rw-r--r--src/plugins/nim/project/nimblebuildstep.h70
-rw-r--r--src/plugins/nim/project/nimblebuildstepwidget.cpp58
-rw-r--r--src/plugins/nim/project/nimblebuildstepwidget.h50
-rw-r--r--src/plugins/nim/project/nimblebuildstepwidget.ui45
-rw-r--r--src/plugins/nim/project/nimblebuildsystem.cpp149
-rw-r--r--src/plugins/nim/project/nimblebuildsystem.h49
-rw-r--r--src/plugins/nim/project/nimbleproject.cpp112
-rw-r--r--src/plugins/nim/project/nimbleproject.h88
-rw-r--r--src/plugins/nim/project/nimblerunconfiguration.cpp110
-rw-r--r--src/plugins/nim/project/nimblerunconfiguration.h61
-rw-r--r--src/plugins/nim/project/nimbletaskstep.cpp132
-rw-r--r--src/plugins/nim/project/nimbletaskstep.h75
-rw-r--r--src/plugins/nim/project/nimbletaskstepwidget.cpp157
-rw-r--r--src/plugins/nim/project/nimbletaskstepwidget.h66
-rw-r--r--src/plugins/nim/project/nimbletaskstepwidget.ui82
-rw-r--r--src/plugins/nim/project/nimbuildsystem.cpp50
-rw-r--r--src/plugins/nim/project/nimbuildsystem.h4
41 files changed, 2195 insertions, 26 deletions
diff --git a/share/qtcreator/templates/wizards/projects/nimble/binary/binary.nimble b/share/qtcreator/templates/wizards/projects/nimble/binary/binary.nimble
new file mode 100644
index 0000000000..0cefc9ee70
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/binary/binary.nimble
@@ -0,0 +1,14 @@
+# Package
+
+backend = "%{ProjectBackend}"
+version = "%{ProjectVersion}"
+author = "%{ProjectAuthor}"
+description = "%{ProjectDescription}"
+license = "%{ProjectLicense}"
+srcDir = "src"
+bin = @["%{ProjectName}"]
+
+
+# Dependencies
+
+requires "nim >= %{ProjectNimVersion}"
diff --git a/share/qtcreator/templates/wizards/projects/nimble/binary/src/binary.nim b/share/qtcreator/templates/wizards/projects/nimble/binary/src/binary.nim
new file mode 100644
index 0000000000..862d40c247
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/binary/src/binary.nim
@@ -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!")
diff --git a/share/qtcreator/templates/wizards/projects/nimble/hybrid/hybrid.nimble b/share/qtcreator/templates/wizards/projects/nimble/hybrid/hybrid.nimble
new file mode 100644
index 0000000000..a2604bff21
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/hybrid/hybrid.nimble
@@ -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}"
diff --git a/share/qtcreator/templates/wizards/projects/nimble/hybrid/src/hybrid.nim b/share/qtcreator/templates/wizards/projects/nimble/hybrid/src/hybrid.nim
new file mode 100644
index 0000000000..06dbbf298f
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/hybrid/src/hybrid.nim
@@ -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())
diff --git a/share/qtcreator/templates/wizards/projects/nimble/hybrid/src/hybridpkg/submodule.nim b/share/qtcreator/templates/wizards/projects/nimble/hybrid/src/hybridpkg/submodule.nim
new file mode 100644
index 0000000000..c4185a4c1c
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/hybrid/src/hybridpkg/submodule.nim
@@ -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!"
diff --git a/share/qtcreator/templates/wizards/projects/nimble/hybrid/tests/config.nims b/share/qtcreator/templates/wizards/projects/nimble/hybrid/tests/config.nims
new file mode 100644
index 0000000000..80091ff6c7
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/hybrid/tests/config.nims
@@ -0,0 +1 @@
+switch("path", "$projectDir/../src")
diff --git a/share/qtcreator/templates/wizards/projects/nimble/hybrid/tests/test1.nim b/share/qtcreator/templates/wizards/projects/nimble/hybrid/tests/test1.nim
new file mode 100644
index 0000000000..cabb157e1c
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/hybrid/tests/test1.nim
@@ -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!"
diff --git a/share/qtcreator/templates/wizards/projects/nimble/icon.png b/share/qtcreator/templates/wizards/projects/nimble/icon.png
new file mode 100644
index 0000000000..d3f8575b26
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/icon.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/nimble/icon@2x.png b/share/qtcreator/templates/wizards/projects/nimble/icon@2x.png
new file mode 100644
index 0000000000..bdc8c57055
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/icon@2x.png
Binary files differ
diff --git a/share/qtcreator/templates/wizards/projects/nimble/library/library.nimble b/share/qtcreator/templates/wizards/projects/nimble/library/library.nimble
new file mode 100644
index 0000000000..c2b324d043
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/library/library.nimble
@@ -0,0 +1,13 @@
+# Package
+
+backend = "%{ProjectBackend}"
+version = "%{ProjectVersion}"
+author = "%{ProjectAuthor}"
+description = "%{ProjectDescription}"
+license = "%{ProjectLicense}"
+srcDir = "src"
+
+
+# Dependencies
+
+requires "nim >= %{ProjectNimVersion}"
diff --git a/share/qtcreator/templates/wizards/projects/nimble/library/src/library.nim b/share/qtcreator/templates/wizards/projects/nimble/library/src/library.nim
new file mode 100644
index 0000000000..4b2a2701f0
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/library/src/library.nim
@@ -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
diff --git a/share/qtcreator/templates/wizards/projects/nimble/library/src/library/submodule.nim b/share/qtcreator/templates/wizards/projects/nimble/library/src/library/submodule.nim
new file mode 100644
index 0000000000..e9aef4611d
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/library/src/library/submodule.nim
@@ -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")
diff --git a/share/qtcreator/templates/wizards/projects/nimble/library/tests/config.nims b/share/qtcreator/templates/wizards/projects/nimble/library/tests/config.nims
new file mode 100644
index 0000000000..80091ff6c7
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/library/tests/config.nims
@@ -0,0 +1 @@
+switch("path", "$projectDir/../src")
diff --git a/share/qtcreator/templates/wizards/projects/nimble/library/tests/test1.nim b/share/qtcreator/templates/wizards/projects/nimble/library/tests/test1.nim
new file mode 100644
index 0000000000..47be596a6a
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/library/tests/test1.nim
@@ -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
diff --git a/share/qtcreator/templates/wizards/projects/nimble/wizard.json b/share/qtcreator/templates/wizards/projects/nimble/wizard.json
new file mode 100644
index 0000000000..bef6ee34ea
--- /dev/null
+++ b/share/qtcreator/templates/wizards/projects/nimble/wizard.json
@@ -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'}"
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/plugins/nim/CMakeLists.txt b/src/plugins/nim/CMakeLists.txt
index a26e787578..2601c60288 100644
--- a/src/plugins/nim/CMakeLists.txt
+++ b/src/plugins/nim/CMakeLists.txt
@@ -8,6 +8,14 @@ add_qtc_plugin(Nim
nim.qrc
nimconstants.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/nimbuildconfiguration.cpp project/nimbuildconfiguration.h
project/nimcompilerbuildstep.cpp project/nimcompilerbuildstep.h
diff --git a/src/plugins/nim/Nim.json.in b/src/plugins/nim/Nim.json.in
index b9e5d8709f..a3d98945c3 100644
--- a/src/plugins/nim/Nim.json.in
+++ b/src/plugins/nim/Nim.json.in
@@ -30,13 +30,19 @@
\" <mime-type type=\'text/x-nim\'>\",
\" <sub-class-of type=\'text/plain\'/>\",
- \" <comment>Nim source file </comment>\",
+ \" <comment>Nim source file</comment>\",
\" <glob pattern=\'*.nim\'/>\",
\" </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\'>\",
\" <sub-class-of type=\'text/plain\'/>\",
- \" <comment>Nim script file </comment>\",
+ \" <comment>Nim script file</comment>\",
\" <glob pattern=\'*.nims\'/>\",
\" </mime-type>\",
\"</mime-info>\"
diff --git a/src/plugins/nim/nim.pro b/src/plugins/nim/nim.pro
index 31b2adb173..46869353fb 100644
--- a/src/plugins/nim/nim.pro
+++ b/src/plugins/nim/nim.pro
@@ -14,9 +14,17 @@ HEADERS += \
editor/nimcompletionassistprovider.h \
editor/nimhighlighter.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/sourcecodestream.h \
project/nimbuildsystem.h \
+ project/nimblebuildsystem.h \
project/nimproject.h \
project/nimprojectnode.h \
project/nimbuildconfiguration.h \
@@ -45,8 +53,16 @@ SOURCES += \
editor/nimcompletionassistprovider.cpp \
editor/nimhighlighter.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 \
project/nimbuildsystem.cpp \
+ project/nimblebuildsystem.cpp \
project/nimproject.cpp \
project/nimprojectnode.cpp \
project/nimbuildconfiguration.cpp \
@@ -69,6 +85,8 @@ SOURCES += \
suggest/server.cpp
FORMS += \
+ project/nimblebuildstepwidget.ui \
+ project/nimbletaskstepwidget.ui \
project/nimcompilerbuildstepconfigwidget.ui \
settings/nimcodestylepreferenceswidget.ui \
settings/nimtoolssettingswidget.ui
diff --git a/src/plugins/nim/nim.qbs b/src/plugins/nim/nim.qbs
index 6964993cea..383999f377 100644
--- a/src/plugins/nim/nim.qbs
+++ b/src/plugins/nim/nim.qbs
@@ -46,6 +46,14 @@ QtcPlugin {
"nimrunconfiguration.h", "nimrunconfiguration.cpp",
"nimtoolchain.h", "nimtoolchain.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",
]
}
diff --git a/src/plugins/nim/nimconstants.h b/src/plugins/nim/nimconstants.h
index 03f945689a..61b281fbc7 100644
--- a/src/plugins/nim/nimconstants.h
+++ b/src/plugins/nim/nimconstants.h
@@ -32,6 +32,7 @@ namespace Nim {
namespace Constants {
const char C_NIMPROJECT_ID[] = "Nim.NimProject";
+const char C_NIMBLEPROJECT_ID[] = "Nim.NimbleProject";
const char C_NIMEDITOR_ID[] = "Nim.NimEditor";
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_COMPILER_COMMAND_KEY[] = "Nim.NimToolChain.CompilerCommand";
+// NimbleProject
+const char C_NIMBLEPROJECT_TASKS[] = "Nim.NimbleProject.Tasks";
+const char C_NIMBLEPROJECT_METADATA[] = "Nim.NimbleProject.Metadata";
+
// NimProject
const char C_NIMPROJECT_EXCLUDEDFILES[] = "Nim.NimProjectExcludedFiles";
// 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
const char C_NIMCOMPILERBUILDSTEP_ID[] = "Nim.NimCompilerBuildStep";
@@ -92,6 +110,7 @@ const char C_NIMCODESTYLEPREVIEWSNIPPET[] =
* MIME type
******************************************************************************/
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_MIME_ICON[] = "text-x-nim";
const char C_NIM_PROJECT_MIMETYPE[] = "text/x-nim-project";
diff --git a/src/plugins/nim/nimplugin.cpp b/src/plugins/nim/nimplugin.cpp
index 7740e6096e..152249d4ee 100644
--- a/src/plugins/nim/nimplugin.cpp
+++ b/src/plugins/nim/nimplugin.cpp
@@ -28,12 +28,17 @@
#include "nimconstants.h"
#include "editor/nimeditorfactory.h"
#include "editor/nimhighlighter.h"
+#include "project/nimblerunconfiguration.h"
+#include "project/nimblebuildconfiguration.h"
#include "project/nimbuildconfiguration.h"
#include "project/nimcompilerbuildstep.h"
#include "project/nimcompilercleanstep.h"
#include "project/nimproject.h"
+#include "project/nimbleproject.h"
#include "project/nimrunconfiguration.h"
#include "project/nimtoolchainfactory.h"
+#include "project/nimblebuildstep.h"
+#include "project/nimbletaskstep.h"
#include "settings/nimcodestylepreferencesfactory.h"
#include "settings/nimcodestylesettingspage.h"
#include "settings/nimtoolssettingspage.h"
@@ -66,12 +71,21 @@ public:
NimSettings settings;
NimEditorFactory editorFactory;
NimBuildConfigurationFactory buildConfigFactory;
- NimRunConfigurationFactory runConfigFactory;
- RunWorkerFactory runWorkerFactory{
+ NimbleBuildConfigurationFactory nimbleBuildConfigFactory;
+ NimRunConfigurationFactory nimRunConfigFactory;
+ NimbleRunConfigurationFactory nimbleRunConfigFactory;
+ RunWorkerFactory nimRunWorkerFactory {
RunWorkerFactory::make<SimpleTargetRunner>(),
{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;
NimCompilerCleanStepFactory cleanStepFactory;
NimCodeStyleSettingsPage codeStyleSettingsPage;
@@ -99,6 +113,7 @@ bool NimPlugin::initialize(const QStringList &arguments, QString *errorMessage)
&NimEditorFactory::decorateEditor);
ProjectManager::registerProjectType<NimProject>(Constants::C_NIM_PROJECT_MIMETYPE);
+ ProjectManager::registerProjectType<NimbleProject>(Constants::C_NIMBLE_MIMETYPE);
return true;
}
@@ -112,6 +127,7 @@ void NimPlugin::extensionsInitialized()
if (!icon.isNull()) {
Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_MIMETYPE);
Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_SCRIPT_MIMETYPE);
+ Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIMBLE_MIMETYPE);
}
}
diff --git a/src/plugins/nim/project/nimblebuildconfiguration.cpp b/src/plugins/nim/project/nimblebuildconfiguration.cpp
new file mode 100644
index 0000000000..8b947ce3cc
--- /dev/null
+++ b/src/plugins/nim/project/nimblebuildconfiguration.cpp
@@ -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;
+ });
+}
diff --git a/src/plugins/nim/project/nimblebuildconfiguration.h b/src/plugins/nim/project/nimblebuildconfiguration.h
new file mode 100644
index 0000000000..5ba6b5c218
--- /dev/null
+++ b/src/plugins/nim/project/nimblebuildconfiguration.h
@@ -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;
+};
+
+}
diff --git a/src/plugins/nim/project/nimblebuildstep.cpp b/src/plugins/nim/project/nimblebuildstep.cpp
new file mode 100644
index 0000000000..940c3e91eb
--- /dev/null
+++ b/src/plugins/nim/project/nimblebuildstep.cpp
@@ -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);
+}
diff --git a/src/plugins/nim/project/nimblebuildstep.h b/src/plugins/nim/project/nimblebuildstep.h
new file mode 100644
index 0000000000..e8bcc18253
--- /dev/null
+++ b/src/plugins/nim/project/nimblebuildstep.h
@@ -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();
+};
+
+}
diff --git a/src/plugins/nim/project/nimblebuildstepwidget.cpp b/src/plugins/nim/project/nimblebuildstepwidget.cpp
new file mode 100644
index 0000000000..ad841a4730
--- /dev/null
+++ b/src/plugins/nim/project/nimblebuildstepwidget.cpp
@@ -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;
+}
diff --git a/src/plugins/nim/project/nimblebuildstepwidget.h b/src/plugins/nim/project/nimblebuildstepwidget.h
new file mode 100644
index 0000000000..b367e8319f
--- /dev/null
+++ b/src/plugins/nim/project/nimblebuildstepwidget.h
@@ -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;
+};
+
+}
diff --git a/src/plugins/nim/project/nimblebuildstepwidget.ui b/src/plugins/nim/project/nimblebuildstepwidget.ui
new file mode 100644
index 0000000000..919fdb104b
--- /dev/null
+++ b/src/plugins/nim/project/nimblebuildstepwidget.ui
@@ -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>
diff --git a/src/plugins/nim/project/nimblebuildsystem.cpp b/src/plugins/nim/project/nimblebuildsystem.cpp
new file mode 100644
index 0000000000..c8d0e81d9a
--- /dev/null
+++ b/src/plugins/nim/project/nimblebuildsystem.cpp
@@ -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()));
+}
diff --git a/src/plugins/nim/project/nimblebuildsystem.h b/src/plugins/nim/project/nimblebuildsystem.h
new file mode 100644
index 0000000000..4ffd9185e7
--- /dev/null
+++ b/src/plugins/nim/project/nimblebuildsystem.h
@@ -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();
+};
+
+}
diff --git a/src/plugins/nim/project/nimbleproject.cpp b/src/plugins/nim/project/nimbleproject.cpp
new file mode 100644
index 0000000000..067c647e97
--- /dev/null
+++ b/src/plugins/nim/project/nimbleproject.cpp
@@ -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)};
+}
diff --git a/src/plugins/nim/project/nimbleproject.h b/src/plugins/nim/project/nimbleproject.h
new file mode 100644
index 0000000000..e3c7cf9358
--- /dev/null
+++ b/src/plugins/nim/project/nimbleproject.h
@@ -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;
+};
+
+}
diff --git a/src/plugins/nim/project/nimblerunconfiguration.cpp b/src/plugins/nim/project/nimblerunconfiguration.cpp
new file mode 100644
index 0000000000..4e4748ebd8
--- /dev/null
+++ b/src/plugins/nim/project/nimblerunconfiguration.cpp
@@ -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);
+}
diff --git a/src/plugins/nim/project/nimblerunconfiguration.h b/src/plugins/nim/project/nimblerunconfiguration.h
new file mode 100644
index 0000000000..b273fd4f2b
--- /dev/null
+++ b/src/plugins/nim/project/nimblerunconfiguration.h
@@ -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;
+};
+
+}
diff --git a/src/plugins/nim/project/nimbletaskstep.cpp b/src/plugins/nim/project/nimbletaskstep.cpp
new file mode 100644
index 0000000000..8a6ce49de9
--- /dev/null
+++ b/src/plugins/nim/project/nimbletaskstep.cpp
@@ -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);
+}
diff --git a/src/plugins/nim/project/nimbletaskstep.h b/src/plugins/nim/project/nimbletaskstep.h
new file mode 100644
index 0000000000..47cf507a8d
--- /dev/null
+++ b/src/plugins/nim/project/nimbletaskstep.h
@@ -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();
+};
+
+}
diff --git a/src/plugins/nim/project/nimbletaskstepwidget.cpp b/src/plugins/nim/project/nimbletaskstepwidget.cpp
new file mode 100644
index 0000000000..6d33fdcbe6
--- /dev/null
+++ b/src/plugins/nim/project/nimbletaskstepwidget.cpp
@@ -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);
+ }
+}
diff --git a/src/plugins/nim/project/nimbletaskstepwidget.h b/src/plugins/nim/project/nimbletaskstepwidget.h
new file mode 100644
index 0000000000..73e15dcd05
--- /dev/null
+++ b/src/plugins/nim/project/nimbletaskstepwidget.h
@@ -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;
+};
+
+}
diff --git a/src/plugins/nim/project/nimbletaskstepwidget.ui b/src/plugins/nim/project/nimbletaskstepwidget.ui
new file mode 100644
index 0000000000..223c2ed404
--- /dev/null
+++ b/src/plugins/nim/project/nimbletaskstepwidget.ui
@@ -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>
diff --git a/src/plugins/nim/project/nimbuildsystem.cpp b/src/plugins/nim/project/nimbuildsystem.cpp
index 21b87702ea..740f42dec8 100644
--- a/src/plugins/nim/project/nimbuildsystem.cpp
+++ b/src/plugins/nim/project/nimbuildsystem.cpp
@@ -25,7 +25,7 @@
#include "nimbuildsystem.h"
-#include "nimproject.h"
+#include "nimbleproject.h"
#include "nimprojectnode.h"
#include <utils/algorithm.h>
@@ -51,12 +51,14 @@ NimBuildSystem::NimBuildSystem(Project *project)
connect(&m_scanner, &TreeScanner::finished, this, &NimBuildSystem::updateProject);
m_scanner.setFilter([this](const Utils::MimeType &, const Utils::FilePath &fp) {
const QString path = fp.toString();
- return excludedFiles().contains(path) || path.endsWith(".nimproject")
- || path.contains(".nimproject.user");
+ return excludedFiles().contains(path)
+ || path.endsWith(".nimproject")
+ || path.contains(".nimproject.user");
});
- connect(&m_directoryWatcher, &FileSystemWatcher::directoryChanged, this, [this]() {
- requestParse();
+ connect(&m_directoryWatcher, &FileSystemWatcher::directoryChanged, this, [this] {
+ if (!isWaitingForParse())
+ requestDelayedParse();
});
}
@@ -100,14 +102,14 @@ void NimBuildSystem::parseProject(BuildSystem::ParsingContext &&ctx)
QTC_ASSERT(!m_currentContext.project, return );
m_currentContext = std::move(ctx);
QTC_CHECK(m_currentContext.project);
-
m_scanner.asyncScanForFiles(m_currentContext.project->projectDirectory());
}
const FilePathList NimBuildSystem::nimFiles() const
{
- return project()->files(
- [](const Node *n) { return Project::AllFiles(n) && n->path().endsWith(".nim"); });
+ return project()->files([](const Node *n) {
+ return Project::AllFiles(n) && n->path().endsWith(".nim");
+ });
}
void NimBuildSystem::loadSettings()
@@ -128,23 +130,33 @@ void NimBuildSystem::saveSettings()
void NimBuildSystem::updateProject()
{
- auto newRoot = std::make_unique<NimProjectNode>(project()->projectDirectory());
-
- QSet<QString> directories;
+ // Collect scanned nodes
+ std::vector<std::unique_ptr<FileNode>> nodes;
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
- directories.insert(node->directory());
- newRoot->addNestedNode(std::unique_ptr<FileNode>(node));
+ nodes.emplace_back(node);
}
- newRoot->setDisplayName(project()->displayName());
- project()->setRootProjectNode(std::move(newRoot));
-
- m_directoryWatcher.addDirectories(Utils::toList(directories), FileSystemWatcher::WatchAllChanges);
+ // Sync watched dirs
+ 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));
+
+ // 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 = {};
}
diff --git a/src/plugins/nim/project/nimbuildsystem.h b/src/plugins/nim/project/nimbuildsystem.h
index b725cf4d9d..686bab3aca 100644
--- a/src/plugins/nim/project/nimbuildsystem.h
+++ b/src/plugins/nim/project/nimbuildsystem.h
@@ -58,11 +58,11 @@ public:
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
- void parseProject(ParsingContext &&ctx) final;
+ void parseProject(ParsingContext &&ctx) override;
const Utils::FilePathList nimFiles() const;
-private:
+protected:
void loadSettings();
void saveSettings();